/** * @license * Copyright 2025 Vybestack LLC * SPDX-License-Identifier: Apache-2.0 */ /** * Manages the agent stream, including user input, command processing, * API interaction, and tool call lifecycle. * * @plan:PLAN-20260211-SESSIONRECORDING.P26 * @pseudocode recording-integration.md lines 100-108 */ import { useMemo } from 'react'; import { type EditorType, type MessageBus, type RecordingIntegration, type AgentRequestInput, } from '@vybestack/llxprt-code-core'; import type { Agent } from '@vybestack/llxprt-code-agents'; import { type LoadedSettings } from '../../../config/settings.js'; import { type HistoryItem, type HistoryItemWithoutId, type SlashCommandProcessorResult, } from '../../types.js'; import { type RemoveHistoryItems, type UseHistoryManagerReturn, } from '../useHistoryManager.js'; import { mergePendingToolGroupsForDisplay } from './streamUtils.js'; import { useCheckpointPersistence } from './checkpointPersistence.js'; import type { useStreamState } from './useStreamState.js'; import type { AgentStreamOrchestrationDeps } from './useAgentStreamOrchestration.js'; import { useAgentStreamOrchestration } from './useAgentStreamOrchestration.js'; import type { StreamRuntime, UiSubagentManager } from '../../cliUiRuntime.js'; import type { OperationLifecycleRegistry } from './operationLifecycle.js'; export const useAgentStream = ( agent: Agent, history: HistoryItem[], addItem: UseHistoryManagerReturn['addItem'], runtime: StreamRuntime, settings: LoadedSettings, onDebugMessage: (message: string) => void, handleSlashCommand: ( cmd: AgentRequestInput, ) => Promise, shellModeActive: boolean, getPreferredEditor: () => EditorType | undefined, onAuthError: () => void, performMemoryRefresh: () => Promise, onEditorClose: () => void, onCancelSubmit: (shouldRestorePrompt?: boolean) => void, setShellInputFocused: (value: boolean) => void, terminalWidth?: number, terminalHeight?: number, onEditorOpen: () => void = () => {}, recordingIntegration?: RecordingIntegration, runtimeMessageBus?: MessageBus, subagentManager?: UiSubagentManager, removeItems?: RemoveHistoryItems, operationLifecycle?: OperationLifecycleRegistry, ) => { const orchestration = useAgentStreamOrchestration({ agent, addItem, removeItems, runtime, settings, onDebugMessage, handleSlashCommand, shellModeActive, getPreferredEditor, onAuthError, performMemoryRefresh, onEditorClose, onCancelSubmit, setShellInputFocused, terminalWidth, terminalHeight, onEditorOpen, recordingIntegration, runtimeMessageBus, subagentManager, operationLifecycle, } satisfies AgentStreamOrchestrationDeps); return useAgentStreamReturn( orchestration, runtime, history, agent, onDebugMessage, ); }; function useAgentStreamReturn( orchestration: ReturnType, runtime: StreamRuntime, history: HistoryItem[], agent: Agent, onDebugMessage: (message: string) => void, ) { const pendingHistoryItems = usePendingHistoryItems( orchestration.st, orchestration.pendingToolCallGroupDisplay, ); useCheckpointPersistence( orchestration.toolCalls, runtime, orchestration.st.gitService, history, agent, runtime.storage, onDebugMessage, ); return { streamingState: orchestration.streamingState, submitQuery: orchestration.submitQuery, sanitizeContent: orchestration.st.sanitizeContent, initError: orchestration.st.initError, pendingHistoryItems, thought: orchestration.st.thought, interactiveRuntimeReady: orchestration.interactiveRuntimeReady, cancelOngoingRequest: orchestration.cancelOngoingRequest, activeShellPtyId: orchestration.activeShellPtyId, lastOutputTime: getLastOutputTime(orchestration), queuedSubmissions: orchestration.queuedSubmissions, clearQueuedSubmissions: orchestration.st.clearSubmissions, sendAllQueuedSubmissions: orchestration.sendAllQueuedSubmissions, steerAllQueuedSubmissions: orchestration.steerAllQueuedSubmissions, }; } function usePendingHistoryItems( st: ReturnType, pendingToolCallGroupDisplay: HistoryItemWithoutId | undefined, ) { return useMemo( () => mergePendingToolGroupsForDisplay( st.pendingHistoryItem, pendingToolCallGroupDisplay, ), [st.pendingHistoryItem, pendingToolCallGroupDisplay], ); } function getLastOutputTime({ lastToolOutputTime, lastShellOutputTime, st, }: ReturnType): number { return Math.max( lastToolOutputTime, lastShellOutputTime, st.lastAgentActivityTime, ); }