summaryrefslogtreecommitdiff
path: root/packages/cli/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/core')
-rw-r--r--packages/cli/src/core/history-updater.ts241
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,
- ];
- }
- });
-};