mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-14 05:42:54 -07:00
refactor(cli): migrate core tools to native ToolDisplay property and fix UI rendering (#25186)
This commit is contained in:
@@ -236,6 +236,7 @@ export function translateEvent(
|
||||
requestId: event.value.callId,
|
||||
name: event.value.name,
|
||||
args: event.value.args,
|
||||
display: event.value.display,
|
||||
}),
|
||||
);
|
||||
break;
|
||||
@@ -243,13 +244,15 @@ export function translateEvent(
|
||||
case GeminiEventType.ToolCallResponse: {
|
||||
ensureStreamStart(state, out);
|
||||
const data = buildToolResponseData(event.value);
|
||||
const display: ToolDisplay | undefined = event.value.resultDisplay
|
||||
? {
|
||||
result: toolResultDisplayToDisplayContent(
|
||||
event.value.resultDisplay,
|
||||
),
|
||||
}
|
||||
: undefined;
|
||||
const display: ToolDisplay | undefined =
|
||||
event.value.display ??
|
||||
(event.value.resultDisplay
|
||||
? {
|
||||
result: toolResultDisplayToDisplayContent(
|
||||
event.value.resultDisplay,
|
||||
),
|
||||
}
|
||||
: undefined);
|
||||
out.push(
|
||||
makeEvent('tool_response', state, {
|
||||
requestId: event.value.callId,
|
||||
@@ -279,7 +282,6 @@ export function translateEvent(
|
||||
((x: never) => {
|
||||
throw new Error(`Unhandled event type: ${JSON.stringify(x)}`);
|
||||
})(event);
|
||||
break;
|
||||
}
|
||||
|
||||
return out;
|
||||
|
||||
@@ -102,7 +102,10 @@ function makeCompletedToolCall(
|
||||
response: {
|
||||
callId,
|
||||
responseParts: [{ text: responseText }],
|
||||
resultDisplay: undefined,
|
||||
resultDisplay: responseText,
|
||||
display: {
|
||||
result: { type: 'text', text: responseText },
|
||||
},
|
||||
error: undefined,
|
||||
errorType: undefined,
|
||||
},
|
||||
@@ -426,6 +429,12 @@ describe('LegacyAgentSession', () => {
|
||||
(e): e is AgentEvent<'tool_response'> => e.type === 'tool_response',
|
||||
);
|
||||
expect(toolResp?.name).toBe('read_file');
|
||||
expect(toolResp?.display).toEqual(
|
||||
expect.objectContaining({
|
||||
name: 'read_file',
|
||||
result: { type: 'text', text: 'file contents' },
|
||||
}),
|
||||
);
|
||||
expect(toolResp?.content).toEqual([
|
||||
{ type: 'text', text: 'file contents' },
|
||||
]);
|
||||
|
||||
@@ -266,6 +266,7 @@ export class LegacyAgentProtocol implements AgentProtocol {
|
||||
invocation: 'invocation' in tc ? tc.invocation : undefined,
|
||||
resultDisplay: response.resultDisplay,
|
||||
displayName: 'tool' in tc ? tc.tool?.displayName : undefined,
|
||||
display: response.display,
|
||||
});
|
||||
const data = buildToolResponseData(response);
|
||||
|
||||
|
||||
@@ -21,18 +21,21 @@ export function populateToolDisplay({
|
||||
invocation,
|
||||
resultDisplay,
|
||||
displayName,
|
||||
display: prevDisplay,
|
||||
}: {
|
||||
name: string;
|
||||
invocation?: ToolInvocation<object, ToolResult>;
|
||||
resultDisplay?: ToolResultDisplay;
|
||||
displayName?: string;
|
||||
display?: ToolDisplay;
|
||||
}): ToolDisplay {
|
||||
const display: ToolDisplay = {
|
||||
name: displayName || name,
|
||||
description: invocation?.getDescription?.(),
|
||||
...prevDisplay,
|
||||
};
|
||||
|
||||
if (resultDisplay) {
|
||||
if (resultDisplay !== undefined && display.result === undefined) {
|
||||
display.result = toolResultDisplayToDisplayContent(resultDisplay);
|
||||
}
|
||||
|
||||
@@ -91,7 +94,7 @@ export function renderDisplayDiff(diff: DisplayDiff): string {
|
||||
* Useful for fallback displays or non-interactive environments.
|
||||
*/
|
||||
export function displayContentToString(
|
||||
display: DisplayContent | undefined,
|
||||
display: DisplayContent | undefined | null,
|
||||
): string | undefined {
|
||||
if (!display) {
|
||||
return undefined;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type { AnsiOutput } from '../utils/terminalSerializer.js';
|
||||
import type { Kind } from '../tools/tools.js';
|
||||
|
||||
export type WithMeta = { _meta?: Record<string, unknown> };
|
||||
@@ -182,13 +183,48 @@ export type DisplayDiff = {
|
||||
beforeText: string;
|
||||
afterText: string;
|
||||
};
|
||||
export type DisplayContent = DisplayText | DisplayDiff;
|
||||
export type DisplayTerminal = {
|
||||
type: 'terminal';
|
||||
pid?: string;
|
||||
exitCode?: number;
|
||||
ansi?: AnsiOutput;
|
||||
};
|
||||
export type DisplayAgent = {
|
||||
type: 'agent';
|
||||
threadId: string;
|
||||
};
|
||||
|
||||
export type DisplayContent =
|
||||
| DisplayText
|
||||
| DisplayDiff
|
||||
| DisplayTerminal
|
||||
| DisplayAgent;
|
||||
|
||||
export type ToolDisplayFormat =
|
||||
/**
|
||||
* Displays as compact when user has enabled compact tools, box otherwise.
|
||||
* This is the default format if none is selected.
|
||||
**/
|
||||
| 'auto'
|
||||
/** Always display this tool in compact format. */
|
||||
| 'compact'
|
||||
/** Always display this tool in full box format. */
|
||||
| 'box'
|
||||
/** Hide this tool from the event history. */
|
||||
| 'hidden'
|
||||
/** Display this tool as a message-like notice. */
|
||||
| 'notice';
|
||||
|
||||
export interface ToolDisplay {
|
||||
/** A display name for the tool. */
|
||||
name?: string;
|
||||
/** A short description of what the tool is doing. */
|
||||
description?: string;
|
||||
resultSummary?: string;
|
||||
result?: DisplayContent;
|
||||
/** A short, one-line summary of the tool's results. */
|
||||
resultSummary?: string | null;
|
||||
result?: DisplayContent | null;
|
||||
/** A tool may specify its preferred display format. */
|
||||
format?: ToolDisplayFormat;
|
||||
}
|
||||
|
||||
export interface ToolRequest {
|
||||
|
||||
Reference in New Issue
Block a user