mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-17 01:21:10 -07:00
137 lines
3.6 KiB
TypeScript
137 lines
3.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright 2026 Google LLC
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
import {
|
|
type ToolCall,
|
|
type Status as CoreStatus,
|
|
type ToolCallConfirmationDetails,
|
|
type SerializableConfirmationDetails,
|
|
type ToolResultDisplay,
|
|
debugLogger,
|
|
} from '@google/gemini-cli-core';
|
|
import {
|
|
ToolCallStatus,
|
|
type HistoryItemToolGroup,
|
|
type IndividualToolCallDisplay,
|
|
} from '../types.js';
|
|
|
|
import { checkExhaustive } from '@google/gemini-cli-core';
|
|
|
|
export function mapCoreStatusToDisplayStatus(
|
|
coreStatus: CoreStatus,
|
|
): ToolCallStatus {
|
|
switch (coreStatus) {
|
|
case 'validating':
|
|
return ToolCallStatus.Pending;
|
|
case 'awaiting_approval':
|
|
return ToolCallStatus.Confirming;
|
|
case 'executing':
|
|
return ToolCallStatus.Executing;
|
|
case 'success':
|
|
return ToolCallStatus.Success;
|
|
case 'cancelled':
|
|
return ToolCallStatus.Canceled;
|
|
case 'error':
|
|
return ToolCallStatus.Error;
|
|
case 'scheduled':
|
|
return ToolCallStatus.Pending;
|
|
default:
|
|
return checkExhaustive(coreStatus);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 === '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:
|
|
| ToolCallConfirmationDetails
|
|
| SerializableConfirmationDetails
|
|
| undefined = undefined;
|
|
let outputFile: string | undefined = undefined;
|
|
let ptyId: number | undefined = undefined;
|
|
let correlationId: string | undefined = undefined;
|
|
|
|
switch (call.status) {
|
|
case 'success':
|
|
resultDisplay = call.response.resultDisplay;
|
|
outputFile = call.response.outputFile;
|
|
break;
|
|
case 'error':
|
|
case 'cancelled':
|
|
resultDisplay = call.response.resultDisplay;
|
|
break;
|
|
case 'awaiting_approval':
|
|
correlationId = call.correlationId;
|
|
// Pass through details. Context handles dispatch (callback vs bus).
|
|
confirmationDetails = call.confirmationDetails;
|
|
break;
|
|
case 'executing':
|
|
resultDisplay = call.liveOutput;
|
|
ptyId = call.pid;
|
|
break;
|
|
case 'scheduled':
|
|
case 'validating':
|
|
break;
|
|
default: {
|
|
const exhaustiveCheck: never = call;
|
|
debugLogger.warn(
|
|
`Unhandled tool call status in mapper: ${
|
|
(exhaustiveCheck as ToolCall).status
|
|
}`,
|
|
);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return {
|
|
...baseDisplayProperties,
|
|
status: mapCoreStatusToDisplayStatus(call.status),
|
|
resultDisplay,
|
|
confirmationDetails,
|
|
outputFile,
|
|
ptyId,
|
|
correlationId,
|
|
};
|
|
});
|
|
|
|
return {
|
|
type: 'tool_group',
|
|
tools: toolDisplays,
|
|
borderTop,
|
|
borderBottom,
|
|
};
|
|
}
|