UNPKG

buroventures-harald-code

Version:

Harald Code - AI-powered coding assistant CLI

185 lines 7.71 kB
/** * @license * Copyright 2025 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { CoreToolScheduler, } from 'buroventures-harald-code-core'; import { useCallback, useState, useMemo } from 'react'; import { ToolCallStatus, } from '../types.js'; export function useReactToolScheduler(onComplete, config, setPendingHistoryItem, getPreferredEditor) { const [toolCallsForDisplay, setToolCallsForDisplay] = useState([]); const outputUpdateHandler = useCallback((toolCallId, outputChunk) => { setPendingHistoryItem((prevItem) => { if (prevItem?.type === 'tool_group') { return { ...prevItem, tools: prevItem.tools.map((toolDisplay) => toolDisplay.callId === toolCallId && toolDisplay.status === ToolCallStatus.Executing ? { ...toolDisplay, resultDisplay: outputChunk } : toolDisplay), }; } return prevItem; }); setToolCallsForDisplay((prevCalls) => prevCalls.map((tc) => { if (tc.request.callId === toolCallId && tc.status === 'executing') { const executingTc = tc; return { ...executingTc, liveOutput: outputChunk }; } return tc; })); }, [setPendingHistoryItem]); const allToolCallsCompleteHandler = useCallback((completedToolCalls) => { onComplete(completedToolCalls); }, [onComplete]); const toolCallsUpdateHandler = useCallback((updatedCoreToolCalls) => { setToolCallsForDisplay((prevTrackedCalls) => updatedCoreToolCalls.map((coreTc) => { const existingTrackedCall = prevTrackedCalls.find((ptc) => ptc.request.callId === coreTc.request.callId); const newTrackedCall = { ...coreTc, responseSubmittedToGemini: existingTrackedCall?.responseSubmittedToGemini ?? false, }; return newTrackedCall; })); }, [setToolCallsForDisplay]); const scheduler = useMemo(() => new CoreToolScheduler({ toolRegistry: config.getToolRegistry(), outputUpdateHandler, onAllToolCallsComplete: allToolCallsCompleteHandler, onToolCallsUpdate: toolCallsUpdateHandler, getPreferredEditor, config, }), [ config, outputUpdateHandler, allToolCallsCompleteHandler, toolCallsUpdateHandler, getPreferredEditor, ]); const schedule = useCallback((request, signal) => { scheduler.schedule(request, signal); }, [scheduler]); const markToolsAsSubmitted = useCallback((callIdsToMark) => { setToolCallsForDisplay((prevCalls) => prevCalls.map((tc) => callIdsToMark.includes(tc.request.callId) ? { ...tc, responseSubmittedToGemini: true } : tc)); }, []); return [toolCallsForDisplay, schedule, markToolsAsSubmitted]; } /** * Maps a CoreToolScheduler status to the UI's ToolCallStatus enum. */ function mapCoreStatusToDisplayStatus(coreStatus) { switch (coreStatus) { case 'validating': return ToolCallStatus.Executing; 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: { const exhaustiveCheck = coreStatus; console.warn(`Unknown core status encountered: ${exhaustiveCheck}`); return ToolCallStatus.Error; } } } /** * Transforms `TrackedToolCall` objects into `HistoryItemToolGroup` objects for UI display. */ export function mapToDisplay(toolOrTools) { const toolCalls = Array.isArray(toolOrTools) ? toolOrTools : [toolOrTools]; const toolDisplays = toolCalls.map((trackedCall) => { let displayName = trackedCall.request.name; let description = ''; let renderOutputAsMarkdown = false; const currentToolInstance = 'tool' in trackedCall && trackedCall.tool ? trackedCall.tool : undefined; if (currentToolInstance) { displayName = currentToolInstance.displayName; description = currentToolInstance.getDescription(trackedCall.request.args); renderOutputAsMarkdown = currentToolInstance.isOutputMarkdown; } else if ('request' in trackedCall && 'args' in trackedCall.request) { description = JSON.stringify(trackedCall.request.args); } const baseDisplayProperties = { callId: trackedCall.request.callId, name: displayName, description, renderOutputAsMarkdown, }; switch (trackedCall.status) { case 'success': return { ...baseDisplayProperties, status: mapCoreStatusToDisplayStatus(trackedCall.status), resultDisplay: trackedCall.response.resultDisplay, confirmationDetails: undefined, }; case 'error': return { ...baseDisplayProperties, name: currentToolInstance?.displayName ?? trackedCall.request.name, status: mapCoreStatusToDisplayStatus(trackedCall.status), resultDisplay: trackedCall.response.resultDisplay, confirmationDetails: undefined, }; case 'cancelled': return { ...baseDisplayProperties, status: mapCoreStatusToDisplayStatus(trackedCall.status), resultDisplay: trackedCall.response.resultDisplay, confirmationDetails: undefined, }; case 'awaiting_approval': return { ...baseDisplayProperties, status: mapCoreStatusToDisplayStatus(trackedCall.status), resultDisplay: undefined, confirmationDetails: trackedCall.confirmationDetails, }; case 'executing': return { ...baseDisplayProperties, status: mapCoreStatusToDisplayStatus(trackedCall.status), resultDisplay: trackedCall.liveOutput ?? undefined, confirmationDetails: undefined, }; case 'validating': // Fallthrough case 'scheduled': return { ...baseDisplayProperties, status: mapCoreStatusToDisplayStatus(trackedCall.status), resultDisplay: undefined, confirmationDetails: undefined, }; default: { const exhaustiveCheck = trackedCall; return { callId: exhaustiveCheck.request.callId, name: 'Unknown Tool', description: 'Encountered an unknown tool call state.', status: ToolCallStatus.Error, resultDisplay: 'Unknown tool call state', confirmationDetails: undefined, renderOutputAsMarkdown: false, }; } } }); return { type: 'tool_group', tools: toolDisplays, }; } //# sourceMappingURL=useReactToolScheduler.js.map