mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 22:21:22 -07:00
109 lines
3.0 KiB
TypeScript
109 lines
3.0 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import {
|
|
type ToolCall,
|
|
type SerializableConfirmationDetails,
|
|
type ToolResultDisplay,
|
|
debugLogger,
|
|
CoreToolCallStatus,
|
|
} from '@google/gemini-cli-core';
|
|
import {
|
|
type HistoryItemToolGroup,
|
|
type IndividualToolCallDisplay,
|
|
} from '../types.js';
|
|
|
|
/**
|
|
* Transforms `ToolCall` objects into `HistoryItemToolGroup` objects for UI
|
|
* display. This is a pure projection layer and does not track interaction
|
|
* state.
|
|
*/
|
|
export function mapToDisplay(
|
|
toolOrTools: ToolCall[] | ToolCall,
|
|
options: { borderTop?: boolean; borderBottom?: boolean } = {},
|
|
): HistoryItemToolGroup {
|
|
const toolCalls = Array.isArray(toolOrTools) ? toolOrTools : [toolOrTools];
|
|
const { borderTop, borderBottom } = options;
|
|
|
|
const toolDisplays = toolCalls.map((call): IndividualToolCallDisplay => {
|
|
let description: string;
|
|
let renderOutputAsMarkdown = false;
|
|
|
|
const displayName = call.tool?.displayName ?? call.request.name;
|
|
|
|
if (call.status === CoreToolCallStatus.Error) {
|
|
description = JSON.stringify(call.request.args);
|
|
} else {
|
|
description = call.invocation.getDescription();
|
|
renderOutputAsMarkdown = call.tool.isOutputMarkdown;
|
|
}
|
|
|
|
const baseDisplayProperties = {
|
|
callId: call.request.callId,
|
|
name: displayName,
|
|
description,
|
|
renderOutputAsMarkdown,
|
|
};
|
|
|
|
let resultDisplay: ToolResultDisplay | undefined = undefined;
|
|
let confirmationDetails: SerializableConfirmationDetails | undefined =
|
|
undefined;
|
|
let outputFile: string | undefined = undefined;
|
|
let ptyId: number | undefined = undefined;
|
|
let correlationId: string | undefined = undefined;
|
|
|
|
switch (call.status) {
|
|
case CoreToolCallStatus.Success:
|
|
resultDisplay = call.response.resultDisplay;
|
|
outputFile = call.response.outputFile;
|
|
break;
|
|
case CoreToolCallStatus.Error:
|
|
case CoreToolCallStatus.Cancelled:
|
|
resultDisplay = call.response.resultDisplay;
|
|
break;
|
|
case CoreToolCallStatus.AwaitingApproval:
|
|
correlationId = call.correlationId;
|
|
// Pass through details. Context handles dispatch (callback vs bus).
|
|
confirmationDetails = call.confirmationDetails;
|
|
break;
|
|
case CoreToolCallStatus.Executing:
|
|
resultDisplay = call.liveOutput;
|
|
ptyId = call.pid;
|
|
break;
|
|
case CoreToolCallStatus.Scheduled:
|
|
case CoreToolCallStatus.Validating:
|
|
break;
|
|
default: {
|
|
const exhaustiveCheck: never = call;
|
|
debugLogger.warn(
|
|
`Unhandled tool call status in mapper: ${
|
|
(exhaustiveCheck as ToolCall).status
|
|
}`,
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return {
|
|
...baseDisplayProperties,
|
|
status: call.status,
|
|
resultDisplay,
|
|
confirmationDetails,
|
|
outputFile,
|
|
ptyId,
|
|
correlationId,
|
|
approvalMode: call.approvalMode,
|
|
};
|
|
});
|
|
|
|
return {
|
|
type: 'tool_group',
|
|
tools: toolDisplays,
|
|
borderTop,
|
|
borderBottom,
|
|
};
|
|
}
|