@qduc/term2 0.6.1 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent.d.ts +9 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +158 -69
- package/dist/agent.js.map +1 -1
- package/dist/agent.test.js +165 -15
- package/dist/agent.test.js.map +1 -1
- package/dist/app.d.ts +14 -3
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +192 -28
- package/dist/app.js.map +1 -1
- package/dist/app.large-uncached-warning.test.d.ts +2 -0
- package/dist/app.large-uncached-warning.test.d.ts.map +1 -0
- package/dist/app.large-uncached-warning.test.js +15 -0
- package/dist/app.large-uncached-warning.test.js.map +1 -0
- package/dist/app.startup-banner.test.js +3 -19
- package/dist/app.startup-banner.test.js.map +1 -1
- package/dist/cli.integration.test.d.ts +2 -0
- package/dist/cli.integration.test.d.ts.map +1 -0
- package/dist/cli.integration.test.js +102 -0
- package/dist/cli.integration.test.js.map +1 -0
- package/dist/cli.js +158 -71
- package/dist/cli.js.map +1 -1
- package/dist/commands/auto-approve-command.d.ts +10 -0
- package/dist/commands/auto-approve-command.d.ts.map +1 -0
- package/dist/commands/auto-approve-command.js +40 -0
- package/dist/commands/auto-approve-command.js.map +1 -0
- package/dist/commands/clear-command.d.ts +3 -0
- package/dist/commands/clear-command.d.ts.map +1 -0
- package/dist/commands/clear-command.js +12 -0
- package/dist/commands/clear-command.js.map +1 -0
- package/dist/commands/copy-command.d.ts +10 -0
- package/dist/commands/copy-command.d.ts.map +1 -0
- package/dist/commands/copy-command.js +25 -0
- package/dist/commands/copy-command.js.map +1 -0
- package/dist/commands/effort-command.d.ts +11 -0
- package/dist/commands/effort-command.d.ts.map +1 -0
- package/dist/commands/effort-command.js +34 -0
- package/dist/commands/effort-command.js.map +1 -0
- package/dist/commands/guarded-settings-command.d.ts +14 -0
- package/dist/commands/guarded-settings-command.d.ts.map +1 -0
- package/dist/commands/guarded-settings-command.js +23 -0
- package/dist/commands/guarded-settings-command.js.map +1 -0
- package/dist/commands/handoff-command.d.ts +10 -0
- package/dist/commands/handoff-command.d.ts.map +1 -0
- package/dist/commands/handoff-command.js +17 -0
- package/dist/commands/handoff-command.js.map +1 -0
- package/dist/commands/mode-commands.d.ts +32 -0
- package/dist/commands/mode-commands.d.ts.map +1 -0
- package/dist/commands/mode-commands.js +64 -0
- package/dist/commands/mode-commands.js.map +1 -0
- package/dist/commands/model-command.d.ts +11 -0
- package/dist/commands/model-command.d.ts.map +1 -0
- package/dist/commands/model-command.js +35 -0
- package/dist/commands/model-command.js.map +1 -0
- package/dist/commands/quit-command.d.ts +3 -0
- package/dist/commands/quit-command.d.ts.map +1 -0
- package/dist/commands/quit-command.js +10 -0
- package/dist/commands/quit-command.js.map +1 -0
- package/dist/commands/retry-command.d.ts +19 -0
- package/dist/commands/retry-command.d.ts.map +1 -0
- package/dist/commands/retry-command.js +30 -0
- package/dist/commands/retry-command.js.map +1 -0
- package/dist/commands/undo-command.d.ts +15 -0
- package/dist/commands/undo-command.d.ts.map +1 -0
- package/dist/commands/undo-command.js +28 -0
- package/dist/commands/undo-command.js.map +1 -0
- package/dist/commands/usage-command.d.ts +3 -0
- package/dist/commands/usage-command.d.ts.map +1 -0
- package/dist/commands/usage-command.js +11 -0
- package/dist/commands/usage-command.js.map +1 -0
- package/dist/components/Banner.d.ts.map +1 -1
- package/dist/components/Banner.js +35 -17
- package/dist/components/Banner.js.map +1 -1
- package/dist/components/BottomArea.d.ts +10 -1
- package/dist/components/BottomArea.d.ts.map +1 -1
- package/dist/components/BottomArea.js +8 -6
- package/dist/components/BottomArea.js.map +1 -1
- package/dist/components/BottomArea.test.js +14 -1
- package/dist/components/BottomArea.test.js.map +1 -1
- package/dist/components/CommandMessage.d.ts.map +1 -1
- package/dist/components/CommandMessage.js +31 -1
- package/dist/components/CommandMessage.js.map +1 -1
- package/dist/components/CommandMessage.test.js +150 -31
- package/dist/components/CommandMessage.test.js.map +1 -1
- package/dist/components/Common/MenuContainer.d.ts +20 -0
- package/dist/components/Common/MenuContainer.d.ts.map +1 -0
- package/dist/components/Common/MenuContainer.js +52 -0
- package/dist/components/Common/MenuContainer.js.map +1 -0
- package/dist/components/Common/ScrollableTabBar.d.ts +26 -0
- package/dist/components/Common/ScrollableTabBar.d.ts.map +1 -0
- package/dist/components/Common/ScrollableTabBar.js +26 -0
- package/dist/components/Common/ScrollableTabBar.js.map +1 -0
- package/dist/components/Common/compute-visible-tabs.d.ts +16 -0
- package/dist/components/Common/compute-visible-tabs.d.ts.map +1 -0
- package/dist/components/Common/compute-visible-tabs.js +53 -0
- package/dist/components/Common/compute-visible-tabs.js.map +1 -0
- package/dist/components/Common/compute-visible-tabs.test.d.ts +2 -0
- package/dist/components/Common/compute-visible-tabs.test.d.ts.map +1 -0
- package/dist/components/Common/compute-visible-tabs.test.js +97 -0
- package/dist/components/Common/compute-visible-tabs.test.js.map +1 -0
- package/dist/components/HandoffConfirmationPrompt.d.ts +9 -0
- package/dist/components/HandoffConfirmationPrompt.d.ts.map +1 -0
- package/dist/components/HandoffConfirmationPrompt.js +38 -0
- package/dist/components/HandoffConfirmationPrompt.js.map +1 -0
- package/dist/components/HandoffConfirmationPrompt.test.d.ts +2 -0
- package/dist/components/HandoffConfirmationPrompt.test.d.ts.map +1 -0
- package/dist/components/HandoffConfirmationPrompt.test.js +12 -0
- package/dist/components/HandoffConfirmationPrompt.test.js.map +1 -0
- package/dist/components/Input/PopupManager.d.ts +5 -1
- package/dist/components/Input/PopupManager.d.ts.map +1 -1
- package/dist/components/Input/PopupManager.js +2 -2
- package/dist/components/Input/PopupManager.js.map +1 -1
- package/dist/components/Input/popup-key-navigation.js +2 -2
- package/dist/components/Input/popup-key-navigation.js.map +1 -1
- package/dist/components/Input/popup-key-navigation.test.js +5 -3
- package/dist/components/Input/popup-key-navigation.test.js.map +1 -1
- package/dist/components/Input/popup-props.d.ts.map +1 -1
- package/dist/components/Input/popup-props.js +4 -0
- package/dist/components/Input/popup-props.js.map +1 -1
- package/dist/components/Input/popup-props.test.d.ts +2 -0
- package/dist/components/Input/popup-props.test.d.ts.map +1 -0
- package/dist/components/Input/popup-props.test.js +70 -0
- package/dist/components/Input/popup-props.test.js.map +1 -0
- package/dist/components/InputBox.d.ts +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +67 -14
- package/dist/components/InputBox.js.map +1 -1
- package/dist/components/InputBox.test.js +192 -12
- package/dist/components/InputBox.test.js.map +1 -1
- package/dist/components/MessageList.d.ts +1 -0
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/ModelSelectionMenu.d.ts.map +1 -1
- package/dist/components/ModelSelectionMenu.js +29 -125
- package/dist/components/ModelSelectionMenu.js.map +1 -1
- package/dist/components/ModelSelectionMenu.test.js +9 -5
- package/dist/components/ModelSelectionMenu.test.js.map +1 -1
- package/dist/components/PathSelectionMenu.d.ts.map +1 -1
- package/dist/components/PathSelectionMenu.js +15 -55
- package/dist/components/PathSelectionMenu.js.map +1 -1
- package/dist/components/SettingsSelectionMenu.d.ts +4 -1
- package/dist/components/SettingsSelectionMenu.d.ts.map +1 -1
- package/dist/components/SettingsSelectionMenu.js +48 -104
- package/dist/components/SettingsSelectionMenu.js.map +1 -1
- package/dist/components/SettingsSelectionMenu.scroll.test.js +140 -0
- package/dist/components/SettingsSelectionMenu.scroll.test.js.map +1 -1
- package/dist/components/SettingsSelectionMenu.test.js +38 -5
- package/dist/components/SettingsSelectionMenu.test.js.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.d.ts.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.js +24 -51
- package/dist/components/SettingsValueSelectionMenu.js.map +1 -1
- package/dist/components/SlashCommandMenu.d.ts +1 -0
- package/dist/components/SlashCommandMenu.d.ts.map +1 -1
- package/dist/components/SlashCommandMenu.js +11 -14
- package/dist/components/SlashCommandMenu.js.map +1 -1
- package/dist/components/StatusBar.d.ts +6 -0
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +51 -4
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/StatusBar.test.js +47 -0
- package/dist/components/StatusBar.test.js.map +1 -1
- package/dist/components/UndoSelectionMenu.d.ts.map +1 -1
- package/dist/components/UndoSelectionMenu.js +6 -33
- package/dist/components/UndoSelectionMenu.js.map +1 -1
- package/dist/context/InputContext.stability.test.js +9 -7
- package/dist/context/InputContext.stability.test.js.map +1 -1
- package/dist/contracts/conversation.d.ts +3 -0
- package/dist/contracts/conversation.d.ts.map +1 -1
- package/dist/env-setup.js +1 -0
- package/dist/env-setup.js.map +1 -1
- package/dist/hooks/use-app-commands.d.ts +20 -21
- package/dist/hooks/use-app-commands.d.ts.map +1 -1
- package/dist/hooks/use-app-commands.js +65 -330
- package/dist/hooks/use-app-commands.js.map +1 -1
- package/dist/hooks/use-app-commands.test.js +146 -3
- package/dist/hooks/use-app-commands.test.js.map +1 -1
- package/dist/hooks/use-conversation.clear.test.js +61 -8
- package/dist/hooks/use-conversation.clear.test.js.map +1 -1
- package/dist/hooks/use-conversation.d.ts +25 -2
- package/dist/hooks/use-conversation.d.ts.map +1 -1
- package/dist/hooks/use-conversation.js +91 -30
- package/dist/hooks/use-conversation.js.map +1 -1
- package/dist/hooks/use-escape-key.d.ts +8 -1
- package/dist/hooks/use-escape-key.d.ts.map +1 -1
- package/dist/hooks/use-escape-key.js +15 -4
- package/dist/hooks/use-escape-key.js.map +1 -1
- package/dist/hooks/use-escape-key.test.js +135 -28
- package/dist/hooks/use-escape-key.test.js.map +1 -1
- package/dist/hooks/use-input-history.test.js +14 -8
- package/dist/hooks/use-input-history.test.js.map +1 -1
- package/dist/hooks/use-mode-handlers.d.ts +16 -2
- package/dist/hooks/use-mode-handlers.d.ts.map +1 -1
- package/dist/hooks/use-mode-handlers.js +37 -2
- package/dist/hooks/use-mode-handlers.js.map +1 -1
- package/dist/hooks/use-model-selection.d.ts +6 -1
- package/dist/hooks/use-model-selection.d.ts.map +1 -1
- package/dist/hooks/use-model-selection.js +50 -8
- package/dist/hooks/use-model-selection.js.map +1 -1
- package/dist/hooks/use-model-selection.test.js +306 -50
- package/dist/hooks/use-model-selection.test.js.map +1 -1
- package/dist/hooks/use-path-completion.d.ts +4 -0
- package/dist/hooks/use-path-completion.d.ts.map +1 -1
- package/dist/hooks/use-path-completion.js +23 -17
- package/dist/hooks/use-path-completion.js.map +1 -1
- package/dist/hooks/use-runtime-settings.d.ts.map +1 -1
- package/dist/hooks/use-runtime-settings.js +9 -4
- package/dist/hooks/use-runtime-settings.js.map +1 -1
- package/dist/hooks/use-runtime-settings.test.d.ts +2 -0
- package/dist/hooks/use-runtime-settings.test.d.ts.map +1 -0
- package/dist/hooks/use-runtime-settings.test.js +44 -0
- package/dist/hooks/use-runtime-settings.test.js.map +1 -0
- package/dist/hooks/use-selection.d.ts +6 -2
- package/dist/hooks/use-selection.d.ts.map +1 -1
- package/dist/hooks/use-selection.js +53 -16
- package/dist/hooks/use-selection.js.map +1 -1
- package/dist/hooks/use-selection.test.d.ts +2 -0
- package/dist/hooks/use-selection.test.d.ts.map +1 -0
- package/dist/hooks/use-selection.test.js +132 -0
- package/dist/hooks/use-selection.test.js.map +1 -0
- package/dist/hooks/use-settings-completion.d.ts +19 -0
- package/dist/hooks/use-settings-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-completion.js +106 -18
- package/dist/hooks/use-settings-completion.js.map +1 -1
- package/dist/hooks/use-settings-completion.scroll.test.js +68 -29
- package/dist/hooks/use-settings-completion.scroll.test.js.map +1 -1
- package/dist/hooks/use-settings-completion.test.js +36 -1
- package/dist/hooks/use-settings-completion.test.js.map +1 -1
- package/dist/hooks/use-settings-value-completion.d.ts +7 -1
- package/dist/hooks/use-settings-value-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-value-completion.js +18 -7
- package/dist/hooks/use-settings-value-completion.js.map +1 -1
- package/dist/hooks/use-slash-commands.d.ts +5 -0
- package/dist/hooks/use-slash-commands.d.ts.map +1 -1
- package/dist/hooks/use-slash-commands.js +32 -2
- package/dist/hooks/use-slash-commands.js.map +1 -1
- package/dist/hooks/use-slash-commands.test.js +35 -5
- package/dist/hooks/use-slash-commands.test.js.map +1 -1
- package/dist/hooks/use-trigger-detection.test.js +9 -6
- package/dist/hooks/use-trigger-detection.test.js.map +1 -1
- package/dist/hooks/use-undo-selection.d.ts +4 -0
- package/dist/hooks/use-undo-selection.d.ts.map +1 -1
- package/dist/hooks/use-undo-selection.js +20 -1
- package/dist/hooks/use-undo-selection.js.map +1 -1
- package/dist/lib/openai-agent-client.d.ts +10 -3
- package/dist/lib/openai-agent-client.d.ts.map +1 -1
- package/dist/lib/openai-agent-client.flex-tier.test.js +8 -3
- package/dist/lib/openai-agent-client.flex-tier.test.js.map +1 -1
- package/dist/lib/openai-agent-client.js +198 -38
- package/dist/lib/openai-agent-client.js.map +1 -1
- package/dist/lib/openai-agent-client.public-methods.test.js +193 -0
- package/dist/lib/openai-agent-client.public-methods.test.js.map +1 -1
- package/dist/lib/openai-agent-client.test.js +71 -1
- package/dist/lib/openai-agent-client.test.js.map +1 -1
- package/dist/lib/tool-invoke.d.ts +3 -2
- package/dist/lib/tool-invoke.d.ts.map +1 -1
- package/dist/lib/tool-invoke.js +213 -10
- package/dist/lib/tool-invoke.js.map +1 -1
- package/dist/lib/tool-invoke.test.js +103 -0
- package/dist/lib/tool-invoke.test.js.map +1 -1
- package/dist/lib/tool-selection-policy.d.ts.map +1 -1
- package/dist/lib/tool-selection-policy.js +43 -2
- package/dist/lib/tool-selection-policy.js.map +1 -1
- package/dist/lib/tool-selection-policy.test.js +39 -0
- package/dist/lib/tool-selection-policy.test.js.map +1 -1
- package/dist/prompts/codex.md +105 -97
- package/dist/prompts/fragments/gpt-5.3-codex.md +7 -0
- package/dist/prompts/fragments/gpt-5.4-small.md +6 -0
- package/dist/prompts/fragments/gpt-5.4.md +7 -0
- package/dist/prompts/fragments/gpt-5.5.md +7 -0
- package/dist/prompts/gpt-5-modern.md +90 -54
- package/dist/prompts/plan-mode-info.md +14 -3
- package/dist/prompts/prompt-constructor.d.ts +19 -0
- package/dist/prompts/prompt-constructor.d.ts.map +1 -0
- package/dist/prompts/prompt-constructor.js +53 -0
- package/dist/prompts/prompt-constructor.js.map +1 -0
- package/dist/prompts/prompt-constructor.test.d.ts +2 -0
- package/dist/prompts/prompt-constructor.test.d.ts.map +1 -0
- package/dist/prompts/prompt-constructor.test.js +99 -0
- package/dist/prompts/prompt-constructor.test.js.map +1 -0
- package/dist/prompts/prompt-constructor.test.ts +112 -0
- package/dist/prompts/prompt-constructor.ts +91 -0
- package/dist/prompts/prompt-profiles.d.ts +17 -0
- package/dist/prompts/prompt-profiles.d.ts.map +1 -0
- package/dist/prompts/prompt-profiles.js +61 -0
- package/dist/prompts/prompt-profiles.js.map +1 -0
- package/dist/prompts/prompt-profiles.ts +77 -0
- package/dist/prompts/prompt-selector.d.ts.map +1 -1
- package/dist/prompts/prompt-selector.js +3 -21
- package/dist/prompts/prompt-selector.js.map +1 -1
- package/dist/prompts/prompt-selector.ts +3 -25
- package/dist/prompts/reasoning-efficiency.d.ts.map +1 -1
- package/dist/prompts/reasoning-efficiency.js +2 -0
- package/dist/prompts/reasoning-efficiency.js.map +1 -1
- package/dist/prompts/reasoning-efficiency.test.d.ts +2 -0
- package/dist/prompts/reasoning-efficiency.test.d.ts.map +1 -0
- package/dist/prompts/reasoning-efficiency.test.js +11 -0
- package/dist/prompts/reasoning-efficiency.test.js.map +1 -0
- package/dist/prompts/reasoning-efficiency.test.ts +12 -0
- package/dist/prompts/reasoning-efficiency.ts +2 -0
- package/dist/prompts/search-via-shell.d.ts.map +1 -1
- package/dist/prompts/search-via-shell.js +0 -1
- package/dist/prompts/search-via-shell.js.map +1 -1
- package/dist/prompts/search-via-shell.test.js +19 -16
- package/dist/prompts/search-via-shell.test.js.map +1 -1
- package/dist/prompts/search-via-shell.test.ts +20 -16
- package/dist/prompts/search-via-shell.ts +0 -1
- package/dist/prompts/shell-auto-approval.d.ts +2 -2
- package/dist/prompts/shell-auto-approval.d.ts.map +1 -1
- package/dist/prompts/shell-auto-approval.js +6 -6
- package/dist/prompts/shell-auto-approval.js.map +1 -1
- package/dist/prompts/shell-auto-approval.ts +6 -6
- package/dist/prompts/simple-prev.md +55 -0
- package/dist/prompts/simple.md +31 -53
- package/dist/prompts/subagent-delegation.js +2 -2
- package/dist/prompts/subagent-delegation.js.map +1 -1
- package/dist/prompts/subagent-delegation.test.js +12 -10
- package/dist/prompts/subagent-delegation.test.js.map +1 -1
- package/dist/prompts/subagent-delegation.test.ts +13 -10
- package/dist/prompts/subagent-delegation.ts +2 -2
- package/dist/prompts/worktree-hygiene.md +9 -0
- package/dist/providers/ai-sdk-logging-fetch.d.ts.map +1 -1
- package/dist/providers/ai-sdk-logging-fetch.js +78 -3
- package/dist/providers/ai-sdk-logging-fetch.js.map +1 -1
- package/dist/providers/ai-sdk-logging-fetch.test.js +143 -0
- package/dist/providers/ai-sdk-logging-fetch.test.js.map +1 -1
- package/dist/providers/codex-responses-model.d.ts +21 -0
- package/dist/providers/codex-responses-model.d.ts.map +1 -0
- package/dist/providers/codex-responses-model.js +180 -0
- package/dist/providers/codex-responses-model.js.map +1 -0
- package/dist/providers/codex-responses-model.test.d.ts +2 -0
- package/dist/providers/codex-responses-model.test.d.ts.map +1 -0
- package/dist/providers/codex-responses-model.test.js +354 -0
- package/dist/providers/codex-responses-model.test.js.map +1 -0
- package/dist/providers/codex.provider.d.ts +27 -0
- package/dist/providers/codex.provider.d.ts.map +1 -0
- package/dist/providers/codex.provider.js +482 -0
- package/dist/providers/codex.provider.js.map +1 -0
- package/dist/providers/codex.provider.test.d.ts +2 -0
- package/dist/providers/codex.provider.test.d.ts.map +1 -0
- package/dist/providers/codex.provider.test.js +607 -0
- package/dist/providers/codex.provider.test.js.map +1 -0
- package/dist/providers/custom-provider-adapter.test.js +59 -3
- package/dist/providers/custom-provider-adapter.test.js.map +1 -1
- package/dist/providers/fallback-responses-model.d.ts +20 -0
- package/dist/providers/fallback-responses-model.d.ts.map +1 -0
- package/dist/providers/fallback-responses-model.js +346 -0
- package/dist/providers/fallback-responses-model.js.map +1 -0
- package/dist/providers/fallback-responses-model.test.d.ts +2 -0
- package/dist/providers/fallback-responses-model.test.d.ts.map +1 -0
- package/dist/providers/fallback-responses-model.test.js +568 -0
- package/dist/providers/fallback-responses-model.test.js.map +1 -0
- package/dist/providers/fetch/compose.d.ts +7 -0
- package/dist/providers/fetch/compose.d.ts.map +1 -0
- package/dist/providers/fetch/compose.js +20 -0
- package/dist/providers/fetch/compose.js.map +1 -0
- package/dist/providers/fetch/composer.d.ts +13 -0
- package/dist/providers/fetch/composer.d.ts.map +1 -0
- package/dist/providers/fetch/composer.js +15 -0
- package/dist/providers/fetch/composer.js.map +1 -0
- package/dist/providers/fetch/composer.test.d.ts +2 -0
- package/dist/providers/fetch/composer.test.d.ts.map +1 -0
- package/dist/providers/fetch/composer.test.js +448 -0
- package/dist/providers/fetch/composer.test.js.map +1 -0
- package/dist/providers/fetch/logging-middleware.d.ts +16 -0
- package/dist/providers/fetch/logging-middleware.d.ts.map +1 -0
- package/dist/providers/fetch/logging-middleware.js +214 -0
- package/dist/providers/fetch/logging-middleware.js.map +1 -0
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/llama-cpp.provider.d.ts +3 -0
- package/dist/providers/llama-cpp.provider.d.ts.map +1 -0
- package/dist/providers/llama-cpp.provider.js +34 -0
- package/dist/providers/llama-cpp.provider.js.map +1 -0
- package/dist/providers/openai-compatible-middleware.d.ts +7 -0
- package/dist/providers/openai-compatible-middleware.d.ts.map +1 -0
- package/dist/providers/openai-compatible-middleware.js +133 -0
- package/dist/providers/openai-compatible-middleware.js.map +1 -0
- package/dist/providers/openai-compatible-models.d.ts +6 -0
- package/dist/providers/openai-compatible-models.d.ts.map +1 -0
- package/dist/providers/openai-compatible-models.js +17 -0
- package/dist/providers/openai-compatible-models.js.map +1 -0
- package/dist/providers/openai-compatible-response-normalizer.d.ts +7 -0
- package/dist/providers/openai-compatible-response-normalizer.d.ts.map +1 -0
- package/dist/providers/openai-compatible-response-normalizer.js +58 -0
- package/dist/providers/openai-compatible-response-normalizer.js.map +1 -0
- package/dist/providers/openai-compatible.provider.d.ts +6 -3
- package/dist/providers/openai-compatible.provider.d.ts.map +1 -1
- package/dist/providers/openai-compatible.provider.js +71 -327
- package/dist/providers/openai-compatible.provider.js.map +1 -1
- package/dist/providers/openai-compatible.provider.test.js +106 -1
- package/dist/providers/openai-compatible.provider.test.js.map +1 -1
- package/dist/providers/openai.provider.js +44 -10
- package/dist/providers/openai.provider.js.map +1 -1
- package/dist/providers/opencode.provider.d.ts +19 -0
- package/dist/providers/opencode.provider.d.ts.map +1 -0
- package/dist/providers/opencode.provider.js +45 -0
- package/dist/providers/opencode.provider.js.map +1 -0
- package/dist/providers/openrouter.provider.d.ts +2 -3
- package/dist/providers/openrouter.provider.d.ts.map +1 -1
- package/dist/providers/openrouter.provider.js +23 -24
- package/dist/providers/openrouter.provider.js.map +1 -1
- package/dist/providers/openrouter.provider.request-preprocessing.test.js +12 -9
- package/dist/providers/openrouter.provider.request-preprocessing.test.js.map +1 -1
- package/dist/providers/protocol-client.d.ts +17 -0
- package/dist/providers/protocol-client.d.ts.map +1 -0
- package/dist/providers/protocol-client.js +57 -0
- package/dist/providers/protocol-client.js.map +1 -0
- package/dist/providers/protocol-client.test.d.ts +2 -0
- package/dist/providers/protocol-client.test.d.ts.map +1 -0
- package/dist/providers/protocol-client.test.js +55 -0
- package/dist/providers/protocol-client.test.js.map +1 -0
- package/dist/providers/registry.d.ts +1 -0
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/registry.test.js +6 -22
- package/dist/providers/registry.test.js.map +1 -1
- package/dist/providers/timed-responses-ws-model.d.ts +20 -0
- package/dist/providers/timed-responses-ws-model.d.ts.map +1 -0
- package/dist/providers/timed-responses-ws-model.js +381 -0
- package/dist/providers/timed-responses-ws-model.js.map +1 -0
- package/dist/providers/timed-responses-ws-model.test.d.ts +2 -0
- package/dist/providers/timed-responses-ws-model.test.d.ts.map +1 -0
- package/dist/providers/timed-responses-ws-model.test.js +441 -0
- package/dist/providers/timed-responses-ws-model.test.js.map +1 -0
- package/dist/providers/timed-ws-connection.d.ts +26 -0
- package/dist/providers/timed-ws-connection.d.ts.map +1 -0
- package/dist/providers/timed-ws-connection.js +156 -0
- package/dist/providers/timed-ws-connection.js.map +1 -0
- package/dist/providers/timed-ws-connection.test.d.ts +2 -0
- package/dist/providers/timed-ws-connection.test.d.ts.map +1 -0
- package/dist/providers/timed-ws-connection.test.js +223 -0
- package/dist/providers/timed-ws-connection.test.js.map +1 -0
- package/dist/providers/timed-ws-timeouts.d.ts +6 -0
- package/dist/providers/timed-ws-timeouts.d.ts.map +1 -0
- package/dist/providers/timed-ws-timeouts.js +6 -0
- package/dist/providers/timed-ws-timeouts.js.map +1 -0
- package/dist/scripts/eval-auto-approval/dataset.d.ts +2 -2
- package/dist/services/approval-flow-coordinator.d.ts.map +1 -1
- package/dist/services/approval-flow-coordinator.js +17 -1
- package/dist/services/approval-flow-coordinator.js.map +1 -1
- package/dist/services/approval-flow-coordinator.test.js +22 -0
- package/dist/services/approval-flow-coordinator.test.js.map +1 -1
- package/dist/services/command-message-streaming.d.ts.map +1 -1
- package/dist/services/command-message-streaming.js +8 -6
- package/dist/services/command-message-streaming.js.map +1 -1
- package/dist/services/command-message-streaming.test.js +4 -2
- package/dist/services/command-message-streaming.test.js.map +1 -1
- package/dist/services/conversation-clear-save.test.js +37 -66
- package/dist/services/conversation-clear-save.test.js.map +1 -1
- package/dist/services/conversation-events.d.ts +48 -1
- package/dist/services/conversation-events.d.ts.map +1 -1
- package/dist/services/conversation-history-repair.d.ts.map +1 -1
- package/dist/services/conversation-history-repair.js +81 -26
- package/dist/services/conversation-history-repair.js.map +1 -1
- package/dist/services/conversation-integration.test.js +112 -1
- package/dist/services/conversation-integration.test.js.map +1 -1
- package/dist/services/conversation-log-events.d.ts +113 -0
- package/dist/services/conversation-log-events.d.ts.map +1 -0
- package/dist/services/conversation-log-events.js +12 -0
- package/dist/services/conversation-log-events.js.map +1 -0
- package/dist/services/conversation-log-writer.d.ts +40 -0
- package/dist/services/conversation-log-writer.d.ts.map +1 -0
- package/dist/services/conversation-log-writer.js +264 -0
- package/dist/services/conversation-log-writer.js.map +1 -0
- package/dist/services/conversation-persistence-types.d.ts +46 -0
- package/dist/services/conversation-persistence-types.d.ts.map +1 -0
- package/dist/services/conversation-persistence-types.js +2 -0
- package/dist/services/conversation-persistence-types.js.map +1 -0
- package/dist/services/conversation-persistence.d.ts +44 -39
- package/dist/services/conversation-persistence.d.ts.map +1 -1
- package/dist/services/conversation-persistence.js +273 -83
- package/dist/services/conversation-persistence.js.map +1 -1
- package/dist/services/conversation-persistence.test.js +708 -624
- package/dist/services/conversation-persistence.test.js.map +1 -1
- package/dist/services/conversation-replay.d.ts +26 -0
- package/dist/services/conversation-replay.d.ts.map +1 -0
- package/dist/services/conversation-replay.js +460 -0
- package/dist/services/conversation-replay.js.map +1 -0
- package/dist/services/conversation-replay.test.d.ts +2 -0
- package/dist/services/conversation-replay.test.d.ts.map +1 -0
- package/dist/services/conversation-replay.test.js +492 -0
- package/dist/services/conversation-replay.test.js.map +1 -0
- package/dist/services/conversation-result-builder.d.ts +2 -0
- package/dist/services/conversation-result-builder.d.ts.map +1 -1
- package/dist/services/conversation-result-builder.js +12 -2
- package/dist/services/conversation-result-builder.js.map +1 -1
- package/dist/services/conversation-result-builder.test.js +179 -0
- package/dist/services/conversation-result-builder.test.js.map +1 -1
- package/dist/services/conversation-retry-policy.d.ts +17 -0
- package/dist/services/conversation-retry-policy.d.ts.map +1 -1
- package/dist/services/conversation-retry-policy.js +38 -5
- package/dist/services/conversation-retry-policy.js.map +1 -1
- package/dist/services/conversation-retry-policy.test.js +60 -1
- package/dist/services/conversation-retry-policy.test.js.map +1 -1
- package/dist/services/conversation-service.d.ts +12 -3
- package/dist/services/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation-service.js +18 -3
- package/dist/services/conversation-service.js.map +1 -1
- package/dist/services/conversation-session.d.ts +23 -7
- package/dist/services/conversation-session.d.ts.map +1 -1
- package/dist/services/conversation-session.js +620 -67
- package/dist/services/conversation-session.js.map +1 -1
- package/dist/services/conversation-store.d.ts +16 -13
- package/dist/services/conversation-store.d.ts.map +1 -1
- package/dist/services/conversation-store.js +62 -191
- package/dist/services/conversation-store.js.map +1 -1
- package/dist/services/conversation-store.merge-modes.removed.d.ts +2 -0
- package/dist/services/conversation-store.merge-modes.removed.d.ts.map +1 -0
- package/dist/services/conversation-store.merge-modes.removed.js +2 -0
- package/dist/services/conversation-store.merge-modes.removed.js.map +1 -0
- package/dist/services/conversation-store.merge-modes.test.d.ts +2 -0
- package/dist/services/conversation-store.merge-modes.test.d.ts.map +1 -0
- package/dist/services/conversation-store.merge-modes.test.js +2 -0
- package/dist/services/conversation-store.merge-modes.test.js.map +1 -0
- package/dist/services/conversation-store.test.js +157 -294
- package/dist/services/conversation-store.test.js.map +1 -1
- package/dist/services/conversation-turn-items.d.ts +5 -0
- package/dist/services/conversation-turn-items.d.ts.map +1 -0
- package/dist/services/conversation-turn-items.js +351 -0
- package/dist/services/conversation-turn-items.js.map +1 -0
- package/dist/services/conversation-turn-items.test.d.ts +2 -0
- package/dist/services/conversation-turn-items.test.d.ts.map +1 -0
- package/dist/services/conversation-turn-items.test.js +68 -0
- package/dist/services/conversation-turn-items.test.js.map +1 -0
- package/dist/services/input-surge-guard.d.ts +4 -0
- package/dist/services/input-surge-guard.d.ts.map +1 -1
- package/dist/services/input-surge-guard.js +2 -2
- package/dist/services/input-surge-guard.js.map +1 -1
- package/dist/services/input-surge-guard.test.js +15 -1
- package/dist/services/input-surge-guard.test.js.map +1 -1
- package/dist/services/large-uncached-input-guard.d.ts +35 -0
- package/dist/services/large-uncached-input-guard.d.ts.map +1 -0
- package/dist/services/large-uncached-input-guard.js +127 -0
- package/dist/services/large-uncached-input-guard.js.map +1 -0
- package/dist/services/large-uncached-input-guard.test.d.ts +2 -0
- package/dist/services/large-uncached-input-guard.test.d.ts.map +1 -0
- package/dist/services/large-uncached-input-guard.test.js +160 -0
- package/dist/services/large-uncached-input-guard.test.js.map +1 -0
- package/dist/services/model-service.d.ts +2 -0
- package/dist/services/model-service.d.ts.map +1 -1
- package/dist/services/model-service.js +7 -0
- package/dist/services/model-service.js.map +1 -1
- package/dist/services/provider-traffic.d.ts.map +1 -1
- package/dist/services/provider-traffic.js +82 -24
- package/dist/services/provider-traffic.js.map +1 -1
- package/dist/services/provider-traffic.test.js +98 -6
- package/dist/services/provider-traffic.test.js.map +1 -1
- package/dist/services/repro-error.test.d.ts +2 -0
- package/dist/services/repro-error.test.d.ts.map +1 -0
- package/dist/services/repro-error.test.js +38 -0
- package/dist/services/repro-error.test.js.map +1 -0
- package/dist/services/rtk-service.d.ts.map +1 -1
- package/dist/services/rtk-service.js +1 -2
- package/dist/services/rtk-service.js.map +1 -1
- package/dist/services/settings-schema.d.ts +36 -28
- package/dist/services/settings-schema.d.ts.map +1 -1
- package/dist/services/settings-schema.js +7 -2
- package/dist/services/settings-schema.js.map +1 -1
- package/dist/services/settings-sources.d.ts.map +1 -1
- package/dist/services/settings-sources.js +1 -0
- package/dist/services/settings-sources.js.map +1 -1
- package/dist/services/stream-event-processor.d.ts +4 -0
- package/dist/services/stream-event-processor.d.ts.map +1 -1
- package/dist/services/stream-event-processor.js +78 -39
- package/dist/services/stream-event-processor.js.map +1 -1
- package/dist/services/stream-event-processor.test.js +71 -0
- package/dist/services/stream-event-processor.test.js.map +1 -1
- package/dist/services/subagents/subagent-manager.d.ts.map +1 -1
- package/dist/services/subagents/subagent-manager.js +120 -46
- package/dist/services/subagents/subagent-manager.js.map +1 -1
- package/dist/services/subagents/subagent-manager.test.js +361 -11
- package/dist/services/subagents/subagent-manager.test.js.map +1 -1
- package/dist/services/subagents/subagent-session.d.ts +1 -1
- package/dist/services/subagents/subagent-session.d.ts.map +1 -1
- package/dist/services/subagents/subagent-session.js +2 -2
- package/dist/services/subagents/subagent-session.js.map +1 -1
- package/dist/services/subagents/subagent-session.test.js +3 -3
- package/dist/services/subagents/subagent-session.test.js.map +1 -1
- package/dist/services/subagents/types.d.ts +2 -1
- package/dist/services/subagents/types.d.ts.map +1 -1
- package/dist/services/terminal-result-collector.d.ts.map +1 -1
- package/dist/services/terminal-result-collector.js +49 -1
- package/dist/services/terminal-result-collector.js.map +1 -1
- package/dist/services/terminal-result-collector.test.js +44 -0
- package/dist/services/terminal-result-collector.test.js.map +1 -1
- package/dist/services/tool-call-arguments.d.ts +20 -0
- package/dist/services/tool-call-arguments.d.ts.map +1 -0
- package/dist/services/tool-call-arguments.js +49 -0
- package/dist/services/tool-call-arguments.js.map +1 -0
- package/dist/services/tool-execution-ledger.d.ts +41 -0
- package/dist/services/tool-execution-ledger.d.ts.map +1 -0
- package/dist/services/tool-execution-ledger.js +269 -0
- package/dist/services/tool-execution-ledger.js.map +1 -0
- package/dist/services/tool-execution-ledger.test.d.ts +2 -0
- package/dist/services/tool-execution-ledger.test.d.ts.map +1 -0
- package/dist/services/tool-execution-ledger.test.js +271 -0
- package/dist/services/tool-execution-ledger.test.js.map +1 -0
- package/dist/tools/apply-patch.d.ts +8 -0
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +187 -14
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/apply-patch.test.js +81 -0
- package/dist/tools/apply-patch.test.js.map +1 -1
- package/dist/tools/edit-healing.d.ts.map +1 -1
- package/dist/tools/edit-healing.js +9 -3
- package/dist/tools/edit-healing.js.map +1 -1
- package/dist/tools/run-subagent.d.ts +0 -1
- package/dist/tools/run-subagent.d.ts.map +1 -1
- package/dist/tools/run-subagent.js +1 -8
- package/dist/tools/run-subagent.js.map +1 -1
- package/dist/tools/run-subagent.test.js +0 -18
- package/dist/tools/run-subagent.test.js.map +1 -1
- package/dist/tools/search-replace.d.ts.map +1 -1
- package/dist/tools/search-replace.js +92 -140
- package/dist/tools/search-replace.js.map +1 -1
- package/dist/utils/clipboard.d.ts +7 -0
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +83 -4
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/clipboard.test.js +152 -2
- package/dist/utils/clipboard.test.js.map +1 -1
- package/dist/utils/conversation-event-handler.d.ts.map +1 -1
- package/dist/utils/conversation-event-handler.js +36 -1
- package/dist/utils/conversation-event-handler.js.map +1 -1
- package/dist/utils/conversation-event-handler.test.js +116 -0
- package/dist/utils/conversation-event-handler.test.js.map +1 -1
- package/dist/utils/error-helpers.d.ts +1 -0
- package/dist/utils/error-helpers.d.ts.map +1 -1
- package/dist/utils/error-helpers.js +61 -0
- package/dist/utils/error-helpers.js.map +1 -1
- package/dist/utils/error-helpers.test.js +13 -1
- package/dist/utils/error-helpers.test.js.map +1 -1
- package/dist/utils/extract-command-messages.d.ts.map +1 -1
- package/dist/utils/extract-command-messages.js +8 -4
- package/dist/utils/extract-command-messages.js.map +1 -1
- package/dist/utils/ink-render-options.d.ts +1 -1
- package/dist/utils/ink-render-options.d.ts.map +1 -1
- package/dist/utils/ink-render-options.js +1 -1
- package/dist/utils/ink-render-options.js.map +1 -1
- package/dist/utils/message-utils.d.ts +7 -0
- package/dist/utils/message-utils.d.ts.map +1 -0
- package/dist/utils/message-utils.js +31 -0
- package/dist/utils/message-utils.js.map +1 -0
- package/dist/utils/resume-list.d.ts +15 -0
- package/dist/utils/resume-list.d.ts.map +1 -0
- package/dist/utils/resume-list.js +68 -0
- package/dist/utils/resume-list.js.map +1 -0
- package/dist/utils/resume-list.test.d.ts +2 -0
- package/dist/utils/resume-list.test.d.ts.map +1 -0
- package/dist/utils/resume-list.test.js +89 -0
- package/dist/utils/resume-list.test.js.map +1 -0
- package/dist/utils/streaming-session-factory.d.ts +2 -0
- package/dist/utils/streaming-session-factory.d.ts.map +1 -1
- package/dist/utils/streaming-session-factory.js +4 -0
- package/dist/utils/streaming-session-factory.js.map +1 -1
- package/package.json +2 -2
- package/readme.md +22 -7
|
@@ -3,17 +3,50 @@ import { decideRetry, isTransientRetryableError, MAX_HALLUCINATION_RETRIES, MAX_
|
|
|
3
3
|
import { getProvider } from '../providers/index.js';
|
|
4
4
|
import { ApprovalState } from './approval-state.js';
|
|
5
5
|
import { collectTerminalResult } from './terminal-result-collector.js';
|
|
6
|
-
import { getMethod } from './interruption-info.js';
|
|
6
|
+
import { getMethod, getCallIdFromObject } from './interruption-info.js';
|
|
7
7
|
import { createStreamAccumulator, processStreamEvents } from './stream-event-processor.js';
|
|
8
8
|
import { ShellAutoApprovalResolver } from './shell-auto-approval-resolver.js';
|
|
9
9
|
import { ApprovalFlowCoordinator } from './approval-flow-coordinator.js';
|
|
10
10
|
import { buildConversationResult, toTerminalEvent } from './conversation-result-builder.js';
|
|
11
11
|
import { normalizeUserTurn } from '../types/user-turn.js';
|
|
12
|
-
import { InputSurgeGuard } from './input-surge-guard.js';
|
|
12
|
+
import { collectDuplicateToolCallResultPairs, InputSurgeGuard } from './input-surge-guard.js';
|
|
13
|
+
import { LargeUncachedInputGuard } from './large-uncached-input-guard.js';
|
|
14
|
+
import { reconcileHistoryWithToolLedger, ToolExecutionLedger, callIdOf, toolNameOf, outputOf, } from './tool-execution-ledger.js';
|
|
15
|
+
import { describeError } from '../utils/error-helpers.js';
|
|
13
16
|
const supportsConversationChaining = (providerId) => {
|
|
14
17
|
const providerDef = getProvider(providerId);
|
|
15
18
|
return providerDef?.capabilities?.supportsConversationChaining ?? false;
|
|
16
19
|
};
|
|
20
|
+
const asArray = (value) => (Array.isArray(value) ? value : []);
|
|
21
|
+
const warnIfStreamHistoryReplayedTools = ({ logger, sessionId, source, stream, }) => {
|
|
22
|
+
const streamRecord = stream;
|
|
23
|
+
const history = asArray(streamRecord.history);
|
|
24
|
+
const newItems = asArray(streamRecord.newItems);
|
|
25
|
+
const stateGeneratedItems = asArray(streamRecord.state?._generatedItems);
|
|
26
|
+
const historyDuplicates = collectDuplicateToolCallResultPairs(history);
|
|
27
|
+
const newItemsDuplicates = collectDuplicateToolCallResultPairs(newItems);
|
|
28
|
+
const stateGeneratedItemsDuplicates = collectDuplicateToolCallResultPairs(stateGeneratedItems);
|
|
29
|
+
if (historyDuplicates.pairs === 0 && newItemsDuplicates.pairs === 0 && stateGeneratedItemsDuplicates.pairs === 0) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
logger.warn('Completed stream history contains replayed tool call/result pairs', {
|
|
33
|
+
eventType: 'conversation.stream_history.replayed_tools',
|
|
34
|
+
category: 'provider',
|
|
35
|
+
phase: 'post_stream',
|
|
36
|
+
sessionId,
|
|
37
|
+
traceId: logger.getCorrelationId(),
|
|
38
|
+
source,
|
|
39
|
+
historyLength: history.length,
|
|
40
|
+
newItemsLength: newItems.length,
|
|
41
|
+
stateGeneratedItemsLength: stateGeneratedItems.length,
|
|
42
|
+
historyDuplicatePairs: historyDuplicates.pairs,
|
|
43
|
+
historyMaxCopies: historyDuplicates.maxCopies,
|
|
44
|
+
newItemsDuplicatePairs: newItemsDuplicates.pairs,
|
|
45
|
+
newItemsMaxCopies: newItemsDuplicates.maxCopies,
|
|
46
|
+
stateGeneratedItemsDuplicatePairs: stateGeneratedItemsDuplicates.pairs,
|
|
47
|
+
stateGeneratedItemsMaxCopies: stateGeneratedItemsDuplicates.maxCopies,
|
|
48
|
+
});
|
|
49
|
+
};
|
|
17
50
|
export class ConversationSession {
|
|
18
51
|
id;
|
|
19
52
|
startedAt;
|
|
@@ -24,12 +57,19 @@ export class ConversationSession {
|
|
|
24
57
|
approvalState = new ApprovalState();
|
|
25
58
|
toolCallArgumentsById = new Map();
|
|
26
59
|
emittedInvalidToolCallPackets = new Set();
|
|
60
|
+
emittedToolStartedCallIds = new Set();
|
|
27
61
|
shellAutoApproval;
|
|
28
62
|
approvalFlow;
|
|
29
63
|
inputSurgeGuard = new InputSurgeGuard();
|
|
64
|
+
largeUncachedInputGuard = new LargeUncachedInputGuard();
|
|
65
|
+
toolLedger = new ToolExecutionLedger();
|
|
30
66
|
generation = 0;
|
|
67
|
+
#inputSurgeKind = 'delta';
|
|
68
|
+
currentPersistedTurnItems = [];
|
|
69
|
+
currentReasoningBuffer = '';
|
|
70
|
+
currentAssistantTextBuffer = '';
|
|
31
71
|
settingsService;
|
|
32
|
-
|
|
72
|
+
logSink = null;
|
|
33
73
|
constructor(id, { agentClient, deps, sessionStartedAt, }) {
|
|
34
74
|
this.id = id;
|
|
35
75
|
this.startedAt = sessionStartedAt ?? new Date().toISOString();
|
|
@@ -63,6 +103,61 @@ export class ConversationSession {
|
|
|
63
103
|
return 'mentor';
|
|
64
104
|
return 'standard';
|
|
65
105
|
}
|
|
106
|
+
#getModelForGuard() {
|
|
107
|
+
return this.settingsService?.get('agent.model') ?? null;
|
|
108
|
+
}
|
|
109
|
+
#getReasoningEffortForGuard() {
|
|
110
|
+
return this.settingsService?.get('agent.reasoningEffort') ?? null;
|
|
111
|
+
}
|
|
112
|
+
#getProviderForGuard() {
|
|
113
|
+
const getProvider = getMethod(this.agentClient, 'getProvider');
|
|
114
|
+
return getProvider
|
|
115
|
+
? getProvider.call(this.agentClient)
|
|
116
|
+
: this.settingsService?.get('agent.provider') ?? null;
|
|
117
|
+
}
|
|
118
|
+
#makeUserInputItem(turn) {
|
|
119
|
+
const images = turn.images ?? [];
|
|
120
|
+
if (images.length === 0) {
|
|
121
|
+
return { role: 'user', type: 'message', content: turn.text ?? '' };
|
|
122
|
+
}
|
|
123
|
+
const content = [];
|
|
124
|
+
if (turn.text) {
|
|
125
|
+
content.push({ type: 'input_text', text: turn.text });
|
|
126
|
+
}
|
|
127
|
+
for (const image of images) {
|
|
128
|
+
content.push({
|
|
129
|
+
type: 'input_image',
|
|
130
|
+
image: `data:${image.mimeType};base64,${image.data}`,
|
|
131
|
+
detail: 'auto',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return { role: 'user', type: 'message', content };
|
|
135
|
+
}
|
|
136
|
+
#buildOutgoingInput(turn, { includeTurn }) {
|
|
137
|
+
const provider = this.#getProviderForGuard() ?? 'openai';
|
|
138
|
+
const supportsChaining = supportsConversationChaining(provider);
|
|
139
|
+
const history = this.#getCanonicalHistory();
|
|
140
|
+
const outgoingHistory = includeTurn ? [...history, this.#makeUserInputItem(turn)] : history;
|
|
141
|
+
const useChaining = supportsChaining && (!!this.previousResponseId || outgoingHistory.length <= 1);
|
|
142
|
+
const latestInput = outgoingHistory[outgoingHistory.length - 1] ?? turn.text;
|
|
143
|
+
const chainedInput = turn.images?.length ? latestInput : turn.text;
|
|
144
|
+
return {
|
|
145
|
+
streamInput: useChaining ? (typeof chainedInput === 'string' ? chainedInput : [chainedInput]) : outgoingHistory,
|
|
146
|
+
inputSurgeKind: useChaining ? 'delta' : 'full_history',
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
previewLargeUncachedInput(input, now = Date.now()) {
|
|
150
|
+
const turn = normalizeUserTurn(input);
|
|
151
|
+
const { streamInput } = this.#buildOutgoingInput(turn, { includeTurn: true });
|
|
152
|
+
return this.largeUncachedInputGuard.inspect({
|
|
153
|
+
input: streamInput,
|
|
154
|
+
now,
|
|
155
|
+
provider: this.#getProviderForGuard(),
|
|
156
|
+
model: this.#getModelForGuard(),
|
|
157
|
+
reasoningEffort: this.#getReasoningEffortForGuard(),
|
|
158
|
+
mode: this.#getTrafficMode(),
|
|
159
|
+
});
|
|
160
|
+
}
|
|
66
161
|
#getFirstUserMessagePreview(currentTurn) {
|
|
67
162
|
const [firstTurn] = this.conversationStore.listUserTurns();
|
|
68
163
|
return firstTurn?.text ?? currentTurn ?? '';
|
|
@@ -89,8 +184,13 @@ export class ConversationSession {
|
|
|
89
184
|
this.approvalState.clearPending();
|
|
90
185
|
this.approvalState.consumeAborted();
|
|
91
186
|
this.toolCallArgumentsById.clear();
|
|
187
|
+
this.emittedToolStartedCallIds.clear();
|
|
188
|
+
this.toolLedger = new ToolExecutionLedger();
|
|
92
189
|
this.shellAutoApproval.clearCache();
|
|
93
190
|
this.inputSurgeGuard.reset();
|
|
191
|
+
this.largeUncachedInputGuard.reset();
|
|
192
|
+
this.#inputSurgeKind = 'delta';
|
|
193
|
+
this.#resetPersistedTurnState();
|
|
94
194
|
const clearConversations = getMethod(this.agentClient, 'clearConversations');
|
|
95
195
|
clearConversations?.call(this.agentClient);
|
|
96
196
|
}
|
|
@@ -103,8 +203,13 @@ export class ConversationSession {
|
|
|
103
203
|
this.approvalState.clearPending();
|
|
104
204
|
this.approvalState.consumeAborted();
|
|
105
205
|
this.toolCallArgumentsById.clear();
|
|
206
|
+
this.emittedToolStartedCallIds.clear();
|
|
106
207
|
this.shellAutoApproval.clearCache();
|
|
107
208
|
this.inputSurgeGuard.reset();
|
|
209
|
+
this.largeUncachedInputGuard.markUndoOrRewind();
|
|
210
|
+
this.#inputSurgeKind = 'delta';
|
|
211
|
+
this.#resetPersistedTurnState();
|
|
212
|
+
this.#log({ type: 'undo', removedUserTurns: 1, snapshot: this.getCurrentSnapshot() });
|
|
108
213
|
return removed;
|
|
109
214
|
}
|
|
110
215
|
listUserTurns() {
|
|
@@ -119,8 +224,13 @@ export class ConversationSession {
|
|
|
119
224
|
this.approvalState.clearPending();
|
|
120
225
|
this.approvalState.consumeAborted();
|
|
121
226
|
this.toolCallArgumentsById.clear();
|
|
227
|
+
this.emittedToolStartedCallIds.clear();
|
|
122
228
|
this.shellAutoApproval.clearCache();
|
|
123
229
|
this.inputSurgeGuard.reset();
|
|
230
|
+
this.largeUncachedInputGuard.markUndoOrRewind();
|
|
231
|
+
this.#inputSurgeKind = 'delta';
|
|
232
|
+
this.#resetPersistedTurnState();
|
|
233
|
+
this.#log({ type: 'undo', removedUserTurns: n, snapshot: this.getCurrentSnapshot() });
|
|
124
234
|
return removed;
|
|
125
235
|
}
|
|
126
236
|
setModel(model) {
|
|
@@ -135,52 +245,292 @@ export class ConversationSession {
|
|
|
135
245
|
setTemperature?.call(this.agentClient, temperature);
|
|
136
246
|
}
|
|
137
247
|
setProvider(provider) {
|
|
248
|
+
this.generation++;
|
|
249
|
+
this.previousResponseId = null;
|
|
250
|
+
this.approvalState.clearPending();
|
|
251
|
+
this.approvalState.consumeAborted();
|
|
252
|
+
this.toolCallArgumentsById.clear();
|
|
253
|
+
this.emittedToolStartedCallIds.clear();
|
|
254
|
+
this.shellAutoApproval.clearCache();
|
|
255
|
+
this.inputSurgeGuard.reset();
|
|
256
|
+
const clearConversations = getMethod(this.agentClient, 'clearConversations');
|
|
257
|
+
clearConversations?.call(this.agentClient);
|
|
138
258
|
const setProvider = getMethod(this.agentClient, 'setProvider');
|
|
139
259
|
setProvider?.call(this.agentClient, provider);
|
|
140
260
|
}
|
|
261
|
+
switchProvider(provider) {
|
|
262
|
+
this.setProvider(provider);
|
|
263
|
+
}
|
|
141
264
|
setRetryCallback(callback) {
|
|
142
265
|
if (typeof this.agentClient.setRetryCallback === 'function') {
|
|
143
266
|
this.agentClient.setRetryCallback(callback);
|
|
144
267
|
}
|
|
145
268
|
}
|
|
269
|
+
setLogSink(sink) {
|
|
270
|
+
this.logSink = sink;
|
|
271
|
+
}
|
|
272
|
+
getCurrentSnapshot() {
|
|
273
|
+
const getProvider = getMethod(this.agentClient, 'getProvider');
|
|
274
|
+
const provider = getProvider
|
|
275
|
+
? getProvider.call(this.agentClient)
|
|
276
|
+
: this.settingsService?.get('agent.provider');
|
|
277
|
+
const model = this.settingsService?.get('agent.model');
|
|
278
|
+
return {
|
|
279
|
+
history: this.#getCanonicalHistory(),
|
|
280
|
+
previousResponseId: this.previousResponseId,
|
|
281
|
+
toolLedger: this.toolLedger.export(),
|
|
282
|
+
...(model ? { model } : {}),
|
|
283
|
+
...(provider ? { provider } : {}),
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
#getCurrentAssistantTurnState() {
|
|
287
|
+
const getProvider = getMethod(this.agentClient, 'getProvider');
|
|
288
|
+
const provider = getProvider
|
|
289
|
+
? getProvider.call(this.agentClient)
|
|
290
|
+
: this.settingsService?.get('agent.provider');
|
|
291
|
+
const model = this.settingsService?.get('agent.model');
|
|
292
|
+
return {
|
|
293
|
+
previousResponseId: this.previousResponseId,
|
|
294
|
+
...(model ? { model } : {}),
|
|
295
|
+
...(provider ? { provider } : {}),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
#flushReasoningItem() {
|
|
299
|
+
if (this.currentReasoningBuffer) {
|
|
300
|
+
this.currentPersistedTurnItems.push({
|
|
301
|
+
type: 'reasoning',
|
|
302
|
+
text: this.currentReasoningBuffer,
|
|
303
|
+
});
|
|
304
|
+
this.currentReasoningBuffer = '';
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
#flushAssistantTextItem() {
|
|
308
|
+
if (this.currentAssistantTextBuffer) {
|
|
309
|
+
this.currentPersistedTurnItems.push({
|
|
310
|
+
type: 'assistant_text',
|
|
311
|
+
text: this.currentAssistantTextBuffer,
|
|
312
|
+
});
|
|
313
|
+
this.currentAssistantTextBuffer = '';
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
#recordToolCallItem(callId, toolName, args) {
|
|
317
|
+
this.#flushReasoningItem();
|
|
318
|
+
this.#flushAssistantTextItem();
|
|
319
|
+
this.currentPersistedTurnItems.push({
|
|
320
|
+
type: 'tool_call',
|
|
321
|
+
callId,
|
|
322
|
+
toolName,
|
|
323
|
+
arguments: args,
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
#recordToolResultItem(callId, toolName, status, output) {
|
|
327
|
+
this.#flushReasoningItem();
|
|
328
|
+
this.#flushAssistantTextItem();
|
|
329
|
+
this.currentPersistedTurnItems.push({
|
|
330
|
+
type: 'tool_result',
|
|
331
|
+
callId,
|
|
332
|
+
toolName,
|
|
333
|
+
status,
|
|
334
|
+
output,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
#resetPersistedTurnState() {
|
|
338
|
+
this.currentPersistedTurnItems = [];
|
|
339
|
+
this.currentReasoningBuffer = '';
|
|
340
|
+
this.currentAssistantTextBuffer = '';
|
|
341
|
+
}
|
|
342
|
+
#log(event) {
|
|
343
|
+
if (!this.logSink)
|
|
344
|
+
return;
|
|
345
|
+
try {
|
|
346
|
+
this.logSink(event);
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
this.logger.warn('Conversation log sink threw', {
|
|
350
|
+
eventType: 'conversation_log.sink_failed',
|
|
351
|
+
category: 'persistence',
|
|
352
|
+
errorMessage: err instanceof Error ? err.message : String(err),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
#dispatchEventToLog(event) {
|
|
357
|
+
if (!this.logSink)
|
|
358
|
+
return;
|
|
359
|
+
switch (event.type) {
|
|
360
|
+
case 'text_delta':
|
|
361
|
+
if (this.currentReasoningBuffer) {
|
|
362
|
+
this.#flushReasoningItem();
|
|
363
|
+
}
|
|
364
|
+
this.currentAssistantTextBuffer += event.delta;
|
|
365
|
+
return;
|
|
366
|
+
case 'reasoning_delta':
|
|
367
|
+
if (this.currentAssistantTextBuffer) {
|
|
368
|
+
this.#flushAssistantTextItem();
|
|
369
|
+
}
|
|
370
|
+
this.currentReasoningBuffer += event.delta;
|
|
371
|
+
return;
|
|
372
|
+
case 'tool_started':
|
|
373
|
+
this.#recordToolCallItem(event.toolCallId, event.toolName, event.arguments);
|
|
374
|
+
this.#log({
|
|
375
|
+
type: 'tool_started',
|
|
376
|
+
toolCallId: event.toolCallId,
|
|
377
|
+
toolName: event.toolName,
|
|
378
|
+
arguments: event.arguments,
|
|
379
|
+
});
|
|
380
|
+
return;
|
|
381
|
+
case 'command_message':
|
|
382
|
+
this.#log({ type: 'command_message', message: event.message });
|
|
383
|
+
if (event.message.callId &&
|
|
384
|
+
event.message.toolName &&
|
|
385
|
+
(event.message.status === 'completed' || event.message.status === 'failed')) {
|
|
386
|
+
this.#recordToolResultItem(event.message.callId, event.message.toolName, event.message.status === 'failed' ? 'failed' : 'completed', event.message.output);
|
|
387
|
+
}
|
|
388
|
+
return;
|
|
389
|
+
case 'approval_required':
|
|
390
|
+
this.#log({
|
|
391
|
+
type: 'approval_required',
|
|
392
|
+
approval: {
|
|
393
|
+
toolName: event.approval.toolName,
|
|
394
|
+
argumentsText: event.approval.argumentsText,
|
|
395
|
+
agentName: event.approval.agentName,
|
|
396
|
+
...('callId' in event.approval && event.approval.callId ? { callId: event.approval.callId } : {}),
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
return;
|
|
400
|
+
case 'subagent_started':
|
|
401
|
+
this.#log({
|
|
402
|
+
type: 'subagent_started',
|
|
403
|
+
agentId: event.agentId,
|
|
404
|
+
role: event.role,
|
|
405
|
+
task: event.task,
|
|
406
|
+
});
|
|
407
|
+
return;
|
|
408
|
+
case 'subagent_completed':
|
|
409
|
+
this.#log({ type: 'subagent_completed', result: event.result });
|
|
410
|
+
return;
|
|
411
|
+
case 'error':
|
|
412
|
+
this.#log({
|
|
413
|
+
type: 'error',
|
|
414
|
+
message: event.message,
|
|
415
|
+
...(event.kind ? { kind: event.kind } : {}),
|
|
416
|
+
...(event.stack ? { stack: event.stack } : {}),
|
|
417
|
+
});
|
|
418
|
+
return;
|
|
419
|
+
case 'final': {
|
|
420
|
+
const turnState = this.#getCurrentAssistantTurnState();
|
|
421
|
+
const toolLedger = this.toolLedger.export();
|
|
422
|
+
this.#flushReasoningItem();
|
|
423
|
+
this.#flushAssistantTextItem();
|
|
424
|
+
const turnItemsToLog = event.turnItems ? [...event.turnItems] : [...this.currentPersistedTurnItems];
|
|
425
|
+
if (event.finalText && !turnItemsToLog.some((item) => item.type === 'assistant_text')) {
|
|
426
|
+
turnItemsToLog.push({
|
|
427
|
+
type: 'assistant_text',
|
|
428
|
+
text: event.finalText,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
// Invariant check: if transcript contains tool_result, matching call IDs exist in the live tool ledger.
|
|
432
|
+
for (const item of turnItemsToLog) {
|
|
433
|
+
if (item.type === 'tool_result') {
|
|
434
|
+
const exists = toolLedger.some((t) => t.callId === item.callId);
|
|
435
|
+
if (!exists) {
|
|
436
|
+
this.logger.warn(`Invariant violation: tool_result callId ${item.callId} not found in toolLedger`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
const turn = {
|
|
441
|
+
items: turnItemsToLog,
|
|
442
|
+
};
|
|
443
|
+
this.#log({
|
|
444
|
+
type: 'assistant_turn',
|
|
445
|
+
turn,
|
|
446
|
+
...(event.usage ? { usage: event.usage } : {}),
|
|
447
|
+
state: turnState,
|
|
448
|
+
});
|
|
449
|
+
this.#resetPersistedTurnState();
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
default:
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
#dedupeToolStarted(event) {
|
|
457
|
+
if (event.type !== 'tool_started') {
|
|
458
|
+
return event;
|
|
459
|
+
}
|
|
460
|
+
if (this.emittedToolStartedCallIds.has(event.toolCallId)) {
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
this.emittedToolStartedCallIds.add(event.toolCallId);
|
|
464
|
+
return event;
|
|
465
|
+
}
|
|
466
|
+
#getCanonicalHistory() {
|
|
467
|
+
return reconcileHistoryWithToolLedger(this.conversationStore.getHistory(), this.toolLedger.export())
|
|
468
|
+
.history;
|
|
469
|
+
}
|
|
146
470
|
exportState() {
|
|
147
471
|
return {
|
|
148
|
-
history: this
|
|
472
|
+
history: this.#getCanonicalHistory(),
|
|
149
473
|
previousResponseId: this.previousResponseId,
|
|
474
|
+
toolLedger: this.toolLedger.export(),
|
|
150
475
|
};
|
|
151
476
|
}
|
|
152
477
|
importState(state) {
|
|
153
478
|
this.conversationStore.clear();
|
|
154
|
-
|
|
479
|
+
this.toolLedger.import(state.toolLedger);
|
|
480
|
+
const reconciled = reconcileHistoryWithToolLedger(state.history, state.toolLedger);
|
|
481
|
+
if (reconciled.addedCompletedPairs > 0 || reconciled.droppedIncompleteCalls > 0) {
|
|
482
|
+
this.logger.warn('Reconciled saved conversation history with tool execution ledger', {
|
|
483
|
+
eventType: 'conversation.tool_ledger.reconciled',
|
|
484
|
+
category: 'conversation',
|
|
485
|
+
phase: 'resume',
|
|
486
|
+
sessionId: this.id,
|
|
487
|
+
addedCompletedPairs: reconciled.addedCompletedPairs,
|
|
488
|
+
droppedIncompleteCalls: reconciled.droppedIncompleteCalls,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
for (const item of reconciled.history) {
|
|
155
492
|
this.conversationStore.addImportedItem(item);
|
|
156
493
|
}
|
|
157
494
|
this.previousResponseId = state.previousResponseId;
|
|
495
|
+
this.emittedToolStartedCallIds.clear();
|
|
158
496
|
this.inputSurgeGuard.reset();
|
|
497
|
+
this.largeUncachedInputGuard.markResumedSession({
|
|
498
|
+
updatedAtMs: state.updatedAt ? Date.parse(state.updatedAt) : null,
|
|
499
|
+
});
|
|
159
500
|
this.generation++;
|
|
160
501
|
}
|
|
161
502
|
addShellContext(historyText) {
|
|
162
503
|
this.conversationStore.addShellContext(historyText);
|
|
163
504
|
}
|
|
164
|
-
queueModeNotice(text) {
|
|
165
|
-
this.pendingModeNotice = text;
|
|
166
|
-
}
|
|
167
505
|
/**
|
|
168
506
|
* Abort the current running operation
|
|
169
507
|
*/
|
|
170
508
|
abort() {
|
|
171
|
-
this.approvalFlow.
|
|
509
|
+
const pending = this.approvalFlow.getPending();
|
|
510
|
+
const callId = pending ? getCallIdFromObject(pending.interruption) : undefined;
|
|
511
|
+
if (this.approvalFlow.abort()) {
|
|
512
|
+
this.toolLedger.recordAbortedApproval('Tool execution was not approved.', 'Tool execution was not approved.', callId);
|
|
513
|
+
}
|
|
172
514
|
}
|
|
173
515
|
/**
|
|
174
516
|
* Phase 4: stream conversation events as an async iterator.
|
|
175
517
|
*
|
|
176
518
|
* This is the transport-friendly primitive that can later be bridged to SSE/WebSockets.
|
|
177
519
|
*/
|
|
178
|
-
async *run(input, {
|
|
520
|
+
async *run(input, { skipUserMessage = false, flexServiceTierFallbackCount = 0, hallucinationRetryCount = 0, transientRetryCount = 0, } = {}) {
|
|
521
|
+
if (!skipUserMessage ||
|
|
522
|
+
hallucinationRetryCount > 0 ||
|
|
523
|
+
flexServiceTierFallbackCount > 0 ||
|
|
524
|
+
transientRetryCount > 0) {
|
|
525
|
+
this.#resetPersistedTurnState();
|
|
526
|
+
}
|
|
179
527
|
const gen = this.generation;
|
|
180
528
|
let stream = null;
|
|
181
529
|
const turn = normalizeUserTurn(input);
|
|
182
530
|
const text = turn.text;
|
|
183
531
|
let addedUserMessage = false;
|
|
532
|
+
const ledgerSnapshot = this.toolLedger.export();
|
|
533
|
+
this.toolLedger.beginTurn();
|
|
184
534
|
try {
|
|
185
535
|
this.logger.debug('Conversation stream start', {
|
|
186
536
|
eventType: 'stream.started',
|
|
@@ -196,6 +546,12 @@ export class ConversationSession {
|
|
|
196
546
|
this.conversationStore.addUserTurn(turn);
|
|
197
547
|
addedUserMessage = true;
|
|
198
548
|
}
|
|
549
|
+
else if (abortedContext && !skipUserMessage) {
|
|
550
|
+
// The UI appended a user message for this input, but the store will consume it
|
|
551
|
+
// as fake tool output for the aborted approval rather than as a new user turn.
|
|
552
|
+
// Signal the UI to mark it so /undo skips it.
|
|
553
|
+
yield { type: 'user_message_consumed_for_abort' };
|
|
554
|
+
}
|
|
199
555
|
// If there's an aborted approval, we need to resolve it first.
|
|
200
556
|
// The user's message is a new input, but the agent is stuck waiting for tool output.
|
|
201
557
|
if (abortedContext) {
|
|
@@ -213,17 +569,53 @@ export class ConversationSession {
|
|
|
213
569
|
try {
|
|
214
570
|
const continuedStream = (await this.agentClient.continueRunStream(abortedContext.state, {
|
|
215
571
|
previousResponseId: this.previousResponseId,
|
|
572
|
+
sessionId: this.id,
|
|
216
573
|
}));
|
|
217
574
|
const acc = createStreamAccumulator();
|
|
218
575
|
acc.emittedCommandIds = new Set(abortedContext.emittedCommandIds);
|
|
219
|
-
|
|
576
|
+
for await (const event of processStreamEvents(continuedStream, acc, {
|
|
220
577
|
toolCallArgumentsById: this.toolCallArgumentsById,
|
|
221
578
|
emittedInvalidToolCallPackets: this.emittedInvalidToolCallPackets,
|
|
222
579
|
preserveExistingToolArgs: true,
|
|
223
|
-
|
|
580
|
+
onFunctionCallItem: (item) => this.toolLedger.recordFunctionCall(item),
|
|
581
|
+
onFunctionResultItem: (item) => {
|
|
582
|
+
this.toolLedger.recordFunctionResult(item);
|
|
583
|
+
const cid = callIdOf(item);
|
|
584
|
+
if (cid && this.logSink) {
|
|
585
|
+
const entry = this.toolLedger.export().find((e) => e.callId === cid);
|
|
586
|
+
this.#log({
|
|
587
|
+
type: 'tool_result',
|
|
588
|
+
callId: cid,
|
|
589
|
+
toolName: entry?.toolName ?? toolNameOf(item),
|
|
590
|
+
status: entry?.status === 'failed' || entry?.status === 'aborted' ? entry.status : 'completed',
|
|
591
|
+
output: entry?.output ?? outputOf(item),
|
|
592
|
+
...(entry?.historyItems ? { historyItems: entry.historyItems } : {}),
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
}, { logger: this.logger, sessionId: this.id })) {
|
|
597
|
+
const filtered = this.#dedupeToolStarted(event);
|
|
598
|
+
if (filtered)
|
|
599
|
+
yield filtered;
|
|
600
|
+
}
|
|
224
601
|
if (this.#isCurrentGeneration(gen)) {
|
|
225
602
|
this.previousResponseId = continuedStream.lastResponseId ?? null;
|
|
226
|
-
|
|
603
|
+
warnIfStreamHistoryReplayedTools({
|
|
604
|
+
logger: this.logger,
|
|
605
|
+
sessionId: this.id,
|
|
606
|
+
source: 'abortResolution',
|
|
607
|
+
stream: continuedStream,
|
|
608
|
+
});
|
|
609
|
+
const s = continuedStream;
|
|
610
|
+
const terminal = !continuedStream.interruptions || continuedStream.interruptions.length === 0;
|
|
611
|
+
if (terminal) {
|
|
612
|
+
if (this.#inputSurgeKind === 'delta') {
|
|
613
|
+
this.conversationStore.appendOutput(s.output);
|
|
614
|
+
}
|
|
615
|
+
else {
|
|
616
|
+
this.conversationStore.replaceHistory(s.history);
|
|
617
|
+
}
|
|
618
|
+
}
|
|
227
619
|
}
|
|
228
620
|
// Check if another interruption occurred
|
|
229
621
|
if (continuedStream.interruptions && continuedStream.interruptions.length > 0) {
|
|
@@ -251,49 +643,21 @@ export class ConversationSession {
|
|
|
251
643
|
}
|
|
252
644
|
}
|
|
253
645
|
// Normal message flow
|
|
254
|
-
const getProvider = getMethod(this.agentClient, 'getProvider');
|
|
255
|
-
const provider = getProvider ? getProvider.call(this.agentClient) : 'openai';
|
|
256
|
-
const supportsChaining = supportsConversationChaining(provider);
|
|
257
|
-
const history = this.conversationStore.getHistory();
|
|
258
646
|
// Use chaining mode only when the provider supports it AND either a valid
|
|
259
647
|
// chain exists (previousResponseId is set) or there is no prior history to
|
|
260
648
|
// resync (fresh start with just the current message). After undo the chain
|
|
261
649
|
// is severed (previousResponseId = null) while prior turns remain in the
|
|
262
650
|
// local store, so we fall back to full-history mode to re-establish context.
|
|
263
|
-
const
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
this.pendingModeNotice = null;
|
|
268
|
-
if (useChaining) {
|
|
269
|
-
const latestInput = history[history.length - 1] ?? text;
|
|
270
|
-
const chainedInput = turn.images?.length ? latestInput : text;
|
|
271
|
-
const userItem = typeof chainedInput === 'string' ? { role: 'user', type: 'message', content: chainedInput } : chainedInput;
|
|
272
|
-
const noticeItem = { role: 'system', type: 'message', content: notice };
|
|
273
|
-
streamInput = [noticeItem, userItem];
|
|
274
|
-
}
|
|
275
|
-
else {
|
|
276
|
-
// Persist the notice at the tail (append-only) rather than splicing
|
|
277
|
-
// it before the last user turn or sending it as a one-shot item.
|
|
278
|
-
// Mid-history insertion adds a stray ephemeral cache breakpoint (see
|
|
279
|
-
// addCacheControlToLastTwoMessages) and a transient item makes
|
|
280
|
-
// consecutive requests diverge at the tail — both break the
|
|
281
|
-
// Claude/Qwen prompt cache. Appending keeps the cached prefix
|
|
282
|
-
// byte-identical and only growing.
|
|
283
|
-
this.conversationStore.addModeNotice(notice);
|
|
284
|
-
streamInput = this.conversationStore.getHistory();
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
const latestInput = history[history.length - 1] ?? text;
|
|
289
|
-
const chainedInput = turn.images?.length ? latestInput : text;
|
|
290
|
-
streamInput = useChaining ? (typeof chainedInput === 'string' ? chainedInput : [chainedInput]) : history;
|
|
291
|
-
}
|
|
292
|
-
const inputSurgeKind = useChaining ? 'delta' : 'full_history';
|
|
651
|
+
const { streamInput, inputSurgeKind } = this.#buildOutgoingInput(turn, {
|
|
652
|
+
includeTurn: false,
|
|
653
|
+
});
|
|
654
|
+
this.#inputSurgeKind = inputSurgeKind;
|
|
293
655
|
const surgeDecision = this.inputSurgeGuard.inspect(streamInput, { kind: inputSurgeKind });
|
|
294
656
|
if (surgeDecision.action === 'block') {
|
|
657
|
+
let droppedUserMessage;
|
|
295
658
|
if (addedUserMessage && this.#isCurrentGeneration(gen)) {
|
|
296
659
|
this.conversationStore.removeLastUserMessage();
|
|
660
|
+
droppedUserMessage = { text: turn.text, imageCount: turn.images?.length ?? 0 };
|
|
297
661
|
}
|
|
298
662
|
this.logger.warn('Input surge guard blocked provider request', {
|
|
299
663
|
eventType: 'input_surge.blocked',
|
|
@@ -309,24 +673,47 @@ export class ConversationSession {
|
|
|
309
673
|
type: 'error',
|
|
310
674
|
kind: 'input_surge_guard',
|
|
311
675
|
message: `${surgeDecision.reason} Request blocked to prevent runaway context growth. Try /undo or /clear, or compact the conversation history.`,
|
|
676
|
+
...(droppedUserMessage ? { droppedUserMessage } : {}),
|
|
312
677
|
};
|
|
313
678
|
return;
|
|
314
679
|
}
|
|
315
680
|
stream = (await this.agentClient.startStream(streamInput, {
|
|
316
|
-
previousResponseId: this.previousResponseId,
|
|
681
|
+
previousResponseId: inputSurgeKind === 'delta' ? this.previousResponseId : null,
|
|
682
|
+
sessionId: this.id,
|
|
317
683
|
}));
|
|
318
684
|
const acc = createStreamAccumulator();
|
|
319
|
-
|
|
685
|
+
for await (const event of processStreamEvents(stream, acc, {
|
|
320
686
|
toolCallArgumentsById: this.toolCallArgumentsById,
|
|
321
687
|
emittedInvalidToolCallPackets: this.emittedInvalidToolCallPackets,
|
|
322
688
|
preserveExistingToolArgs: false,
|
|
323
|
-
|
|
689
|
+
onFunctionCallItem: (item) => this.toolLedger.recordFunctionCall(item),
|
|
690
|
+
onFunctionResultItem: (item) => this.toolLedger.recordFunctionResult(item),
|
|
691
|
+
}, { logger: this.logger, sessionId: this.id })) {
|
|
692
|
+
const filtered = this.#dedupeToolStarted(event);
|
|
693
|
+
if (filtered)
|
|
694
|
+
yield filtered;
|
|
695
|
+
}
|
|
324
696
|
if (this.#isCurrentGeneration(gen)) {
|
|
325
697
|
this.previousResponseId = stream.lastResponseId ?? null;
|
|
326
|
-
|
|
698
|
+
warnIfStreamHistoryReplayedTools({
|
|
699
|
+
logger: this.logger,
|
|
700
|
+
sessionId: this.id,
|
|
701
|
+
source: 'startStream',
|
|
702
|
+
stream,
|
|
703
|
+
});
|
|
704
|
+
const s = stream;
|
|
705
|
+
const terminal = !stream.interruptions || stream.interruptions.length === 0;
|
|
706
|
+
if (terminal) {
|
|
707
|
+
if (inputSurgeKind === 'delta') {
|
|
708
|
+
this.conversationStore.appendOutput(s.output);
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
this.conversationStore.replaceHistory(s.history);
|
|
712
|
+
}
|
|
713
|
+
}
|
|
327
714
|
}
|
|
328
715
|
const resolvedResult = yield* this.#buildAndResolve(stream, acc.finalOutput || undefined, acc.reasoningOutput || undefined, acc.emittedCommandIds, acc.latestUsage);
|
|
329
|
-
if (
|
|
716
|
+
if (inputSurgeKind === 'delta') {
|
|
330
717
|
this.inputSurgeGuard.recordSuccessfulInput(streamInput, { kind: inputSurgeKind });
|
|
331
718
|
}
|
|
332
719
|
else {
|
|
@@ -335,7 +722,23 @@ export class ConversationSession {
|
|
|
335
722
|
previousInput: streamInput,
|
|
336
723
|
});
|
|
337
724
|
}
|
|
725
|
+
this.largeUncachedInputGuard.recordSuccessfulInput({
|
|
726
|
+
input: inputSurgeKind === 'delta' ? streamInput : this.conversationStore.getHistory(),
|
|
727
|
+
now: Date.now(),
|
|
728
|
+
provider: this.#getProviderForGuard(),
|
|
729
|
+
model: this.#getModelForGuard(),
|
|
730
|
+
reasoningEffort: this.#getReasoningEffortForGuard(),
|
|
731
|
+
mode: this.#getTrafficMode(),
|
|
732
|
+
});
|
|
338
733
|
if (resolvedResult.type === 'approval_required') {
|
|
734
|
+
if (resolvedResult.approval.callId) {
|
|
735
|
+
this.toolLedger.recordFunctionCall({
|
|
736
|
+
type: 'function_call',
|
|
737
|
+
callId: resolvedResult.approval.callId,
|
|
738
|
+
name: resolvedResult.approval.toolName,
|
|
739
|
+
arguments: resolvedResult.approval.argumentsText,
|
|
740
|
+
});
|
|
741
|
+
}
|
|
339
742
|
this.logger.debug('Tool approval required', {
|
|
340
743
|
eventType: 'approval.required',
|
|
341
744
|
category: 'approval',
|
|
@@ -374,12 +777,52 @@ export class ConversationSession {
|
|
|
374
777
|
retryType: 'flex_service_tier',
|
|
375
778
|
};
|
|
376
779
|
getMethod(this.agentClient, 'useStandardServiceTierForNextRequest')?.call(this.agentClient);
|
|
780
|
+
this.toolLedger.import(ledgerSnapshot);
|
|
377
781
|
yield* this.run(turn, {
|
|
378
782
|
skipUserMessage: true,
|
|
379
783
|
flexServiceTierFallbackCount: flexServiceTierFallbackCount + 1,
|
|
380
784
|
});
|
|
381
785
|
return;
|
|
382
786
|
}
|
|
787
|
+
if (isTransientRetryableError(error) && transientRetryCount < MAX_TRANSIENT_RETRIES) {
|
|
788
|
+
const attempt = transientRetryCount + 1;
|
|
789
|
+
const delay = Math.min(500 * Math.pow(2, attempt - 1), 30000);
|
|
790
|
+
this.logger.warn('Transient upstream error detected, retrying turn', {
|
|
791
|
+
eventType: 'retry.transient',
|
|
792
|
+
category: 'retry',
|
|
793
|
+
phase: 'retry',
|
|
794
|
+
retryType: 'upstream',
|
|
795
|
+
retryAttempt: attempt,
|
|
796
|
+
attempt,
|
|
797
|
+
maxRetries: MAX_TRANSIENT_RETRIES,
|
|
798
|
+
sessionId: this.id,
|
|
799
|
+
traceId: this.logger.getCorrelationId(),
|
|
800
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
801
|
+
delayMs: delay,
|
|
802
|
+
});
|
|
803
|
+
yield {
|
|
804
|
+
type: 'retry',
|
|
805
|
+
toolName: 'turn',
|
|
806
|
+
attempt,
|
|
807
|
+
maxRetries: MAX_TRANSIENT_RETRIES,
|
|
808
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
809
|
+
retryType: 'upstream',
|
|
810
|
+
};
|
|
811
|
+
if (!this.#isCurrentGeneration(gen))
|
|
812
|
+
return;
|
|
813
|
+
if (stream) {
|
|
814
|
+
this.toolLedger.import(ledgerSnapshot);
|
|
815
|
+
}
|
|
816
|
+
else {
|
|
817
|
+
this.conversationStore.removeLastUserMessage();
|
|
818
|
+
}
|
|
819
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
820
|
+
yield* this.run(turn, {
|
|
821
|
+
skipUserMessage: Boolean(stream),
|
|
822
|
+
transientRetryCount: attempt,
|
|
823
|
+
});
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
383
826
|
const decision = decideRetry(error, hallucinationRetryCount, Boolean(stream), streamHistoryLength);
|
|
384
827
|
if (decision.kind === 'retry') {
|
|
385
828
|
this.logger.warn('Recoverable model error detected, retrying', {
|
|
@@ -399,6 +842,7 @@ export class ConversationSession {
|
|
|
399
842
|
if (!this.#isCurrentGeneration(gen))
|
|
400
843
|
return;
|
|
401
844
|
if (decision.hadStream && stream) {
|
|
845
|
+
this.toolLedger.import(ledgerSnapshot);
|
|
402
846
|
if (decision.shouldInjectErrorContext) {
|
|
403
847
|
this.conversationStore.addErrorContext(decision.errorContextMessage);
|
|
404
848
|
}
|
|
@@ -409,20 +853,47 @@ export class ConversationSession {
|
|
|
409
853
|
yield* this.run(turn, decision.nextRunOptions);
|
|
410
854
|
return;
|
|
411
855
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
856
|
+
// Drop the just-added user turn from the store before yielding so the
|
|
857
|
+
// generator-cleanup path doesn't strand the removal — and so the error
|
|
858
|
+
// event can carry the dropped text for UI restoration.
|
|
859
|
+
let droppedUserMessage;
|
|
416
860
|
if (addedUserMessage && !stream && this.#isCurrentGeneration(gen)) {
|
|
417
861
|
this.conversationStore.removeLastUserMessage();
|
|
862
|
+
droppedUserMessage = { text: turn.text, imageCount: turn.images?.length ?? 0 };
|
|
863
|
+
}
|
|
864
|
+
if (stream && this.#isCurrentGeneration(gen)) {
|
|
865
|
+
this.toolLedger.markOpenCallsAborted(error instanceof Error ? error.message : String(error));
|
|
866
|
+
// Persist completed tool call/result pairs (and the recovery notice) into
|
|
867
|
+
// canonical history so the next user turn doesn't ship a request with two
|
|
868
|
+
// consecutive user messages and no record of the tool activity.
|
|
869
|
+
const reconciled = reconcileHistoryWithToolLedger(this.conversationStore.getHistory(), this.toolLedger.export());
|
|
870
|
+
if (reconciled.addedCompletedPairs > 0 || reconciled.droppedIncompleteCalls > 0) {
|
|
871
|
+
this.conversationStore.replaceHistory(reconciled.history);
|
|
872
|
+
}
|
|
873
|
+
const recoverySummary = this.toolLedger.getRecoverySummary();
|
|
874
|
+
if (recoverySummary) {
|
|
875
|
+
yield {
|
|
876
|
+
type: 'tool_recovery',
|
|
877
|
+
recoveredCallIds: recoverySummary.recoveredCallIds,
|
|
878
|
+
droppedCallIds: recoverySummary.droppedCallIds,
|
|
879
|
+
message: recoverySummary.message,
|
|
880
|
+
};
|
|
881
|
+
}
|
|
418
882
|
}
|
|
883
|
+
yield {
|
|
884
|
+
type: 'error',
|
|
885
|
+
message: describeError(error),
|
|
886
|
+
...(error instanceof Error && error.stack ? { stack: error.stack } : {}),
|
|
887
|
+
...(droppedUserMessage ? { droppedUserMessage } : {}),
|
|
888
|
+
};
|
|
419
889
|
this.logger.error('Conversation stream error', {
|
|
420
890
|
eventType: 'stream.failed',
|
|
421
891
|
category: 'stream',
|
|
422
892
|
phase: 'abort',
|
|
423
893
|
sessionId: this.id,
|
|
424
894
|
traceId: this.logger.getCorrelationId(),
|
|
425
|
-
errorMessage:
|
|
895
|
+
errorMessage: describeError(error),
|
|
896
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
426
897
|
});
|
|
427
898
|
throw error;
|
|
428
899
|
}
|
|
@@ -438,9 +909,19 @@ export class ConversationSession {
|
|
|
438
909
|
if (!plan) {
|
|
439
910
|
return;
|
|
440
911
|
}
|
|
912
|
+
if (answer !== 'y') {
|
|
913
|
+
const interruption = plan.pendingApprovalContext.interruption;
|
|
914
|
+
const callId = getCallIdFromObject(interruption);
|
|
915
|
+
const output = rejectionReason
|
|
916
|
+
? `Tool execution was not approved. User's reason: ${rejectionReason}`
|
|
917
|
+
: 'Tool execution was not approved.';
|
|
918
|
+
this.toolLedger.recordAbortedApproval(output, output, callId);
|
|
919
|
+
}
|
|
441
920
|
const { pendingApprovalContext: { state, toolCallArgumentsById, emittedCommandIds: previouslyEmittedIds }, toolStartedEvent, removeInterceptor, } = plan;
|
|
442
921
|
if (toolStartedEvent) {
|
|
443
|
-
|
|
922
|
+
const filtered = this.#dedupeToolStarted(toolStartedEvent);
|
|
923
|
+
if (filtered)
|
|
924
|
+
yield filtered;
|
|
444
925
|
}
|
|
445
926
|
// Restore cached tool-call arguments so continuation outputs can attach them
|
|
446
927
|
this.toolCallArgumentsById.clear();
|
|
@@ -455,22 +936,66 @@ export class ConversationSession {
|
|
|
455
936
|
try {
|
|
456
937
|
const stream = (await this.agentClient.continueRunStream(state, {
|
|
457
938
|
previousResponseId: this.previousResponseId,
|
|
939
|
+
sessionId: this.id,
|
|
458
940
|
}));
|
|
459
941
|
const acc = createStreamAccumulator();
|
|
460
|
-
|
|
942
|
+
for await (const event of processStreamEvents(stream, acc, {
|
|
461
943
|
toolCallArgumentsById: this.toolCallArgumentsById,
|
|
462
944
|
emittedInvalidToolCallPackets: this.emittedInvalidToolCallPackets,
|
|
463
945
|
preserveExistingToolArgs: true,
|
|
464
|
-
|
|
946
|
+
onFunctionCallItem: (item) => this.toolLedger.recordFunctionCall(item),
|
|
947
|
+
onFunctionResultItem: (item) => {
|
|
948
|
+
this.toolLedger.recordFunctionResult(item);
|
|
949
|
+
const cid = callIdOf(item);
|
|
950
|
+
if (cid && this.logSink) {
|
|
951
|
+
const entry = this.toolLedger.export().find((e) => e.callId === cid);
|
|
952
|
+
this.#log({
|
|
953
|
+
type: 'tool_result',
|
|
954
|
+
callId: cid,
|
|
955
|
+
toolName: entry?.toolName ?? toolNameOf(item),
|
|
956
|
+
status: entry?.status === 'failed' || entry?.status === 'aborted' ? entry.status : 'completed',
|
|
957
|
+
output: entry?.output ?? outputOf(item),
|
|
958
|
+
...(entry?.historyItems ? { historyItems: entry.historyItems } : {}),
|
|
959
|
+
});
|
|
960
|
+
}
|
|
961
|
+
},
|
|
962
|
+
}, { logger: this.logger, sessionId: this.id })) {
|
|
963
|
+
const filtered = this.#dedupeToolStarted(event);
|
|
964
|
+
if (filtered)
|
|
965
|
+
yield filtered;
|
|
966
|
+
}
|
|
465
967
|
if (this.#isCurrentGeneration(gen)) {
|
|
466
968
|
this.previousResponseId = stream.lastResponseId ?? null;
|
|
467
|
-
|
|
969
|
+
warnIfStreamHistoryReplayedTools({
|
|
970
|
+
logger: this.logger,
|
|
971
|
+
sessionId: this.id,
|
|
972
|
+
source: 'continueRunStream',
|
|
973
|
+
stream,
|
|
974
|
+
});
|
|
975
|
+
const s = stream;
|
|
976
|
+
const terminal = !stream.interruptions || stream.interruptions.length === 0;
|
|
977
|
+
if (terminal) {
|
|
978
|
+
if (this.#inputSurgeKind === 'delta') {
|
|
979
|
+
this.conversationStore.appendOutput(s.output);
|
|
980
|
+
}
|
|
981
|
+
else {
|
|
982
|
+
this.conversationStore.replaceHistory(s.history);
|
|
983
|
+
}
|
|
984
|
+
}
|
|
468
985
|
}
|
|
469
986
|
// Merge previously emitted command IDs with newly emitted ones
|
|
470
987
|
// This prevents duplicates when result.history contains commands from the initial stream
|
|
471
988
|
const allEmittedIds = new Set([...previouslyEmittedIds, ...acc.emittedCommandIds]);
|
|
472
989
|
const resolvedResult = yield* this.#buildAndResolve(stream, acc.finalOutput || undefined, acc.reasoningOutput || undefined, allEmittedIds, acc.latestUsage);
|
|
473
990
|
if (resolvedResult.type === 'approval_required') {
|
|
991
|
+
if (resolvedResult.approval.callId) {
|
|
992
|
+
this.toolLedger.recordFunctionCall({
|
|
993
|
+
type: 'function_call',
|
|
994
|
+
callId: resolvedResult.approval.callId,
|
|
995
|
+
name: resolvedResult.approval.toolName,
|
|
996
|
+
arguments: resolvedResult.approval.argumentsText,
|
|
997
|
+
});
|
|
998
|
+
}
|
|
474
999
|
this.logger.debug('Tool approval required', {
|
|
475
1000
|
eventType: 'approval.required',
|
|
476
1001
|
category: 'approval',
|
|
@@ -517,9 +1042,19 @@ export class ConversationSession {
|
|
|
517
1042
|
}
|
|
518
1043
|
}
|
|
519
1044
|
catch (error) {
|
|
1045
|
+
this.logger.error('Conversation stream error during continuation', {
|
|
1046
|
+
eventType: 'stream.failed',
|
|
1047
|
+
category: 'stream',
|
|
1048
|
+
phase: 'abort',
|
|
1049
|
+
sessionId: this.id,
|
|
1050
|
+
traceId: this.logger.getCorrelationId(),
|
|
1051
|
+
errorMessage: describeError(error),
|
|
1052
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
1053
|
+
});
|
|
520
1054
|
yield {
|
|
521
1055
|
type: 'error',
|
|
522
|
-
message:
|
|
1056
|
+
message: describeError(error),
|
|
1057
|
+
...(error instanceof Error && error.stack ? { stack: error.stack } : {}),
|
|
523
1058
|
};
|
|
524
1059
|
throw error;
|
|
525
1060
|
}
|
|
@@ -531,14 +1066,18 @@ export class ConversationSession {
|
|
|
531
1066
|
async sendMessage(input, { onTextChunk, onReasoningChunk, onCommandMessage, onEvent, hallucinationRetryCount = 0, } = {}) {
|
|
532
1067
|
const turn = normalizeUserTurn(input);
|
|
533
1068
|
return this.#withTrafficContext(turn.text, async () => {
|
|
534
|
-
|
|
1069
|
+
const wrappedOnEvent = (event) => {
|
|
1070
|
+
this.#dispatchEventToLog(event);
|
|
1071
|
+
onEvent?.(event);
|
|
1072
|
+
};
|
|
1073
|
+
getMethod(this.agentClient, 'setSubagentEventSink')?.call(this.agentClient, wrappedOnEvent);
|
|
535
1074
|
let result;
|
|
536
1075
|
try {
|
|
537
1076
|
result = await collectTerminalResult(this.run(input, { hallucinationRetryCount }), {
|
|
538
1077
|
onTextChunk,
|
|
539
1078
|
onReasoningChunk,
|
|
540
1079
|
onCommandMessage,
|
|
541
|
-
onEvent,
|
|
1080
|
+
onEvent: wrappedOnEvent,
|
|
542
1081
|
getRawInterruption: () => this.approvalFlow.getPendingInterruption(),
|
|
543
1082
|
onFinalEvent: (event) => {
|
|
544
1083
|
this.logger.debug('sendMessage received final event', {
|
|
@@ -566,15 +1105,24 @@ export class ConversationSession {
|
|
|
566
1105
|
if (!this.approvalFlow.getPending()) {
|
|
567
1106
|
return null;
|
|
568
1107
|
}
|
|
1108
|
+
this.#log({
|
|
1109
|
+
type: 'approval_resolved',
|
|
1110
|
+
answer: answer === 'y' ? 'y' : 'n',
|
|
1111
|
+
...(rejectionReason ? { rejectionReason } : {}),
|
|
1112
|
+
});
|
|
569
1113
|
return this.#withTrafficContext(undefined, async () => {
|
|
570
|
-
|
|
1114
|
+
const wrappedOnEvent = (event) => {
|
|
1115
|
+
this.#dispatchEventToLog(event);
|
|
1116
|
+
onEvent?.(event);
|
|
1117
|
+
};
|
|
1118
|
+
getMethod(this.agentClient, 'setSubagentEventSink')?.call(this.agentClient, wrappedOnEvent);
|
|
571
1119
|
let result;
|
|
572
1120
|
try {
|
|
573
1121
|
result = await collectTerminalResult(this['continue']({ answer, rejectionReason }), {
|
|
574
1122
|
onTextChunk,
|
|
575
1123
|
onReasoningChunk,
|
|
576
1124
|
onCommandMessage,
|
|
577
|
-
onEvent,
|
|
1125
|
+
onEvent: wrappedOnEvent,
|
|
578
1126
|
getRawInterruption: () => this.approvalFlow.getPendingInterruption(),
|
|
579
1127
|
onFinalEvent: (event) => {
|
|
580
1128
|
this.logger.debug('handleApprovalDecision received final event', {
|
|
@@ -606,6 +1154,7 @@ export class ConversationSession {
|
|
|
606
1154
|
emittedCommandIds,
|
|
607
1155
|
usage,
|
|
608
1156
|
toolCallArgumentsById: this.toolCallArgumentsById,
|
|
1157
|
+
turnItems: this.currentPersistedTurnItems,
|
|
609
1158
|
}, {
|
|
610
1159
|
approvalFlow: this.approvalFlow,
|
|
611
1160
|
shellAutoApproval: this.shellAutoApproval,
|
|
@@ -621,6 +1170,7 @@ export class ConversationSession {
|
|
|
621
1170
|
let continuationApprovalUsage;
|
|
622
1171
|
const commandMessages = [];
|
|
623
1172
|
let approvalRequiredResult;
|
|
1173
|
+
let continuationTurnItems;
|
|
624
1174
|
for await (const event of this['continue']({ answer: 'y' })) {
|
|
625
1175
|
if (event.type === 'approval_required') {
|
|
626
1176
|
continuationApprovalUsage = event.usage;
|
|
@@ -649,7 +1199,9 @@ export class ConversationSession {
|
|
|
649
1199
|
if (event.commandMessages) {
|
|
650
1200
|
commandMessages.push(...event.commandMessages);
|
|
651
1201
|
}
|
|
652
|
-
|
|
1202
|
+
if (event.turnItems) {
|
|
1203
|
+
continuationTurnItems = event.turnItems;
|
|
1204
|
+
}
|
|
653
1205
|
}
|
|
654
1206
|
else {
|
|
655
1207
|
yield event;
|
|
@@ -669,6 +1221,7 @@ export class ConversationSession {
|
|
|
669
1221
|
finalText: finalText || 'Done.',
|
|
670
1222
|
...(reasoningText ? { reasoningText } : {}),
|
|
671
1223
|
...(combinedUsage && Object.keys(combinedUsage).length > 0 ? { usage: combinedUsage } : {}),
|
|
1224
|
+
turnItems: continuationTurnItems ?? this.currentPersistedTurnItems,
|
|
672
1225
|
};
|
|
673
1226
|
}
|
|
674
1227
|
}
|