@qduc/term2 0.1.4 → 0.1.6
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.map +1 -1
- package/dist/agent.js +4 -24
- package/dist/agent.js.map +1 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +12 -33
- package/dist/app.js.map +1 -1
- package/dist/app.parseInput.test.js +4 -4
- package/dist/app.parseInput.test.js.map +1 -1
- package/dist/cli.js +44 -29
- package/dist/cli.js.map +1 -1
- package/dist/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/components/ApprovalPrompt.js +14 -11
- package/dist/components/ApprovalPrompt.js.map +1 -1
- package/dist/components/Banner.d.ts.map +1 -1
- package/dist/components/Banner.js +4 -12
- package/dist/components/Banner.js.map +1 -1
- package/dist/components/BottomArea.d.ts +2 -0
- package/dist/components/BottomArea.d.ts.map +1 -1
- package/dist/components/BottomArea.js +6 -9
- package/dist/components/BottomArea.js.map +1 -1
- package/dist/components/BottomArea.test.js +4 -6
- package/dist/components/BottomArea.test.js.map +1 -1
- package/dist/components/ChatMessage.d.ts.map +1 -1
- package/dist/components/ChatMessage.js.map +1 -1
- package/dist/components/CommandMessage.d.ts.map +1 -1
- package/dist/components/CommandMessage.js +19 -30
- package/dist/components/CommandMessage.js.map +1 -1
- package/dist/components/CommandMessage.test.js +2 -2
- package/dist/components/CommandMessage.test.js.map +1 -1
- package/dist/components/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/ErrorBoundary.js +3 -9
- package/dist/components/ErrorBoundary.js.map +1 -1
- package/dist/components/ErrorBoundary.test.js +2 -2
- package/dist/components/ErrorBoundary.test.js.map +1 -1
- package/dist/components/Input/PopupManager.d.ts.map +1 -1
- package/dist/components/Input/PopupManager.js.map +1 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +15 -33
- package/dist/components/InputBox.js.map +1 -1
- package/dist/components/InputBox.menu-logic.test.js +6 -7
- package/dist/components/InputBox.menu-logic.test.js.map +1 -1
- package/dist/components/InputBox.test.js +7 -9
- package/dist/components/InputBox.test.js.map +1 -1
- package/dist/components/LiveResponse.d.ts.map +1 -1
- package/dist/components/LiveResponse.js.map +1 -1
- package/dist/components/MarkdownRenderer.d.ts.map +1 -1
- package/dist/components/MarkdownRenderer.js +12 -12
- package/dist/components/MarkdownRenderer.js.map +1 -1
- package/dist/components/MessageList.d.ts.map +1 -1
- package/dist/components/MessageList.js.map +1 -1
- package/dist/components/MessageList.test.js +1 -1
- package/dist/components/MessageList.test.js.map +1 -1
- package/dist/components/ModelSelectionMenu.d.ts.map +1 -1
- package/dist/components/ModelSelectionMenu.js +35 -31
- package/dist/components/ModelSelectionMenu.js.map +1 -1
- package/dist/components/ModelSelectionMenu.test.js +9 -9
- package/dist/components/ModelSelectionMenu.test.js.map +1 -1
- package/dist/components/PathSelectionMenu.d.ts.map +1 -1
- package/dist/components/PathSelectionMenu.js +1 -1
- package/dist/components/PathSelectionMenu.js.map +1 -1
- package/dist/components/SettingsSelectionMenu.d.ts.map +1 -1
- package/dist/components/SettingsSelectionMenu.js +1 -1
- package/dist/components/SettingsSelectionMenu.js.map +1 -1
- package/dist/components/SettingsSelectionMenu.test.js +4 -4
- package/dist/components/SettingsSelectionMenu.test.js.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.d.ts.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.js +5 -6
- package/dist/components/SettingsValueSelectionMenu.js.map +1 -1
- package/dist/components/SettingsValueSelectionMenu.test.js +5 -5
- package/dist/components/SettingsValueSelectionMenu.test.js.map +1 -1
- package/dist/components/SlashCommandMenu.d.ts.map +1 -1
- package/dist/components/SlashCommandMenu.js +1 -1
- package/dist/components/SlashCommandMenu.js.map +1 -1
- package/dist/components/StatusBar.d.ts +2 -0
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +45 -41
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/StatusBar.test.d.ts +2 -0
- package/dist/components/StatusBar.test.d.ts.map +1 -0
- package/dist/components/StatusBar.test.js +19 -0
- package/dist/components/StatusBar.test.js.map +1 -0
- package/dist/context/InputContext.d.ts.map +1 -1
- package/dist/context/InputContext.js.map +1 -1
- package/dist/context/InputContext.stability.test.js +1 -1
- package/dist/context/InputContext.stability.test.js.map +1 -1
- package/dist/context/InputContext.test.js +15 -15
- package/dist/context/InputContext.test.js.map +1 -1
- package/dist/hooks/use-conversation.d.ts +5 -13
- package/dist/hooks/use-conversation.d.ts.map +1 -1
- package/dist/hooks/use-conversation.js +40 -148
- package/dist/hooks/use-conversation.js.map +1 -1
- package/dist/hooks/use-input-history.d.ts.map +1 -1
- package/dist/hooks/use-input-history.js +1 -3
- package/dist/hooks/use-input-history.js.map +1 -1
- package/dist/hooks/use-model-selection.d.ts.map +1 -1
- package/dist/hooks/use-model-selection.js +9 -35
- package/dist/hooks/use-model-selection.js.map +1 -1
- package/dist/hooks/use-path-completion.d.ts.map +1 -1
- package/dist/hooks/use-path-completion.js +6 -6
- package/dist/hooks/use-path-completion.js.map +1 -1
- package/dist/hooks/use-setting.d.ts.map +1 -1
- package/dist/hooks/use-setting.js +3 -6
- package/dist/hooks/use-setting.js.map +1 -1
- package/dist/hooks/use-settings-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-completion.js +10 -12
- package/dist/hooks/use-settings-completion.js.map +1 -1
- package/dist/hooks/use-settings-completion.test.js +46 -46
- package/dist/hooks/use-settings-completion.test.js.map +1 -1
- package/dist/hooks/use-settings-value-completion.d.ts.map +1 -1
- package/dist/hooks/use-settings-value-completion.js +13 -43
- package/dist/hooks/use-settings-value-completion.js.map +1 -1
- package/dist/hooks/use-settings-value-completion.test.js +12 -18
- package/dist/hooks/use-settings-value-completion.test.js.map +1 -1
- package/dist/hooks/use-slash-commands.d.ts +1 -1
- package/dist/hooks/use-slash-commands.d.ts.map +1 -1
- package/dist/hooks/use-slash-commands.js +6 -11
- package/dist/hooks/use-slash-commands.js.map +1 -1
- package/dist/hooks/use-slash-commands.test.js +24 -24
- package/dist/hooks/use-slash-commands.test.js.map +1 -1
- package/dist/lib/editor-impl.d.ts.map +1 -1
- package/dist/lib/editor-impl.js +6 -16
- package/dist/lib/editor-impl.js.map +1 -1
- package/dist/lib/editor-impl.test.js.map +1 -1
- package/dist/lib/mentor-client.d.ts +41 -0
- package/dist/lib/mentor-client.d.ts.map +1 -0
- package/dist/lib/mentor-client.js +146 -0
- package/dist/lib/mentor-client.js.map +1 -0
- package/dist/lib/mentor-client.test.d.ts +2 -0
- package/dist/lib/mentor-client.test.d.ts.map +1 -0
- package/dist/lib/mentor-client.test.js +440 -0
- package/dist/lib/mentor-client.test.js.map +1 -0
- package/dist/lib/openai-agent-client.chat.test.js +33 -8
- package/dist/lib/openai-agent-client.chat.test.js.map +1 -1
- package/dist/lib/openai-agent-client.d.ts.map +1 -1
- package/dist/lib/openai-agent-client.flex-tier.test.js +5 -5
- package/dist/lib/openai-agent-client.flex-tier.test.js.map +1 -1
- package/dist/lib/openai-agent-client.js +99 -88
- package/dist/lib/openai-agent-client.js.map +1 -1
- package/dist/lib/openai-agent-client.public-methods.test.js +186 -12
- package/dist/lib/openai-agent-client.public-methods.test.js.map +1 -1
- package/dist/lib/openai-agent-client.test.js +17 -17
- package/dist/lib/openai-agent-client.test.js.map +1 -1
- package/dist/lib/retry-strategy.d.ts +43 -0
- package/dist/lib/retry-strategy.d.ts.map +1 -0
- package/dist/lib/retry-strategy.js +93 -0
- package/dist/lib/retry-strategy.js.map +1 -0
- package/dist/lib/retry-strategy.test.d.ts +2 -0
- package/dist/lib/retry-strategy.test.d.ts.map +1 -0
- package/dist/lib/retry-strategy.test.js +200 -0
- package/dist/lib/retry-strategy.test.js.map +1 -0
- package/dist/lib/tool-invoke.d.ts.map +1 -1
- package/dist/lib/tool-invoke.js.map +1 -1
- package/dist/lib/tool-invoke.test.js.map +1 -1
- package/dist/no-singleton-imports.test.js +1 -1
- package/dist/no-singleton-imports.test.js.map +1 -1
- package/dist/non-interactive.d.ts +20 -0
- package/dist/non-interactive.d.ts.map +1 -0
- package/dist/non-interactive.js +86 -0
- package/dist/non-interactive.js.map +1 -0
- package/dist/non-interactive.test.d.ts +2 -0
- package/dist/non-interactive.test.d.ts.map +1 -0
- package/dist/non-interactive.test.js +213 -0
- package/dist/non-interactive.test.js.map +1 -0
- package/dist/prompts/anthropic.md +11 -11
- package/dist/prompts/codex.md +63 -63
- package/dist/prompts/gpt-5.md +95 -95
- package/dist/prompts/mentor-addon.md +6 -5
- package/dist/prompts/prompt-selector.d.ts +8 -0
- package/dist/prompts/prompt-selector.d.ts.map +1 -0
- package/dist/prompts/prompt-selector.js +21 -0
- package/dist/prompts/prompt-selector.js.map +1 -0
- package/dist/prompts/prompt-selector.test.d.ts +2 -0
- package/dist/prompts/prompt-selector.test.d.ts.map +1 -0
- package/dist/prompts/prompt-selector.test.js +21 -0
- package/dist/prompts/prompt-selector.test.js.map +1 -0
- package/dist/prompts/prompt-selector.test.ts +32 -0
- package/dist/prompts/prompt-selector.ts +30 -0
- package/dist/prompts/simple.md +58 -58
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai-compatible/api.d.ts.map +1 -1
- package/dist/providers/openai-compatible/api.js.map +1 -1
- package/dist/providers/openai-compatible/model.d.ts.map +1 -1
- package/dist/providers/openai-compatible/model.js +19 -53
- package/dist/providers/openai-compatible/model.js.map +1 -1
- package/dist/providers/openai-compatible/provider.d.ts.map +1 -1
- package/dist/providers/openai-compatible/provider.js.map +1 -1
- package/dist/providers/openai-compatible/reasoning-content.test.js +2 -2
- package/dist/providers/openai-compatible/reasoning-content.test.js.map +1 -1
- package/dist/providers/openai-compatible/utils.d.ts.map +1 -1
- package/dist/providers/openai-compatible/utils.js.map +1 -1
- package/dist/providers/openai-compatible.provider.d.ts.map +1 -1
- package/dist/providers/openai-compatible.provider.js +5 -1
- package/dist/providers/openai-compatible.provider.js.map +1 -1
- package/dist/providers/openai.provider.js +4 -0
- package/dist/providers/openai.provider.js.map +1 -1
- package/dist/providers/openrouter/api.d.ts.map +1 -1
- package/dist/providers/openrouter/api.js +5 -13
- package/dist/providers/openrouter/api.js.map +1 -1
- package/dist/providers/openrouter/converters.d.ts.map +1 -1
- package/dist/providers/openrouter/converters.js +9 -28
- package/dist/providers/openrouter/converters.js.map +1 -1
- package/dist/providers/openrouter/converters.test.js +7 -11
- package/dist/providers/openrouter/converters.test.js.map +1 -1
- package/dist/providers/openrouter/index.d.ts.map +1 -1
- package/dist/providers/openrouter/index.js.map +1 -1
- package/dist/providers/openrouter/model.d.ts.map +1 -1
- package/dist/providers/openrouter/model.js +19 -55
- package/dist/providers/openrouter/model.js.map +1 -1
- package/dist/providers/openrouter/provider.d.ts.map +1 -1
- package/dist/providers/openrouter/provider.js.map +1 -1
- package/dist/providers/openrouter/reasoning-content.test.js +1 -1
- package/dist/providers/openrouter/reasoning-content.test.js.map +1 -1
- package/dist/providers/openrouter/utils.d.ts.map +1 -1
- package/dist/providers/openrouter/utils.js +2 -3
- package/dist/providers/openrouter/utils.js.map +1 -1
- package/dist/providers/openrouter.api.retry.test.js.map +1 -1
- package/dist/providers/openrouter.provider.createRunner.test.js +1 -1
- package/dist/providers/openrouter.provider.createRunner.test.js.map +1 -1
- package/dist/providers/openrouter.provider.js +6 -4
- package/dist/providers/openrouter.provider.js.map +1 -1
- package/dist/providers/openrouter.test.js +13 -17
- package/dist/providers/openrouter.test.js.map +1 -1
- package/dist/providers/registry.d.ts +5 -0
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/registry.test.js +11 -11
- package/dist/providers/registry.test.js.map +1 -1
- package/dist/providers/web-search/index.d.ts +1 -1
- package/dist/providers/web-search/index.d.ts.map +1 -1
- package/dist/providers/web-search/index.js.map +1 -1
- package/dist/providers/web-search/registry.d.ts.map +1 -1
- package/dist/providers/web-search/registry.js.map +1 -1
- package/dist/providers/web-search/registry.test.js +14 -14
- package/dist/providers/web-search/registry.test.js.map +1 -1
- package/dist/providers/web-search/tavily.provider.d.ts.map +1 -1
- package/dist/providers/web-search/tavily.provider.js +4 -4
- package/dist/providers/web-search/tavily.provider.js.map +1 -1
- package/dist/providers/web-search/tavily.provider.test.js +7 -7
- package/dist/providers/web-search/tavily.provider.test.js.map +1 -1
- package/dist/providers/web-search/types.d.ts.map +1 -1
- package/dist/scripts/extract-provider-traffic.d.ts +3 -0
- package/dist/scripts/extract-provider-traffic.d.ts.map +1 -0
- package/dist/scripts/extract-provider-traffic.js +32 -0
- package/dist/scripts/extract-provider-traffic.js.map +1 -0
- package/dist/services/approval-state.d.ts +24 -0
- package/dist/services/approval-state.d.ts.map +1 -0
- package/dist/services/approval-state.js +41 -0
- package/dist/services/approval-state.js.map +1 -0
- package/dist/services/approval-state.test.d.ts +2 -0
- package/dist/services/approval-state.test.d.ts.map +1 -0
- package/dist/services/approval-state.test.js +59 -0
- package/dist/services/approval-state.test.js.map +1 -0
- package/dist/services/command-message-streaming.d.ts +12 -0
- package/dist/services/command-message-streaming.d.ts.map +1 -0
- package/dist/services/command-message-streaming.js +68 -0
- package/dist/services/command-message-streaming.js.map +1 -0
- package/dist/services/command-message-streaming.test.d.ts +2 -0
- package/dist/services/command-message-streaming.test.d.ts.map +1 -0
- package/dist/services/command-message-streaming.test.js +78 -0
- package/dist/services/command-message-streaming.test.js.map +1 -0
- package/dist/services/conversation-events.d.ts +5 -13
- package/dist/services/conversation-events.d.ts.map +1 -1
- package/dist/services/conversation-integration.test.d.ts +2 -0
- package/dist/services/conversation-integration.test.d.ts.map +1 -0
- package/dist/services/conversation-integration.test.js +155 -0
- package/dist/services/conversation-integration.test.js.map +1 -0
- package/dist/services/conversation-result-builder.d.ts +41 -0
- package/dist/services/conversation-result-builder.d.ts.map +1 -0
- package/dist/services/conversation-result-builder.js +110 -0
- package/dist/services/conversation-result-builder.js.map +1 -0
- package/dist/services/conversation-result-builder.test.d.ts +2 -0
- package/dist/services/conversation-result-builder.test.d.ts.map +1 -0
- package/dist/services/conversation-result-builder.test.js +76 -0
- package/dist/services/conversation-result-builder.test.js.map +1 -0
- package/dist/services/conversation-service.d.ts +1 -1
- package/dist/services/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation-service.js.map +1 -1
- package/dist/services/conversation-session-reasoning.test.js +3 -3
- package/dist/services/conversation-session-reasoning.test.js.map +1 -1
- package/dist/services/conversation-session.d.ts +7 -17
- package/dist/services/conversation-session.d.ts.map +1 -1
- package/dist/services/conversation-session.js +290 -278
- package/dist/services/conversation-session.js.map +1 -1
- package/dist/services/conversation-session.usage.test.d.ts +2 -0
- package/dist/services/conversation-session.usage.test.d.ts.map +1 -0
- package/dist/services/conversation-session.usage.test.js +59 -0
- package/dist/services/conversation-session.usage.test.js.map +1 -0
- package/dist/services/conversation-store.d.ts.map +1 -1
- package/dist/services/conversation-store.js +3 -9
- package/dist/services/conversation-store.js.map +1 -1
- package/dist/services/conversation-store.test.js +17 -14
- package/dist/services/conversation-store.test.js.map +1 -1
- package/dist/services/execution-context.d.ts.map +1 -1
- package/dist/services/execution-context.js.map +1 -1
- package/dist/services/execution-context.test.js +7 -7
- package/dist/services/execution-context.test.js.map +1 -1
- package/dist/services/file-service.d.ts.map +1 -1
- package/dist/services/file-service.js +5 -9
- package/dist/services/file-service.js.map +1 -1
- package/dist/services/history-service.d.ts.map +1 -1
- package/dist/services/history-service.js +3 -7
- package/dist/services/history-service.js.map +1 -1
- package/dist/services/logging-contract.d.ts +74 -0
- package/dist/services/logging-contract.d.ts.map +1 -0
- package/dist/services/logging-contract.js +157 -0
- package/dist/services/logging-contract.js.map +1 -0
- package/dist/services/logging-contract.test.d.ts +2 -0
- package/dist/services/logging-contract.test.d.ts.map +1 -0
- package/dist/services/logging-contract.test.js +66 -0
- package/dist/services/logging-contract.test.js.map +1 -0
- package/dist/services/logging-service.d.ts +5 -0
- package/dist/services/logging-service.d.ts.map +1 -1
- package/dist/services/logging-service.js +93 -21
- package/dist/services/logging-service.js.map +1 -1
- package/dist/services/model-service.d.ts.map +1 -1
- package/dist/services/model-service.js +2 -2
- package/dist/services/model-service.js.map +1 -1
- package/dist/services/model-service.test.js +6 -6
- package/dist/services/model-service.test.js.map +1 -1
- package/dist/services/service-interfaces.d.ts.map +1 -1
- package/dist/services/settings-env.d.ts +9 -0
- package/dist/services/settings-env.d.ts.map +1 -0
- package/dist/services/settings-env.js +75 -0
- package/dist/services/settings-env.js.map +1 -0
- package/dist/services/settings-env.test.d.ts +2 -0
- package/dist/services/settings-env.test.d.ts.map +1 -0
- package/dist/services/settings-env.test.js +32 -0
- package/dist/services/settings-env.test.js.map +1 -0
- package/dist/services/settings-merger.d.ts +26 -0
- package/dist/services/settings-merger.d.ts.map +1 -0
- package/dist/services/settings-merger.js +122 -0
- package/dist/services/settings-merger.js.map +1 -0
- package/dist/services/settings-merger.test.d.ts +2 -0
- package/dist/services/settings-merger.test.d.ts.map +1 -0
- package/dist/services/settings-merger.test.js +26 -0
- package/dist/services/settings-merger.test.js.map +1 -0
- package/dist/services/settings-persistence.d.ts +32 -0
- package/dist/services/settings-persistence.d.ts.map +1 -0
- package/dist/services/settings-persistence.js +134 -0
- package/dist/services/settings-persistence.js.map +1 -0
- package/dist/services/settings-persistence.test.d.ts +2 -0
- package/dist/services/settings-persistence.test.d.ts.map +1 -0
- package/dist/services/settings-persistence.test.js +51 -0
- package/dist/services/settings-persistence.test.js.map +1 -0
- package/dist/services/settings-schema.d.ts +320 -0
- package/dist/services/settings-schema.d.ts.map +1 -0
- package/dist/services/settings-schema.js +272 -0
- package/dist/services/settings-schema.js.map +1 -0
- package/dist/services/settings-service.d.ts +4 -248
- package/dist/services/settings-service.d.ts.map +1 -1
- package/dist/services/settings-service.js +45 -641
- package/dist/services/settings-service.js.map +1 -1
- package/dist/services/settings-service.mock.d.ts.map +1 -1
- package/dist/services/settings-service.mock.js.map +1 -1
- package/dist/services/singleton-deprecation.test.js +2 -2
- package/dist/services/singleton-deprecation.test.js.map +1 -1
- package/dist/services/ssh-service.d.ts.map +1 -1
- package/dist/services/ssh-service.js +8 -7
- package/dist/services/ssh-service.js.map +1 -1
- package/dist/services/ssh-service.test.js +15 -13
- package/dist/services/ssh-service.test.js.map +1 -1
- package/dist/services/stream-event-parsing.d.ts +4 -0
- package/dist/services/stream-event-parsing.d.ts.map +1 -0
- package/dist/services/stream-event-parsing.js +76 -0
- package/dist/services/stream-event-parsing.js.map +1 -0
- package/dist/services/stream-event-parsing.test.d.ts +2 -0
- package/dist/services/stream-event-parsing.test.d.ts.map +1 -0
- package/dist/services/stream-event-parsing.test.js +59 -0
- package/dist/services/stream-event-parsing.test.js.map +1 -0
- package/dist/services/stream-event-processor.d.ts +32 -0
- package/dist/services/stream-event-processor.d.ts.map +1 -0
- package/dist/services/stream-event-processor.js +344 -0
- package/dist/services/stream-event-processor.js.map +1 -0
- package/dist/services/stream-event-processor.test.d.ts +2 -0
- package/dist/services/stream-event-processor.test.d.ts.map +1 -0
- package/dist/services/stream-event-processor.test.js +117 -0
- package/dist/services/stream-event-processor.test.js.map +1 -0
- package/dist/tools/apply-patch.d.ts.map +1 -1
- package/dist/tools/apply-patch.js +45 -35
- package/dist/tools/apply-patch.js.map +1 -1
- package/dist/tools/apply-patch.test.js +23 -0
- package/dist/tools/apply-patch.test.js.map +1 -1
- package/dist/tools/ask-mentor.d.ts.map +1 -1
- package/dist/tools/ask-mentor.js +5 -15
- package/dist/tools/ask-mentor.js.map +1 -1
- package/dist/tools/ask-mentor.test.js +1 -1
- package/dist/tools/ask-mentor.test.js.map +1 -1
- package/dist/tools/create-file.d.ts.map +1 -1
- package/dist/tools/create-file.js +2 -2
- package/dist/tools/create-file.js.map +1 -1
- package/dist/tools/create-file.test.js.map +1 -1
- package/dist/tools/edit-healing.d.ts.map +1 -1
- package/dist/tools/edit-healing.js +5 -4
- package/dist/tools/edit-healing.js.map +1 -1
- package/dist/tools/edit-healing.test.js.map +1 -1
- package/dist/tools/find-files.d.ts +1 -0
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +93 -24
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/find-files.test.js +46 -2
- package/dist/tools/find-files.test.js.map +1 -1
- package/dist/tools/format-helpers.d.ts.map +1 -1
- package/dist/tools/format-helpers.js +2 -6
- package/dist/tools/format-helpers.js.map +1 -1
- package/dist/tools/grep.d.ts +1 -1
- package/dist/tools/grep.d.ts.map +1 -1
- package/dist/tools/grep.js +6 -21
- package/dist/tools/grep.js.map +1 -1
- package/dist/tools/read-file.d.ts.map +1 -1
- package/dist/tools/read-file.js +3 -7
- package/dist/tools/read-file.js.map +1 -1
- package/dist/tools/read-file.test.js.map +1 -1
- package/dist/tools/search-replace.d.ts.map +1 -1
- package/dist/tools/search-replace.js +14 -31
- package/dist/tools/search-replace.js.map +1 -1
- package/dist/tools/search-replace.test.js.map +1 -1
- package/dist/tools/search.d.ts +1 -1
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +6 -16
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/shell.d.ts +1 -1
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +25 -51
- package/dist/tools/shell.js.map +1 -1
- package/dist/tools/shell.test.d.ts +2 -0
- package/dist/tools/shell.test.d.ts.map +1 -0
- package/dist/tools/shell.test.js +70 -0
- package/dist/tools/shell.test.js.map +1 -0
- package/dist/tools/tool-names.d.ts +3 -0
- package/dist/tools/tool-names.d.ts.map +1 -0
- package/dist/tools/tool-names.js +3 -0
- package/dist/tools/tool-names.js.map +1 -0
- package/dist/tools/tool-names.test.d.ts +2 -0
- package/dist/tools/tool-names.test.d.ts.map +1 -0
- package/dist/tools/tool-names.test.js +7 -0
- package/dist/tools/tool-names.test.js.map +1 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/utils.d.ts.map +1 -1
- package/dist/tools/utils.js +3 -8
- package/dist/tools/utils.js.map +1 -1
- package/dist/tools/web-fetch.d.ts +4 -4
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +32 -249
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/tools/web-fetch.test.js +3 -3
- package/dist/tools/web-fetch.test.js.map +1 -1
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +6 -10
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools/web-search.test.js +12 -14
- package/dist/tools/web-search.test.js.map +1 -1
- package/dist/types/messages.d.ts +29 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/dist/types/messages.js +2 -0
- package/dist/types/messages.js.map +1 -0
- package/dist/utils/command-logger.d.ts.map +1 -1
- package/dist/utils/command-logger.js.map +1 -1
- package/dist/utils/command-safety/constants.d.ts.map +1 -1
- package/dist/utils/command-safety/constants.js +1 -9
- package/dist/utils/command-safety/constants.js.map +1 -1
- package/dist/utils/command-safety/find-helpers.d.ts.map +1 -1
- package/dist/utils/command-safety/find-helpers.js +4 -9
- package/dist/utils/command-safety/find-helpers.js.map +1 -1
- package/dist/utils/command-safety/handlers/find-handler.d.ts.map +1 -1
- package/dist/utils/command-safety/handlers/find-handler.js +3 -10
- package/dist/utils/command-safety/handlers/find-handler.js.map +1 -1
- package/dist/utils/command-safety/handlers/git-handler.d.ts.map +1 -1
- package/dist/utils/command-safety/handlers/git-handler.js +2 -4
- package/dist/utils/command-safety/handlers/git-handler.js.map +1 -1
- package/dist/utils/command-safety/handlers/index.d.ts +1 -1
- package/dist/utils/command-safety/handlers/index.d.ts.map +1 -1
- package/dist/utils/command-safety/handlers/index.js.map +1 -1
- package/dist/utils/command-safety/handlers/sed-handler.d.ts.map +1 -1
- package/dist/utils/command-safety/handlers/sed-handler.js.map +1 -1
- package/dist/utils/command-safety/handlers/types.d.ts.map +1 -1
- package/dist/utils/command-safety/index.d.ts.map +1 -1
- package/dist/utils/command-safety/index.js +4 -10
- package/dist/utils/command-safety/index.js.map +1 -1
- package/dist/utils/command-safety/path-analysis.d.ts.map +1 -1
- package/dist/utils/command-safety/path-analysis.js +9 -20
- package/dist/utils/command-safety/path-analysis.js.map +1 -1
- package/dist/utils/command-safety/utils.d.ts.map +1 -1
- package/dist/utils/command-safety/utils.js +1 -3
- package/dist/utils/command-safety/utils.js.map +1 -1
- package/dist/utils/command-safety.find.test.js +44 -87
- package/dist/utils/command-safety.find.test.js.map +1 -1
- package/dist/utils/command-safety.path.test.js +32 -67
- package/dist/utils/command-safety.path.test.js.map +1 -1
- package/dist/utils/conversation-event-handler.d.ts +4 -16
- package/dist/utils/conversation-event-handler.d.ts.map +1 -1
- package/dist/utils/conversation-event-handler.js +4 -8
- package/dist/utils/conversation-event-handler.js.map +1 -1
- package/dist/utils/conversation-event-handler.test.js +16 -18
- package/dist/utils/conversation-event-handler.test.js.map +1 -1
- package/dist/utils/conversation-utils.d.ts.map +1 -1
- package/dist/utils/conversation-utils.js +5 -8
- package/dist/utils/conversation-utils.js.map +1 -1
- package/dist/utils/conversation-utils.test.js +45 -44
- package/dist/utils/conversation-utils.test.js.map +1 -1
- package/dist/utils/diff.d.ts.map +1 -1
- package/dist/utils/diff.js +2 -4
- package/dist/utils/diff.js.map +1 -1
- package/dist/utils/diff.test.js +12 -12
- package/dist/utils/diff.test.js.map +1 -1
- package/dist/utils/error-helpers.d.ts.map +1 -1
- package/dist/utils/error-helpers.js +2 -6
- package/dist/utils/error-helpers.js.map +1 -1
- package/dist/utils/error-helpers.test.js +32 -32
- package/dist/utils/error-helpers.test.js.map +1 -1
- package/dist/utils/execute-shell.d.ts.map +1 -1
- package/dist/utils/execute-shell.js.map +1 -1
- package/dist/utils/execute-shell.test.js.map +1 -1
- package/dist/utils/extract-command-messages.d.ts.map +1 -1
- package/dist/utils/extract-command-messages.js +16 -21
- package/dist/utils/extract-command-messages.js.map +1 -1
- package/dist/utils/ink-render-options.d.ts.map +1 -1
- package/dist/utils/ink-render-options.js.map +1 -1
- package/dist/utils/log-viewer-filters.d.ts +29 -0
- package/dist/utils/log-viewer-filters.d.ts.map +1 -0
- package/dist/utils/log-viewer-filters.js +49 -0
- package/dist/utils/log-viewer-filters.js.map +1 -0
- package/dist/utils/log-viewer-filters.test.d.ts +2 -0
- package/dist/utils/log-viewer-filters.test.d.ts.map +1 -0
- package/dist/utils/log-viewer-filters.test.js +48 -0
- package/dist/utils/log-viewer-filters.test.js.map +1 -0
- package/dist/utils/message-buffer.d.ts.map +1 -1
- package/dist/utils/message-buffer.js.map +1 -1
- package/dist/utils/message-buffer.test.js +4 -4
- package/dist/utils/message-buffer.test.js.map +1 -1
- package/dist/utils/output-trim.d.ts.map +1 -1
- package/dist/utils/output-trim.js.map +1 -1
- package/dist/utils/provider-credentials.d.ts.map +1 -1
- package/dist/utils/provider-credentials.js +1 -1
- package/dist/utils/provider-credentials.js.map +1 -1
- package/dist/utils/provider-traffic-extractor.d.ts +18 -0
- package/dist/utils/provider-traffic-extractor.d.ts.map +1 -0
- package/dist/utils/provider-traffic-extractor.js +121 -0
- package/dist/utils/provider-traffic-extractor.js.map +1 -0
- package/dist/utils/provider-traffic-extractor.test.d.ts +2 -0
- package/dist/utils/provider-traffic-extractor.test.d.ts.map +1 -0
- package/dist/utils/provider-traffic-extractor.test.js +84 -0
- package/dist/utils/provider-traffic-extractor.test.js.map +1 -0
- package/dist/utils/settings-command.d.ts.map +1 -1
- package/dist/utils/settings-command.js +5 -12
- package/dist/utils/settings-command.js.map +1 -1
- package/dist/utils/ssh-config-parser.d.ts.map +1 -1
- package/dist/utils/ssh-config-parser.js.map +1 -1
- package/dist/utils/ssh-config-parser.test.js.map +1 -1
- package/dist/utils/streaming-session-factory.d.ts +33 -0
- package/dist/utils/streaming-session-factory.d.ts.map +1 -0
- package/dist/utils/streaming-session-factory.js +75 -0
- package/dist/utils/streaming-session-factory.js.map +1 -0
- package/dist/utils/streaming-session-factory.test.d.ts +2 -0
- package/dist/utils/streaming-session-factory.test.d.ts.map +1 -0
- package/dist/utils/streaming-session-factory.test.js +74 -0
- package/dist/utils/streaming-session-factory.test.js.map +1 -0
- package/dist/utils/streaming-updater.d.ts.map +1 -1
- package/dist/utils/streaming-updater.js.map +1 -1
- package/dist/utils/throttle.d.ts.map +1 -1
- package/dist/utils/throttle.js.map +1 -1
- package/dist/utils/token-usage.d.ts +16 -0
- package/dist/utils/token-usage.d.ts.map +1 -0
- package/dist/utils/token-usage.js +109 -0
- package/dist/utils/token-usage.js.map +1 -0
- package/dist/utils/token-usage.test.d.ts +2 -0
- package/dist/utils/token-usage.test.d.ts.map +1 -0
- package/dist/utils/token-usage.test.js +38 -0
- package/dist/utils/token-usage.test.js.map +1 -0
- package/dist/utils/trim-tool-output.d.ts +2 -0
- package/dist/utils/trim-tool-output.d.ts.map +1 -0
- package/dist/utils/trim-tool-output.js +52 -0
- package/dist/utils/trim-tool-output.js.map +1 -0
- package/package.json +117 -110
- package/{README.md → readme.md} +208 -136
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { extractCommandMessages, markToolCallAsApprovalRejection
|
|
1
|
+
import { extractCommandMessages, markToolCallAsApprovalRejection } from '../utils/extract-command-messages.js';
|
|
2
2
|
import { ConversationStore } from './conversation-store.js';
|
|
3
3
|
import { ModelBehaviorError } from '@openai/agents';
|
|
4
|
+
import { extractUsage } from '../utils/token-usage.js';
|
|
5
|
+
import { getProvider } from '../providers/index.js';
|
|
6
|
+
import { extractReasoningDelta, extractTextDelta } from './stream-event-parsing.js';
|
|
7
|
+
import { captureToolCallArguments, emitCommandMessagesFromItems } from './command-message-streaming.js';
|
|
8
|
+
import { ApprovalState } from './approval-state.js';
|
|
9
|
+
import { createInvalidToolCallDiagnostic } from './logging-contract.js';
|
|
4
10
|
const getCommandFromArgs = (args) => {
|
|
5
11
|
if (!args) {
|
|
6
12
|
return '';
|
|
@@ -16,7 +22,7 @@ const getCommandFromArgs = (args) => {
|
|
|
16
22
|
if (Array.isArray(parsed?.commands)) {
|
|
17
23
|
return parsed.commands.join('\n');
|
|
18
24
|
}
|
|
19
|
-
return
|
|
25
|
+
return JSON.stringify(parsed);
|
|
20
26
|
}
|
|
21
27
|
catch {
|
|
22
28
|
return args;
|
|
@@ -29,7 +35,21 @@ const getCommandFromArgs = (args) => {
|
|
|
29
35
|
if ('commands' in args && Array.isArray(args.commands)) {
|
|
30
36
|
return args.commands.join('\n');
|
|
31
37
|
}
|
|
32
|
-
|
|
38
|
+
let argsFromObject;
|
|
39
|
+
if ('arguments' in args) {
|
|
40
|
+
const rawArguments = args.arguments;
|
|
41
|
+
if (typeof rawArguments === 'string') {
|
|
42
|
+
try {
|
|
43
|
+
argsFromObject = JSON.stringify(JSON.parse(rawArguments));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
argsFromObject = String(rawArguments);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else if (rawArguments !== undefined) {
|
|
50
|
+
argsFromObject = String(rawArguments);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
33
53
|
return cmdFromObject ?? argsFromObject ?? JSON.stringify(args);
|
|
34
54
|
}
|
|
35
55
|
return String(args);
|
|
@@ -48,19 +68,23 @@ const isToolHallucinationError = (error) => {
|
|
|
48
68
|
const message = error.message.toLowerCase();
|
|
49
69
|
return message.includes('tool') && message.includes('not found');
|
|
50
70
|
};
|
|
71
|
+
const supportsConversationChaining = (providerId) => {
|
|
72
|
+
const providerDef = getProvider(providerId);
|
|
73
|
+
return providerDef?.capabilities?.supportsConversationChaining ?? false;
|
|
74
|
+
};
|
|
51
75
|
export class ConversationSession {
|
|
52
76
|
id;
|
|
53
77
|
agentClient;
|
|
54
78
|
logger;
|
|
55
79
|
conversationStore;
|
|
56
80
|
previousResponseId = null;
|
|
57
|
-
|
|
58
|
-
abortedApprovalContext = null;
|
|
81
|
+
approvalState = new ApprovalState();
|
|
59
82
|
textDeltaCount = 0;
|
|
60
83
|
reasoningDeltaCount = 0;
|
|
61
84
|
toolCallArgumentsById = new Map();
|
|
62
85
|
lastEventType = null;
|
|
63
86
|
eventTypeCount = 0;
|
|
87
|
+
emittedInvalidToolCallPackets = new Set();
|
|
64
88
|
// private logStreamEvent = (eventType: string, eventData: any) => {
|
|
65
89
|
// if (eventData.item) {
|
|
66
90
|
// eventType = eventData.item.type;
|
|
@@ -97,7 +121,7 @@ export class ConversationSession {
|
|
|
97
121
|
this.lastEventType = null;
|
|
98
122
|
this.eventTypeCount = 0;
|
|
99
123
|
};
|
|
100
|
-
constructor(id, { agentClient, deps
|
|
124
|
+
constructor(id, { agentClient, deps }) {
|
|
101
125
|
this.id = id;
|
|
102
126
|
this.agentClient = agentClient;
|
|
103
127
|
this.logger = deps.logger;
|
|
@@ -106,8 +130,8 @@ export class ConversationSession {
|
|
|
106
130
|
reset() {
|
|
107
131
|
this.previousResponseId = null;
|
|
108
132
|
this.conversationStore.clear();
|
|
109
|
-
this.
|
|
110
|
-
this.
|
|
133
|
+
this.approvalState.clearPending();
|
|
134
|
+
this.approvalState.consumeAborted();
|
|
111
135
|
this.toolCallArgumentsById.clear();
|
|
112
136
|
if (typeof this.agentClient.clearConversations === 'function') {
|
|
113
137
|
this.agentClient.clearConversations();
|
|
@@ -145,10 +169,14 @@ export class ConversationSession {
|
|
|
145
169
|
abort() {
|
|
146
170
|
this.agentClient.abort();
|
|
147
171
|
// Save pending approval context so we can handle it in the next message
|
|
148
|
-
if (this.
|
|
149
|
-
this.
|
|
150
|
-
|
|
151
|
-
|
|
172
|
+
if (this.approvalState.abortPending()) {
|
|
173
|
+
this.logger.debug('Aborted approval - will handle rejection on next message', {
|
|
174
|
+
eventType: 'approval.aborted',
|
|
175
|
+
category: 'approval',
|
|
176
|
+
phase: 'abort',
|
|
177
|
+
sessionId: this.id,
|
|
178
|
+
traceId: this.logger.getCorrelationId(),
|
|
179
|
+
});
|
|
152
180
|
}
|
|
153
181
|
}
|
|
154
182
|
/**
|
|
@@ -159,34 +187,40 @@ export class ConversationSession {
|
|
|
159
187
|
async *run(text, { hallucinationRetryCount = 0, skipUserMessage = false, } = {}) {
|
|
160
188
|
let stream = null;
|
|
161
189
|
try {
|
|
190
|
+
this.logger.info('Conversation stream start', {
|
|
191
|
+
eventType: 'stream.started',
|
|
192
|
+
category: 'stream',
|
|
193
|
+
phase: 'request_start',
|
|
194
|
+
sessionId: this.id,
|
|
195
|
+
traceId: this.logger.getCorrelationId(),
|
|
196
|
+
});
|
|
197
|
+
const abortedContext = this.approvalState.consumeAborted();
|
|
198
|
+
const shouldAddUserMessage = !skipUserMessage && !abortedContext;
|
|
162
199
|
// Maintain canonical local history regardless of provider.
|
|
163
|
-
if (
|
|
200
|
+
if (shouldAddUserMessage) {
|
|
164
201
|
this.conversationStore.addUserMessage(text);
|
|
165
202
|
}
|
|
166
203
|
// If there's an aborted approval, we need to resolve it first.
|
|
167
204
|
// The user's message is a new input, but the agent is stuck waiting for tool output.
|
|
168
|
-
if (
|
|
205
|
+
if (abortedContext) {
|
|
169
206
|
this.logger.debug('Resolving aborted approval with fake execution', {
|
|
170
207
|
message: text,
|
|
171
208
|
});
|
|
172
|
-
const { state, interruption, emittedCommandIds, toolCallArgumentsById
|
|
173
|
-
this.abortedApprovalContext = null;
|
|
209
|
+
const { state, interruption, emittedCommandIds, toolCallArgumentsById } = abortedContext;
|
|
174
210
|
// Restore cached tool-call arguments captured before abort so continuation can attach them
|
|
175
211
|
this.toolCallArgumentsById.clear();
|
|
176
212
|
if (toolCallArgumentsById?.size) {
|
|
177
|
-
for (const [key, value
|
|
213
|
+
for (const [key, value] of toolCallArgumentsById.entries()) {
|
|
178
214
|
this.toolCallArgumentsById.set(key, value);
|
|
179
215
|
}
|
|
180
216
|
}
|
|
181
217
|
// Add interceptor for this tool execution
|
|
182
218
|
const toolName = interruption.name ?? 'unknown';
|
|
183
|
-
const expectedCallId = interruption.rawItem?.callId ??
|
|
184
|
-
interruption.callId;
|
|
219
|
+
const expectedCallId = interruption.rawItem?.callId ?? interruption.callId;
|
|
185
220
|
const rejectionMessage = `Tool execution was not approved. User provided new input instead: ${text}`;
|
|
186
221
|
const removeInterceptor = this.agentClient.addToolInterceptor(async (name, _params, toolCallId) => {
|
|
187
222
|
// Match both tool name and call ID for stricter matching
|
|
188
|
-
if (name === toolName &&
|
|
189
|
-
(!expectedCallId || toolCallId === expectedCallId)) {
|
|
223
|
+
if (name === toolName && (!expectedCallId || toolCallId === expectedCallId)) {
|
|
190
224
|
markToolCallAsApprovalRejection(toolCallId ?? expectedCallId);
|
|
191
225
|
return rejectionMessage;
|
|
192
226
|
}
|
|
@@ -201,6 +235,7 @@ export class ConversationSession {
|
|
|
201
235
|
finalOutput: '',
|
|
202
236
|
reasoningOutput: '',
|
|
203
237
|
emittedCommandIds: new Set(emittedCommandIds),
|
|
238
|
+
latestUsage: undefined,
|
|
204
239
|
};
|
|
205
240
|
yield* this.#streamEvents(stream, acc, {
|
|
206
241
|
preserveExistingToolArgs: true,
|
|
@@ -208,11 +243,10 @@ export class ConversationSession {
|
|
|
208
243
|
this.previousResponseId = stream.lastResponseId;
|
|
209
244
|
this.conversationStore.updateFromResult(stream);
|
|
210
245
|
// Check if another interruption occurred
|
|
211
|
-
if (stream.interruptions &&
|
|
212
|
-
stream.interruptions.length > 0) {
|
|
246
|
+
if (stream.interruptions && stream.interruptions.length > 0) {
|
|
213
247
|
this.logger.warn('Another interruption occurred after fake execution - handling as approval');
|
|
214
248
|
// Let the normal flow handle this
|
|
215
|
-
const result = this.#buildResult(stream, acc.finalOutput, acc.reasoningOutput, acc.emittedCommandIds);
|
|
249
|
+
const result = this.#buildResult(stream, acc.finalOutput, acc.reasoningOutput, acc.emittedCommandIds, acc.latestUsage);
|
|
216
250
|
// Re-emit the terminal event explicitly.
|
|
217
251
|
if (result.type === 'approval_required') {
|
|
218
252
|
const interruption = result.approval.rawInterruption;
|
|
@@ -236,19 +270,16 @@ export class ConversationSession {
|
|
|
236
270
|
yield {
|
|
237
271
|
type: 'final',
|
|
238
272
|
finalText: result.finalText,
|
|
239
|
-
...(result.reasoningText
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
...(result.commandMessages?.length
|
|
243
|
-
? { commandMessages: result.commandMessages }
|
|
244
|
-
: {}),
|
|
273
|
+
...(result.reasoningText ? { reasoningText: result.reasoningText } : {}),
|
|
274
|
+
...(result.commandMessages?.length ? { commandMessages: result.commandMessages } : {}),
|
|
275
|
+
...(result.usage ? { usage: result.usage } : {}),
|
|
245
276
|
};
|
|
246
277
|
}
|
|
247
278
|
return;
|
|
248
279
|
}
|
|
249
280
|
// Successfully resolved - agent should now have processed the fake rejection
|
|
250
281
|
this.logger.debug('Fake execution completed, agent received rejection message');
|
|
251
|
-
const result = this.#buildResult(stream, acc.finalOutput, acc.reasoningOutput, acc.emittedCommandIds);
|
|
282
|
+
const result = this.#buildResult(stream, acc.finalOutput, acc.reasoningOutput, acc.emittedCommandIds, acc.latestUsage);
|
|
252
283
|
if (result.type === 'approval_required') {
|
|
253
284
|
const interruption = result.approval.rawInterruption;
|
|
254
285
|
const callId = interruption?.rawItem?.callId ??
|
|
@@ -271,21 +302,16 @@ export class ConversationSession {
|
|
|
271
302
|
yield {
|
|
272
303
|
type: 'final',
|
|
273
304
|
finalText: result.finalText,
|
|
274
|
-
...(result.reasoningText
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
...(result.commandMessages?.length
|
|
278
|
-
? { commandMessages: result.commandMessages }
|
|
279
|
-
: {}),
|
|
305
|
+
...(result.reasoningText ? { reasoningText: result.reasoningText } : {}),
|
|
306
|
+
...(result.commandMessages?.length ? { commandMessages: result.commandMessages } : {}),
|
|
307
|
+
...(result.usage ? { usage: result.usage } : {}),
|
|
280
308
|
};
|
|
281
309
|
}
|
|
282
310
|
return;
|
|
283
311
|
}
|
|
284
312
|
catch (error) {
|
|
285
313
|
this.logger.warn('Error resolving aborted approval with fake execution', {
|
|
286
|
-
error: error instanceof Error
|
|
287
|
-
? error.message
|
|
288
|
-
: String(error),
|
|
314
|
+
error: error instanceof Error ? error.message : String(error),
|
|
289
315
|
});
|
|
290
316
|
// Fall through to normal message flow
|
|
291
317
|
}
|
|
@@ -298,17 +324,15 @@ export class ConversationSession {
|
|
|
298
324
|
const provider = typeof this.agentClient.getProvider === 'function'
|
|
299
325
|
? this.agentClient.getProvider()
|
|
300
326
|
: 'openai';
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
stream = await this.agentClient.startStream(provider !== 'openai'
|
|
304
|
-
? this.conversationStore.getHistory()
|
|
305
|
-
: text, {
|
|
327
|
+
const supportsChaining = supportsConversationChaining(provider);
|
|
328
|
+
stream = await this.agentClient.startStream(supportsChaining ? text : this.conversationStore.getHistory(), {
|
|
306
329
|
previousResponseId: this.previousResponseId,
|
|
307
330
|
});
|
|
308
331
|
const acc = {
|
|
309
332
|
finalOutput: '',
|
|
310
333
|
reasoningOutput: '',
|
|
311
334
|
emittedCommandIds: new Set(),
|
|
335
|
+
latestUsage: undefined,
|
|
312
336
|
};
|
|
313
337
|
yield* this.#streamEvents(stream, acc, {
|
|
314
338
|
preserveExistingToolArgs: false,
|
|
@@ -316,8 +340,16 @@ export class ConversationSession {
|
|
|
316
340
|
this.previousResponseId = stream.lastResponseId;
|
|
317
341
|
this.conversationStore.updateFromResult(stream);
|
|
318
342
|
// Build terminal event (approval_required or final)
|
|
319
|
-
const result = this.#buildResult(stream, acc.finalOutput || undefined, acc.reasoningOutput || undefined, acc.emittedCommandIds);
|
|
343
|
+
const result = this.#buildResult(stream, acc.finalOutput || undefined, acc.reasoningOutput || undefined, acc.emittedCommandIds, acc.latestUsage);
|
|
320
344
|
if (result.type === 'approval_required') {
|
|
345
|
+
this.logger.info('Tool approval required', {
|
|
346
|
+
eventType: 'approval.required',
|
|
347
|
+
category: 'approval',
|
|
348
|
+
phase: 'approval',
|
|
349
|
+
sessionId: this.id,
|
|
350
|
+
traceId: this.logger.getCorrelationId(),
|
|
351
|
+
toolName: result.approval.toolName,
|
|
352
|
+
});
|
|
321
353
|
const interruption = result.approval.rawInterruption;
|
|
322
354
|
const callId = interruption?.rawItem?.callId ??
|
|
323
355
|
interruption?.callId ??
|
|
@@ -339,26 +371,26 @@ export class ConversationSession {
|
|
|
339
371
|
yield {
|
|
340
372
|
type: 'final',
|
|
341
373
|
finalText: result.finalText,
|
|
342
|
-
...(result.reasoningText
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
...(result.commandMessages?.length
|
|
346
|
-
? { commandMessages: result.commandMessages }
|
|
347
|
-
: {}),
|
|
374
|
+
...(result.reasoningText ? { reasoningText: result.reasoningText } : {}),
|
|
375
|
+
...(result.commandMessages?.length ? { commandMessages: result.commandMessages } : {}),
|
|
376
|
+
...(result.usage ? { usage: result.usage } : {}),
|
|
348
377
|
};
|
|
349
378
|
}
|
|
350
379
|
catch (error) {
|
|
351
380
|
// Handle tool hallucination: model called a non-existent tool
|
|
352
|
-
if (isToolHallucinationError(error) &&
|
|
353
|
-
|
|
354
|
-
const toolName = error instanceof Error
|
|
355
|
-
? error.message.match(/Tool (\S+) not found/)?.[1] ||
|
|
356
|
-
'unknown'
|
|
357
|
-
: 'unknown';
|
|
381
|
+
if (isToolHallucinationError(error) && hallucinationRetryCount < MAX_HALLUCINATION_RETRIES) {
|
|
382
|
+
const toolName = error instanceof Error ? error.message.match(/Tool (\S+) not found/)?.[1] || 'unknown' : 'unknown';
|
|
358
383
|
this.logger.warn('Tool hallucination detected, retrying', {
|
|
384
|
+
eventType: 'retry.hallucination',
|
|
385
|
+
category: 'retry',
|
|
386
|
+
phase: 'retry',
|
|
359
387
|
toolName,
|
|
388
|
+
retryType: 'hallucination',
|
|
389
|
+
retryAttempt: hallucinationRetryCount + 1,
|
|
360
390
|
attempt: hallucinationRetryCount + 1,
|
|
361
391
|
maxRetries: MAX_HALLUCINATION_RETRIES,
|
|
392
|
+
sessionId: this.id,
|
|
393
|
+
traceId: this.logger.getCorrelationId(),
|
|
362
394
|
errorMessage: error instanceof Error ? error.message : String(error),
|
|
363
395
|
});
|
|
364
396
|
yield {
|
|
@@ -391,6 +423,14 @@ export class ConversationSession {
|
|
|
391
423
|
type: 'error',
|
|
392
424
|
message: error instanceof Error ? error.message : String(error),
|
|
393
425
|
};
|
|
426
|
+
this.logger.error('Conversation stream error', {
|
|
427
|
+
eventType: 'stream.failed',
|
|
428
|
+
category: 'stream',
|
|
429
|
+
phase: 'abort',
|
|
430
|
+
sessionId: this.id,
|
|
431
|
+
traceId: this.logger.getCorrelationId(),
|
|
432
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
433
|
+
});
|
|
394
434
|
throw error;
|
|
395
435
|
}
|
|
396
436
|
}
|
|
@@ -400,23 +440,31 @@ export class ConversationSession {
|
|
|
400
440
|
* Named as a string-literal because `continue` is a keyword.
|
|
401
441
|
*/
|
|
402
442
|
async *['continue']({ answer, rejectionReason, }) {
|
|
403
|
-
|
|
443
|
+
const pendingApprovalContext = this.approvalState.getPending();
|
|
444
|
+
if (!pendingApprovalContext) {
|
|
404
445
|
return;
|
|
405
446
|
}
|
|
406
|
-
const { state, interruption, emittedCommandIds: previouslyEmittedIds, toolCallArgumentsById, } =
|
|
447
|
+
const { state, interruption, emittedCommandIds: previouslyEmittedIds, toolCallArgumentsById, } = pendingApprovalContext;
|
|
448
|
+
let removeInterceptor = null;
|
|
407
449
|
if (answer === 'y') {
|
|
450
|
+
this.logger.info('Tool approval granted', {
|
|
451
|
+
eventType: 'approval.granted',
|
|
452
|
+
category: 'approval',
|
|
453
|
+
phase: 'approval',
|
|
454
|
+
sessionId: this.id,
|
|
455
|
+
traceId: this.logger.getCorrelationId(),
|
|
456
|
+
});
|
|
408
457
|
state.approve(interruption);
|
|
409
458
|
}
|
|
410
459
|
else {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
460
|
+
const toolName = interruption.name ?? 'unknown';
|
|
461
|
+
const expectedCallId = interruption.rawItem?.callId ?? interruption.callId;
|
|
462
|
+
const rejectionMessage = rejectionReason
|
|
463
|
+
? `Tool execution was not approved. User's reason: ${rejectionReason}`
|
|
464
|
+
: 'Tool execution was not approved.';
|
|
465
|
+
if (typeof this.agentClient.addToolInterceptor === 'function') {
|
|
417
466
|
const removeInterceptor = this.agentClient.addToolInterceptor(async (name, _params, toolCallId) => {
|
|
418
|
-
if (name === toolName &&
|
|
419
|
-
(!expectedCallId || toolCallId === expectedCallId)) {
|
|
467
|
+
if (name === toolName && (!expectedCallId || toolCallId === expectedCallId)) {
|
|
420
468
|
markToolCallAsApprovalRejection(toolCallId ?? expectedCallId);
|
|
421
469
|
return rejectionMessage;
|
|
422
470
|
}
|
|
@@ -425,15 +473,21 @@ export class ConversationSession {
|
|
|
425
473
|
// Approve to continue but interceptor will return rejection message
|
|
426
474
|
state.approve(interruption);
|
|
427
475
|
// Store interceptor cleanup for after stream
|
|
428
|
-
this.
|
|
429
|
-
...this.pendingApprovalContext,
|
|
430
|
-
removeInterceptor,
|
|
431
|
-
};
|
|
476
|
+
this.approvalState.setPendingRemoveInterceptor(removeInterceptor);
|
|
432
477
|
}
|
|
433
478
|
else {
|
|
479
|
+
// Fallback for clients without tool interceptors
|
|
434
480
|
state.reject(interruption);
|
|
435
481
|
}
|
|
482
|
+
this.logger.info('Tool approval rejected', {
|
|
483
|
+
eventType: 'approval.rejected',
|
|
484
|
+
category: 'approval',
|
|
485
|
+
phase: 'approval',
|
|
486
|
+
sessionId: this.id,
|
|
487
|
+
traceId: this.logger.getCorrelationId(),
|
|
488
|
+
});
|
|
436
489
|
}
|
|
490
|
+
removeInterceptor = this.approvalState.getPending()?.removeInterceptor ?? null;
|
|
437
491
|
// Restore cached tool-call arguments so continuation outputs can attach them
|
|
438
492
|
this.toolCallArgumentsById.clear();
|
|
439
493
|
if (toolCallArgumentsById?.size) {
|
|
@@ -449,6 +503,7 @@ export class ConversationSession {
|
|
|
449
503
|
finalOutput: '',
|
|
450
504
|
reasoningOutput: '',
|
|
451
505
|
emittedCommandIds: new Set(),
|
|
506
|
+
latestUsage: undefined,
|
|
452
507
|
};
|
|
453
508
|
yield* this.#streamEvents(stream, acc, {
|
|
454
509
|
preserveExistingToolArgs: true,
|
|
@@ -457,12 +512,17 @@ export class ConversationSession {
|
|
|
457
512
|
this.conversationStore.updateFromResult(stream);
|
|
458
513
|
// Merge previously emitted command IDs with newly emitted ones
|
|
459
514
|
// This prevents duplicates when result.history contains commands from the initial stream
|
|
460
|
-
const allEmittedIds = new Set([
|
|
461
|
-
|
|
462
|
-
...acc.emittedCommandIds,
|
|
463
|
-
]);
|
|
464
|
-
const result = this.#buildResult(stream, acc.finalOutput || undefined, acc.reasoningOutput || undefined, allEmittedIds);
|
|
515
|
+
const allEmittedIds = new Set([...previouslyEmittedIds, ...acc.emittedCommandIds]);
|
|
516
|
+
const result = this.#buildResult(stream, acc.finalOutput || undefined, acc.reasoningOutput || undefined, allEmittedIds, acc.latestUsage);
|
|
465
517
|
if (result.type === 'approval_required') {
|
|
518
|
+
this.logger.info('Tool approval required', {
|
|
519
|
+
eventType: 'approval.required',
|
|
520
|
+
category: 'approval',
|
|
521
|
+
phase: 'approval',
|
|
522
|
+
sessionId: this.id,
|
|
523
|
+
traceId: this.logger.getCorrelationId(),
|
|
524
|
+
toolName: result.approval.toolName,
|
|
525
|
+
});
|
|
466
526
|
const interruption = result.approval.rawInterruption;
|
|
467
527
|
const callId = interruption?.rawItem?.callId ??
|
|
468
528
|
interruption?.callId ??
|
|
@@ -484,12 +544,9 @@ export class ConversationSession {
|
|
|
484
544
|
yield {
|
|
485
545
|
type: 'final',
|
|
486
546
|
finalText: result.finalText,
|
|
487
|
-
...(result.reasoningText
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
...(result.commandMessages?.length
|
|
491
|
-
? { commandMessages: result.commandMessages }
|
|
492
|
-
: {}),
|
|
547
|
+
...(result.reasoningText ? { reasoningText: result.reasoningText } : {}),
|
|
548
|
+
...(result.commandMessages?.length ? { commandMessages: result.commandMessages } : {}),
|
|
549
|
+
...(result.usage ? { usage: result.usage } : {}),
|
|
493
550
|
};
|
|
494
551
|
}
|
|
495
552
|
catch (error) {
|
|
@@ -501,16 +558,14 @@ export class ConversationSession {
|
|
|
501
558
|
}
|
|
502
559
|
finally {
|
|
503
560
|
// Clean up interceptor if one was added for rejection reason
|
|
504
|
-
|
|
505
|
-
this.pendingApprovalContext?.removeInterceptor) {
|
|
506
|
-
this.pendingApprovalContext.removeInterceptor();
|
|
507
|
-
}
|
|
561
|
+
removeInterceptor?.();
|
|
508
562
|
}
|
|
509
563
|
}
|
|
510
564
|
async sendMessage(text, { onTextChunk, onReasoningChunk, onCommandMessage, onEvent, hallucinationRetryCount = 0, } = {}) {
|
|
511
565
|
let finalText = '';
|
|
512
566
|
let reasoningText = '';
|
|
513
567
|
const commandMessages = [];
|
|
568
|
+
let usage;
|
|
514
569
|
let sawTerminalEvent = null;
|
|
515
570
|
for await (const event of this.run(text, { hallucinationRetryCount })) {
|
|
516
571
|
onEvent?.(event);
|
|
@@ -532,7 +587,7 @@ export class ConversationSession {
|
|
|
532
587
|
case 'approval_required': {
|
|
533
588
|
sawTerminalEvent = event;
|
|
534
589
|
// pendingApprovalContext is set inside #buildResult during run()
|
|
535
|
-
const rawInterruption = this.
|
|
590
|
+
const rawInterruption = this.approvalState.getPending()?.interruption;
|
|
536
591
|
return {
|
|
537
592
|
type: 'approval_required',
|
|
538
593
|
approval: {
|
|
@@ -547,6 +602,12 @@ export class ConversationSession {
|
|
|
547
602
|
sawTerminalEvent = event;
|
|
548
603
|
finalText = event.finalText;
|
|
549
604
|
reasoningText = event.reasoningText ?? '';
|
|
605
|
+
usage = event.usage;
|
|
606
|
+
this.logger.debug('sendMessage received final event', {
|
|
607
|
+
sessionId: this.id,
|
|
608
|
+
hasUsage: Boolean(event.usage),
|
|
609
|
+
usage: event.usage,
|
|
610
|
+
});
|
|
550
611
|
if (event.commandMessages?.length) {
|
|
551
612
|
for (const msg of event.commandMessages) {
|
|
552
613
|
commandMessages.push(msg);
|
|
@@ -566,20 +627,28 @@ export class ConversationSession {
|
|
|
566
627
|
if (!sawTerminalEvent) {
|
|
567
628
|
finalText = finalText || 'Done.';
|
|
568
629
|
}
|
|
569
|
-
|
|
630
|
+
const response = {
|
|
570
631
|
type: 'response',
|
|
571
632
|
commandMessages,
|
|
572
633
|
finalText: finalText || 'Done.',
|
|
573
634
|
...(reasoningText ? { reasoningText } : {}),
|
|
635
|
+
...(usage ? { usage } : {}),
|
|
574
636
|
};
|
|
637
|
+
this.logger.debug('sendMessage returning response', {
|
|
638
|
+
sessionId: this.id,
|
|
639
|
+
hasUsage: Boolean(usage),
|
|
640
|
+
usage,
|
|
641
|
+
});
|
|
642
|
+
return response;
|
|
575
643
|
}
|
|
576
644
|
async handleApprovalDecision(answer, rejectionReason, { onTextChunk, onReasoningChunk, onCommandMessage, onEvent, } = {}) {
|
|
577
|
-
if (!this.
|
|
645
|
+
if (!this.approvalState.getPending()) {
|
|
578
646
|
return null;
|
|
579
647
|
}
|
|
580
648
|
let finalText = '';
|
|
581
649
|
let reasoningText = '';
|
|
582
650
|
const commandMessages = [];
|
|
651
|
+
let usage;
|
|
583
652
|
let sawTerminalEvent = null;
|
|
584
653
|
for await (const event of this['continue']({ answer, rejectionReason })) {
|
|
585
654
|
onEvent?.(event);
|
|
@@ -600,7 +669,7 @@ export class ConversationSession {
|
|
|
600
669
|
}
|
|
601
670
|
case 'approval_required': {
|
|
602
671
|
sawTerminalEvent = event;
|
|
603
|
-
const rawInterruption = this.
|
|
672
|
+
const rawInterruption = this.approvalState.getPending()?.interruption;
|
|
604
673
|
return {
|
|
605
674
|
type: 'approval_required',
|
|
606
675
|
approval: {
|
|
@@ -615,6 +684,12 @@ export class ConversationSession {
|
|
|
615
684
|
sawTerminalEvent = event;
|
|
616
685
|
finalText = event.finalText;
|
|
617
686
|
reasoningText = event.reasoningText ?? '';
|
|
687
|
+
usage = event.usage;
|
|
688
|
+
this.logger.debug('handleApprovalDecision received final event', {
|
|
689
|
+
sessionId: this.id,
|
|
690
|
+
hasUsage: Boolean(event.usage),
|
|
691
|
+
usage: event.usage,
|
|
692
|
+
});
|
|
618
693
|
if (event.commandMessages?.length) {
|
|
619
694
|
for (const msg of event.commandMessages) {
|
|
620
695
|
commandMessages.push(msg);
|
|
@@ -630,19 +705,33 @@ export class ConversationSession {
|
|
|
630
705
|
}
|
|
631
706
|
}
|
|
632
707
|
if (!sawTerminalEvent) {
|
|
633
|
-
|
|
708
|
+
const response = {
|
|
634
709
|
type: 'response',
|
|
635
710
|
commandMessages,
|
|
636
711
|
finalText: finalText || 'Done.',
|
|
637
712
|
...(reasoningText ? { reasoningText } : {}),
|
|
713
|
+
...(usage ? { usage } : {}),
|
|
638
714
|
};
|
|
715
|
+
this.logger.debug('handleApprovalDecision returning response', {
|
|
716
|
+
sessionId: this.id,
|
|
717
|
+
hasUsage: Boolean(usage),
|
|
718
|
+
usage,
|
|
719
|
+
});
|
|
720
|
+
return response;
|
|
639
721
|
}
|
|
640
|
-
|
|
722
|
+
const response = {
|
|
641
723
|
type: 'response',
|
|
642
724
|
commandMessages,
|
|
643
725
|
finalText: finalText || 'Done.',
|
|
644
726
|
...(reasoningText ? { reasoningText } : {}),
|
|
727
|
+
...(usage ? { usage } : {}),
|
|
645
728
|
};
|
|
729
|
+
this.logger.debug('handleApprovalDecision returning response', {
|
|
730
|
+
sessionId: this.id,
|
|
731
|
+
hasUsage: Boolean(usage),
|
|
732
|
+
usage,
|
|
733
|
+
});
|
|
734
|
+
return response;
|
|
646
735
|
}
|
|
647
736
|
async *#streamEvents(stream, acc, { preserveExistingToolArgs }) {
|
|
648
737
|
const toolCallArgumentsById = this.toolCallArgumentsById;
|
|
@@ -676,21 +765,26 @@ export class ConversationSession {
|
|
|
676
765
|
};
|
|
677
766
|
};
|
|
678
767
|
for await (const event of stream) {
|
|
768
|
+
// Extract usage if present in any of the common locations
|
|
769
|
+
const usage = extractUsage(event);
|
|
770
|
+
if (usage) {
|
|
771
|
+
acc.latestUsage = usage;
|
|
772
|
+
this.logger.debug('Usage extracted from stream event', {
|
|
773
|
+
sessionId: this.id,
|
|
774
|
+
source: 'stream_event',
|
|
775
|
+
eventType: event?.type ?? event?.data?.type ?? 'unknown',
|
|
776
|
+
usage,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
679
779
|
// Log event type with deduplication for ordering understanding
|
|
680
|
-
|
|
681
|
-
// this.logStreamEvent(eventType, {
|
|
682
|
-
// eventName: event?.name,
|
|
683
|
-
// hasData: !!event?.data,
|
|
684
|
-
// item: event?.item,
|
|
685
|
-
// });
|
|
686
|
-
const delta1 = this.#extractTextDelta(event);
|
|
780
|
+
const delta1 = extractTextDelta(event);
|
|
687
781
|
if (delta1) {
|
|
688
782
|
const e = emitText(delta1);
|
|
689
783
|
if (e)
|
|
690
784
|
yield e;
|
|
691
785
|
}
|
|
692
786
|
if (event?.data) {
|
|
693
|
-
const delta2 =
|
|
787
|
+
const delta2 = extractTextDelta(event.data);
|
|
694
788
|
if (delta2) {
|
|
695
789
|
const e = emitText(delta2);
|
|
696
790
|
if (e)
|
|
@@ -698,71 +792,25 @@ export class ConversationSession {
|
|
|
698
792
|
}
|
|
699
793
|
}
|
|
700
794
|
// Handle reasoning items
|
|
701
|
-
const reasoningDelta = (
|
|
702
|
-
// OpenAI style
|
|
703
|
-
const data = event?.data;
|
|
704
|
-
if (data &&
|
|
705
|
-
typeof data === 'object' &&
|
|
706
|
-
data.type === 'model') {
|
|
707
|
-
const eventDetail = data.event;
|
|
708
|
-
if (eventDetail &&
|
|
709
|
-
typeof eventDetail === 'object' &&
|
|
710
|
-
eventDetail.type ===
|
|
711
|
-
'response.reasoning_summary_text.delta') {
|
|
712
|
-
return eventDetail.delta ?? '';
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
// OpenRouter style
|
|
716
|
-
const choices = event?.data?.event?.choices;
|
|
717
|
-
if (!choices)
|
|
718
|
-
return '';
|
|
719
|
-
if (Array.isArray(choices)) {
|
|
720
|
-
return choices[0]?.delta?.reasoning ?? choices[0]?.delta?.reasoning_content ?? '';
|
|
721
|
-
}
|
|
722
|
-
if (typeof choices === 'object') {
|
|
723
|
-
const byZero = choices['0'];
|
|
724
|
-
const first = byZero ?? choices[Object.keys(choices)[0]];
|
|
725
|
-
return first?.delta?.reasoning ?? first?.delta?.reasoning_content ?? '';
|
|
726
|
-
}
|
|
727
|
-
return '';
|
|
728
|
-
})();
|
|
795
|
+
const reasoningDelta = extractReasoningDelta(event);
|
|
729
796
|
if (reasoningDelta) {
|
|
730
797
|
const e = emitReasoning(reasoningDelta);
|
|
731
798
|
if (e)
|
|
732
799
|
yield e;
|
|
733
800
|
}
|
|
734
|
-
const maybeEmitCommandMessagesFromItems = (items) => {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
for (const cmdMsg of commandMessages) {
|
|
739
|
-
if (acc.emittedCommandIds.has(cmdMsg.id)) {
|
|
740
|
-
continue;
|
|
741
|
-
}
|
|
742
|
-
if (cmdMsg.isApprovalRejection) {
|
|
743
|
-
continue;
|
|
744
|
-
}
|
|
745
|
-
acc.emittedCommandIds.add(cmdMsg.id);
|
|
746
|
-
out.push({ type: 'command_message', message: cmdMsg });
|
|
747
|
-
}
|
|
748
|
-
return out;
|
|
749
|
-
};
|
|
801
|
+
const maybeEmitCommandMessagesFromItems = (items) => emitCommandMessagesFromItems(items, {
|
|
802
|
+
toolCallArgumentsById,
|
|
803
|
+
emittedCommandIds: acc.emittedCommandIds,
|
|
804
|
+
});
|
|
750
805
|
if (event?.type === 'run_item_stream_event') {
|
|
751
|
-
|
|
806
|
+
captureToolCallArguments(event.item, toolCallArgumentsById);
|
|
752
807
|
// Emit tool_started event when a function_call is detected
|
|
753
808
|
const rawItem = event.item?.rawItem ?? event.item;
|
|
754
809
|
if (rawItem?.type === 'function_call') {
|
|
755
|
-
const callId = rawItem.callId ??
|
|
756
|
-
rawItem.call_id ??
|
|
757
|
-
rawItem.tool_call_id ??
|
|
758
|
-
rawItem.toolCallId ??
|
|
759
|
-
rawItem.id;
|
|
810
|
+
const callId = rawItem.callId ?? rawItem.call_id ?? rawItem.tool_call_id ?? rawItem.toolCallId ?? rawItem.id;
|
|
760
811
|
if (callId) {
|
|
761
812
|
const toolName = rawItem.name ?? event.item?.name;
|
|
762
|
-
const args = rawItem.arguments ??
|
|
763
|
-
rawItem.args ??
|
|
764
|
-
event.item?.arguments ??
|
|
765
|
-
event.item?.args;
|
|
813
|
+
const args = rawItem.arguments ?? rawItem.args ?? event.item?.arguments ?? event.item?.args;
|
|
766
814
|
// Providers sometimes surface arguments as a JSON string.
|
|
767
815
|
// Normalize here so downstream UI (pending/running display)
|
|
768
816
|
// can reliably render parameters.
|
|
@@ -778,6 +826,30 @@ export class ConversationSession {
|
|
|
778
826
|
return JSON.parse(trimmed);
|
|
779
827
|
}
|
|
780
828
|
catch {
|
|
829
|
+
if ((trimmed.startsWith('{') || trimmed.startsWith('[')) &&
|
|
830
|
+
!this.emittedInvalidToolCallPackets.has(String(callId))) {
|
|
831
|
+
this.emittedInvalidToolCallPackets.add(String(callId));
|
|
832
|
+
const diagnostic = createInvalidToolCallDiagnostic({
|
|
833
|
+
toolName: toolName ?? 'unknown',
|
|
834
|
+
toolCallId: String(callId),
|
|
835
|
+
rawPayload: trimmed,
|
|
836
|
+
normalizedToolCall: {
|
|
837
|
+
toolName: toolName ?? 'unknown',
|
|
838
|
+
toolCallId: String(callId),
|
|
839
|
+
arguments: args,
|
|
840
|
+
},
|
|
841
|
+
validationErrors: ['arguments must be valid JSON'],
|
|
842
|
+
traceId: this.logger.getCorrelationId() ?? 'trace-unknown',
|
|
843
|
+
retryContext: {
|
|
844
|
+
sessionId: this.id,
|
|
845
|
+
},
|
|
846
|
+
});
|
|
847
|
+
this.logger.error('Invalid tool call argument payload', {
|
|
848
|
+
...diagnostic,
|
|
849
|
+
sessionId: this.id,
|
|
850
|
+
messageId: String(callId),
|
|
851
|
+
});
|
|
852
|
+
}
|
|
781
853
|
return args;
|
|
782
854
|
}
|
|
783
855
|
})();
|
|
@@ -787,147 +859,86 @@ export class ConversationSession {
|
|
|
787
859
|
toolName: toolName ?? 'unknown',
|
|
788
860
|
arguments: normalizedArgs,
|
|
789
861
|
};
|
|
862
|
+
this.logger.info('Tool execution started', {
|
|
863
|
+
eventType: 'tool_call.execution_started',
|
|
864
|
+
category: 'tool',
|
|
865
|
+
phase: 'execution',
|
|
866
|
+
sessionId: this.id,
|
|
867
|
+
traceId: this.logger.getCorrelationId(),
|
|
868
|
+
toolName: toolName ?? 'unknown',
|
|
869
|
+
toolCallId: String(callId),
|
|
870
|
+
messageId: String(callId),
|
|
871
|
+
});
|
|
790
872
|
}
|
|
791
873
|
}
|
|
792
|
-
for (const e of maybeEmitCommandMessagesFromItems([
|
|
793
|
-
event.item,
|
|
794
|
-
])) {
|
|
874
|
+
for (const e of maybeEmitCommandMessagesFromItems([event.item])) {
|
|
795
875
|
yield e;
|
|
796
876
|
}
|
|
797
877
|
}
|
|
798
|
-
else if (event?.type === 'tool_call_output_item' ||
|
|
799
|
-
event
|
|
800
|
-
this.#captureToolCallArguments(event, toolCallArgumentsById);
|
|
878
|
+
else if (event?.type === 'tool_call_output_item' || event?.rawItem?.type === 'function_call_output') {
|
|
879
|
+
captureToolCallArguments(event, toolCallArgumentsById);
|
|
801
880
|
for (const e of maybeEmitCommandMessagesFromItems([event])) {
|
|
802
881
|
yield e;
|
|
803
882
|
}
|
|
804
883
|
}
|
|
805
884
|
}
|
|
806
|
-
await stream.completed;
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
if (rawItem?.type !== 'function_call') {
|
|
815
|
-
return;
|
|
816
|
-
}
|
|
817
|
-
const callId = rawItem.callId ??
|
|
818
|
-
rawItem.call_id ??
|
|
819
|
-
rawItem.tool_call_id ??
|
|
820
|
-
rawItem.toolCallId ??
|
|
821
|
-
rawItem.id;
|
|
822
|
-
if (!callId) {
|
|
823
|
-
return;
|
|
824
|
-
}
|
|
825
|
-
const args = rawItem.arguments ?? rawItem.args ?? item?.arguments ?? item?.args;
|
|
826
|
-
if (!args) {
|
|
827
|
-
return;
|
|
828
|
-
}
|
|
829
|
-
toolCallArgumentsById.set(callId, args);
|
|
830
|
-
}
|
|
831
|
-
#attachCachedArguments(items = [], toolCallArgumentsById) {
|
|
832
|
-
if (!items?.length) {
|
|
833
|
-
return;
|
|
834
|
-
}
|
|
835
|
-
for (const item of items) {
|
|
836
|
-
if (!item) {
|
|
837
|
-
continue;
|
|
838
|
-
}
|
|
839
|
-
if (item.arguments ||
|
|
840
|
-
item.args ||
|
|
841
|
-
item?.rawItem?.arguments ||
|
|
842
|
-
item?.rawItem?.args) {
|
|
843
|
-
continue;
|
|
844
|
-
}
|
|
845
|
-
const rawItem = item?.rawItem ?? item;
|
|
846
|
-
const callId = rawItem?.callId ??
|
|
847
|
-
rawItem?.call_id ??
|
|
848
|
-
rawItem?.tool_call_id ??
|
|
849
|
-
rawItem?.toolCallId ??
|
|
850
|
-
rawItem?.id ??
|
|
851
|
-
item?.callId ??
|
|
852
|
-
item?.call_id ??
|
|
853
|
-
item?.tool_call_id ??
|
|
854
|
-
item?.toolCallId ??
|
|
855
|
-
item?.id;
|
|
856
|
-
if (!callId) {
|
|
857
|
-
continue;
|
|
858
|
-
}
|
|
859
|
-
const args = toolCallArgumentsById.get(callId);
|
|
860
|
-
if (!args) {
|
|
861
|
-
continue;
|
|
885
|
+
const completedResult = await stream.completed;
|
|
886
|
+
const rawResponses = Array.isArray(stream?.rawResponses) ? stream.rawResponses : [];
|
|
887
|
+
let usageFromRawResponses;
|
|
888
|
+
for (let i = rawResponses.length - 1; i >= 0; i--) {
|
|
889
|
+
const candidate = extractUsage(rawResponses[i]);
|
|
890
|
+
if (candidate) {
|
|
891
|
+
usageFromRawResponses = candidate;
|
|
892
|
+
break;
|
|
862
893
|
}
|
|
863
|
-
item.arguments = args;
|
|
864
|
-
}
|
|
865
|
-
}
|
|
866
|
-
#extractTextDelta(payload) {
|
|
867
|
-
if (payload === null || payload === undefined) {
|
|
868
|
-
return null;
|
|
869
|
-
}
|
|
870
|
-
if (typeof payload === 'string') {
|
|
871
|
-
return payload || null;
|
|
872
894
|
}
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
payload.text ??
|
|
888
|
-
payload.content;
|
|
889
|
-
const text = this.#coerceToText(deltaCandidate);
|
|
890
|
-
return text || null;
|
|
891
|
-
}
|
|
892
|
-
#coerceToText(value) {
|
|
893
|
-
if (value === null || value === undefined) {
|
|
894
|
-
return '';
|
|
895
|
-
}
|
|
896
|
-
if (typeof value === 'string') {
|
|
897
|
-
return value;
|
|
898
|
-
}
|
|
899
|
-
if (typeof value === 'number' || typeof value === 'boolean') {
|
|
900
|
-
return String(value);
|
|
901
|
-
}
|
|
902
|
-
if (Array.isArray(value)) {
|
|
903
|
-
return value
|
|
904
|
-
.map(entry => this.#coerceToText(entry))
|
|
905
|
-
.filter(Boolean)
|
|
906
|
-
.join('');
|
|
895
|
+
const finalUsage = extractUsage(completedResult) || extractUsage(stream) || usageFromRawResponses;
|
|
896
|
+
if (finalUsage) {
|
|
897
|
+
acc.latestUsage = finalUsage;
|
|
898
|
+
const usageSource = extractUsage(completedResult)
|
|
899
|
+
? 'completed_result'
|
|
900
|
+
: extractUsage(stream)
|
|
901
|
+
? 'stream_object'
|
|
902
|
+
: 'stream_raw_responses';
|
|
903
|
+
this.logger.debug('Usage extracted from stream completion', {
|
|
904
|
+
sessionId: this.id,
|
|
905
|
+
source: 'stream_completed',
|
|
906
|
+
usageSource,
|
|
907
|
+
usage: finalUsage,
|
|
908
|
+
});
|
|
907
909
|
}
|
|
908
|
-
|
|
909
|
-
const
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
910
|
+
else {
|
|
911
|
+
const completedResultRecord = completedResult && typeof completedResult === 'object' && !Array.isArray(completedResult)
|
|
912
|
+
? completedResult
|
|
913
|
+
: undefined;
|
|
914
|
+
const streamRecord = stream && typeof stream === 'object' && !Array.isArray(stream)
|
|
915
|
+
? stream
|
|
916
|
+
: undefined;
|
|
917
|
+
this.logger.debug('No usage found in stream completion', {
|
|
918
|
+
sessionId: this.id,
|
|
919
|
+
source: 'stream_completed',
|
|
920
|
+
completedResultType: completedResult === null ? 'null' : Array.isArray(completedResult) ? 'array' : typeof completedResult,
|
|
921
|
+
completedResultKeys: completedResultRecord ? Object.keys(completedResultRecord) : [],
|
|
922
|
+
streamKeys: streamRecord ? Object.keys(streamRecord) : [],
|
|
923
|
+
completedResultHasUsagePath: {
|
|
924
|
+
usage: Boolean(completedResultRecord?.usage),
|
|
925
|
+
usageMetadata: Boolean(completedResultRecord?.usageMetadata),
|
|
926
|
+
usage_metadata: Boolean(completedResultRecord?.usage_metadata),
|
|
927
|
+
responseUsage: Boolean(completedResultRecord?.response?.usage),
|
|
928
|
+
},
|
|
929
|
+
});
|
|
919
930
|
}
|
|
920
|
-
|
|
931
|
+
this.flushStreamEventLog();
|
|
921
932
|
}
|
|
922
|
-
#buildResult(result, finalOutputOverride, reasoningOutputOverride, emittedCommandIds) {
|
|
933
|
+
#buildResult(result, finalOutputOverride, reasoningOutputOverride, emittedCommandIds, usage) {
|
|
923
934
|
if (result.interruptions && result.interruptions.length > 0) {
|
|
924
935
|
const interruption = result.interruptions[0];
|
|
925
|
-
this.
|
|
936
|
+
this.approvalState.setPending({
|
|
926
937
|
state: result.state,
|
|
927
938
|
interruption,
|
|
928
939
|
emittedCommandIds: emittedCommandIds ?? new Set(),
|
|
929
940
|
toolCallArgumentsById: new Map(this.toolCallArgumentsById),
|
|
930
|
-
};
|
|
941
|
+
});
|
|
931
942
|
let argumentsText = '';
|
|
932
943
|
const toolName = interruption.name;
|
|
933
944
|
// For shell_call (built-in shell tool), extract commands from action
|
|
@@ -959,18 +970,19 @@ export class ConversationSession {
|
|
|
959
970
|
},
|
|
960
971
|
};
|
|
961
972
|
}
|
|
962
|
-
this.
|
|
973
|
+
this.approvalState.clearPending();
|
|
963
974
|
const allCommandMessages = extractCommandMessages(result.newItems || result.history || []);
|
|
964
975
|
// Filter out commands that were already emitted in real-time
|
|
965
976
|
const commandMessages = emittedCommandIds
|
|
966
|
-
? allCommandMessages.filter(msg => !emittedCommandIds.has(msg.id))
|
|
977
|
+
? allCommandMessages.filter((msg) => !emittedCommandIds.has(msg.id))
|
|
967
978
|
: allCommandMessages;
|
|
968
|
-
const visibleCommandMessages = commandMessages.filter(msg => !msg.isApprovalRejection);
|
|
979
|
+
const visibleCommandMessages = commandMessages.filter((msg) => !msg.isApprovalRejection);
|
|
969
980
|
const response = {
|
|
970
981
|
type: 'response',
|
|
971
982
|
commandMessages: visibleCommandMessages,
|
|
972
983
|
finalText: finalOutputOverride ?? result.finalOutput ?? 'Done.',
|
|
973
984
|
reasoningText: reasoningOutputOverride,
|
|
985
|
+
usage: usage ?? extractUsage(result),
|
|
974
986
|
};
|
|
975
987
|
return response;
|
|
976
988
|
}
|