diff options
Diffstat (limited to 'packages/cli/src/core')
| -rw-r--r-- | packages/cli/src/core/history-updater.ts | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/packages/cli/src/core/history-updater.ts b/packages/cli/src/core/history-updater.ts deleted file mode 100644 index f56e76ca..00000000 --- a/packages/cli/src/core/history-updater.ts +++ /dev/null @@ -1,241 +0,0 @@ -/** - * @license - * Copyright 2025 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -import { Part } from '@google/genai'; -import { toolRegistry } from '../tools/tool-registry.js'; -import { - HistoryItem, - IndividualToolCallDisplay, - ToolCallEvent, - ToolCallStatus, - ToolConfirmationOutcome, - ToolEditConfirmationDetails, - ToolExecuteConfirmationDetails, -} from '../ui/types.js'; -import { ToolResultDisplay } from '../tools/tools.js'; - -/** - * Processes a tool call chunk and updates the history state accordingly. - * Manages adding new tool groups or updating existing ones. - * Resides here as its primary effect is updating history based on tool events. - */ -export const handleToolCallChunk = ( - chunk: ToolCallEvent, - setHistory: React.Dispatch<React.SetStateAction<HistoryItem[]>>, - submitQuery: (query: Part) => Promise<void>, - getNextMessageId: () => number, - currentToolGroupIdRef: React.MutableRefObject<number | null>, -): void => { - const toolDefinition = toolRegistry.getTool(chunk.name); - const description = toolDefinition?.getDescription - ? toolDefinition.getDescription(chunk.args) - : ''; - const toolDisplayName = toolDefinition?.displayName ?? chunk.name; - let confirmationDetails = chunk.confirmationDetails; - if (confirmationDetails) { - const originalConfirmationDetails = confirmationDetails; - const historyUpdatingConfirm = async (outcome: ToolConfirmationOutcome) => { - originalConfirmationDetails.onConfirm(outcome); - - if (outcome === ToolConfirmationOutcome.Cancel) { - let resultDisplay: ToolResultDisplay | undefined; - if ('fileDiff' in originalConfirmationDetails) { - resultDisplay = { - fileDiff: ( - originalConfirmationDetails as ToolEditConfirmationDetails - ).fileDiff, - }; - } else { - resultDisplay = `~~${(originalConfirmationDetails as ToolExecuteConfirmationDetails).command}~~`; - } - handleToolCallChunk( - { - ...chunk, - status: ToolCallStatus.Error, - confirmationDetails: undefined, - resultDisplay: resultDisplay ?? 'Canceled by user.', - }, - setHistory, - submitQuery, - getNextMessageId, - currentToolGroupIdRef, - ); - const functionResponse: Part = { - functionResponse: { - name: chunk.name, - response: { error: 'User rejected function call.' }, - }, - }; - await submitQuery(functionResponse); - } else { - const tool = toolRegistry.getTool(chunk.name); - if (!tool) { - throw new Error( - `Tool "${chunk.name}" not found or is not registered.`, - ); - } - handleToolCallChunk( - { - ...chunk, - status: ToolCallStatus.Invoked, - resultDisplay: 'Executing...', - confirmationDetails: undefined, - }, - setHistory, - submitQuery, - getNextMessageId, - currentToolGroupIdRef, - ); - const result = await tool.execute(chunk.args); - handleToolCallChunk( - { - ...chunk, - status: ToolCallStatus.Invoked, - resultDisplay: result.returnDisplay, - confirmationDetails: undefined, - }, - setHistory, - submitQuery, - getNextMessageId, - currentToolGroupIdRef, - ); - const functionResponse: Part = { - functionResponse: { - name: chunk.name, - id: chunk.callId, - response: { output: result.llmContent }, - }, - }; - await submitQuery(functionResponse); - } - }; - - confirmationDetails = { - ...originalConfirmationDetails, - onConfirm: historyUpdatingConfirm, - }; - } - const toolDetail: IndividualToolCallDisplay = { - callId: chunk.callId, - name: toolDisplayName, - description, - resultDisplay: chunk.resultDisplay, - status: chunk.status, - confirmationDetails, - }; - - const activeGroupId = currentToolGroupIdRef.current; - setHistory((prev) => { - if (chunk.status === ToolCallStatus.Pending) { - if (activeGroupId === null) { - // Start a new tool group - const newGroupId = getNextMessageId(); - currentToolGroupIdRef.current = newGroupId; - return [ - ...prev, - { - id: newGroupId, - type: 'tool_group', - tools: [toolDetail], - } as HistoryItem, - ]; - } - - // Add to existing tool group - return prev.map((item) => - item.id === activeGroupId && item.type === 'tool_group' - ? item.tools.some((t) => t.callId === toolDetail.callId) - ? item // Tool already listed as pending - : { ...item, tools: [...item.tools, toolDetail] } - : item, - ); - } - - // Update the status of a pending tool within the active group - if (activeGroupId === null) { - // Log if an invoked tool arrives without an active group context - console.warn( - 'Received invoked tool status without an active tool group ID:', - chunk, - ); - return prev; - } - - return prev.map((item) => - item.id === activeGroupId && item.type === 'tool_group' - ? { - ...item, - tools: item.tools.map((t) => - t.callId === toolDetail.callId - ? { ...t, ...toolDetail, status: chunk.status } // Update details & status - : t, - ), - } - : item, - ); - }); -}; - -/** - * Appends an error or informational message to the history, attempting to attach - * it to the last non-user message or creating a new entry. - */ -export const addErrorMessageToHistory = ( - error: DOMException | Error, - setHistory: React.Dispatch<React.SetStateAction<HistoryItem[]>>, - getNextMessageId: () => number, -): void => { - const isAbort = error.name === 'AbortError'; - const errorType = isAbort ? 'info' : 'error'; - const errorText = isAbort - ? '[Request cancelled by user]' - : `[Error: ${error.message || 'Unknown error'}]`; - - setHistory((prev) => { - const reversedHistory = [...prev].reverse(); - // Find the last message that isn't from the user to append the error/info to - const lastBotMessageIndex = reversedHistory.findIndex( - (item) => item.type !== 'user', - ); - const originalIndex = - lastBotMessageIndex !== -1 ? prev.length - 1 - lastBotMessageIndex : -1; - - if (originalIndex !== -1) { - // Append error to the last relevant message - return prev.map((item, index) => { - if (index === originalIndex) { - let baseText = ''; - // Determine base text based on item type - if (item.type === 'gemini') baseText = item.text ?? ''; - else if (item.type === 'tool_group') - baseText = `Tool execution (${item.tools.length} calls)`; - else if (item.type === 'error' || item.type === 'info') - baseText = item.text ?? ''; - // Safely handle potential undefined text - - const updatedText = ( - baseText + - (baseText && !baseText.endsWith('\n') ? '\n' : '') + - errorText - ).trim(); - // Reuse existing ID, update type and text - return { ...item, type: errorType, text: updatedText }; - } - return item; - }); - } else { - // No previous message to append to, add a new error item - return [ - ...prev, - { - id: getNextMessageId(), - type: errorType, - text: errorText, - } as HistoryItem, - ]; - } - }); -}; |
