@qduc/term2 0.6.0 → 0.7.0
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 -0
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +139 -68
- package/dist/agent.js.map +1 -1
- package/dist/agent.test.js +179 -16
- package/dist/agent.test.js.map +1 -1
- package/dist/app.d.ts +16 -3
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +186 -23
- 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.js +170 -71
- package/dist/cli.js.map +1 -1
- 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 +7 -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 +0 -1
- package/dist/components/InputBox.d.ts.map +1 -1
- package/dist/components/InputBox.js +66 -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.debug.test.d.ts +2 -0
- package/dist/components/ModelSelectionMenu.debug.test.d.ts.map +1 -0
- package/dist/components/ModelSelectionMenu.debug.test.js.map +1 -0
- 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 +2 -0
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +35 -2
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/StatusBar.test.js +32 -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/env-setup.js +1 -0
- package/dist/env-setup.js.map +1 -1
- package/dist/hooks/use-app-commands.d.ts +22 -2
- package/dist/hooks/use-app-commands.d.ts.map +1 -1
- package/dist/hooks/use-app-commands.js +43 -3
- package/dist/hooks/use-app-commands.js.map +1 -1
- package/dist/hooks/use-app-commands.test.js +135 -1
- package/dist/hooks/use-app-commands.test.js.map +1 -1
- package/dist/hooks/use-conversation.clear.test.d.ts +2 -0
- package/dist/hooks/use-conversation.clear.test.d.ts.map +1 -0
- package/dist/hooks/use-conversation.clear.test.js +54 -0
- package/dist/hooks/use-conversation.clear.test.js.map +1 -0
- 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 +90 -12
- 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 +12 -1
- package/dist/hooks/use-mode-handlers.d.ts.map +1 -1
- package/dist/hooks/use-mode-handlers.js +31 -1
- 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 +7 -2
- 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 +45 -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 +22 -2
- package/dist/hooks/use-slash-commands.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 +18 -1
- package/dist/hooks/use-undo-selection.js.map +1 -1
- package/dist/inspect_zod.d.ts +2 -0
- package/dist/inspect_zod.d.ts.map +1 -0
- package/dist/inspect_zod.js +16 -0
- package/dist/inspect_zod.js.map +1 -0
- package/dist/lib/openai-agent-client.chat.test.js +40 -0
- package/dist/lib/openai-agent-client.chat.test.js.map +1 -1
- package/dist/lib/openai-agent-client.d.ts +18 -4
- package/dist/lib/openai-agent-client.d.ts.map +1 -1
- package/dist/lib/openai-agent-client.js +228 -32
- 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/retry-executor.js +45 -7
- package/dist/lib/retry-executor.js.map +1 -1
- package/dist/lib/retry-executor.test.js +63 -0
- package/dist/lib/retry-executor.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/non-interactive.d.ts +1 -0
- package/dist/non-interactive.d.ts.map +1 -1
- package/dist/non-interactive.js +3 -1
- package/dist/non-interactive.js.map +1 -1
- package/dist/non-interactive.test.js +8 -1
- package/dist/non-interactive.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 +96 -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.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/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/worktree-hygiene.md +9 -0
- package/dist/providers/ai-sdk-logging-fetch.d.ts +1 -1
- package/dist/providers/ai-sdk-logging-fetch.d.ts.map +1 -1
- package/dist/providers/ai-sdk-logging-fetch.js +145 -47
- package/dist/providers/ai-sdk-logging-fetch.js.map +1 -1
- package/dist/providers/ai-sdk-logging-fetch.test.js +202 -5
- package/dist/providers/ai-sdk-logging-fetch.test.js.map +1 -1
- package/dist/providers/codex-responses-model.d.ts +20 -0
- package/dist/providers/codex-responses-model.d.ts.map +1 -0
- package/dist/providers/codex-responses-model.js +170 -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 +240 -0
- package/dist/providers/codex-responses-model.test.js.map +1 -0
- package/dist/providers/codex.provider.d.ts +29 -0
- package/dist/providers/codex.provider.d.ts.map +1 -0
- package/dist/providers/codex.provider.js +486 -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 +634 -0
- package/dist/providers/codex.provider.test.js.map +1 -0
- package/dist/providers/custom-provider-adapter.test.js +56 -0
- 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 +277 -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 +279 -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 +4 -1
- package/dist/providers/openai-compatible.provider.d.ts.map +1 -1
- package/dist/providers/openai-compatible.provider.js +68 -324
- 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 +53 -1
- 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 -1
- package/dist/providers/openrouter.provider.d.ts.map +1 -1
- package/dist/providers/openrouter.provider.js +39 -22
- package/dist/providers/openrouter.provider.js.map +1 -1
- package/dist/providers/openrouter.provider.request-preprocessing.test.d.ts +2 -0
- package/dist/providers/openrouter.provider.request-preprocessing.test.d.ts.map +1 -0
- package/dist/providers/openrouter.provider.request-preprocessing.test.js +51 -0
- package/dist/providers/openrouter.provider.request-preprocessing.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 +11 -2
- package/dist/providers/registry.test.js.map +1 -1
- package/dist/scripts/eval-auto-approval/dataset.d.ts +3 -3
- 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 +0 -3
- 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.d.ts +2 -0
- package/dist/services/conversation-clear-save.test.d.ts.map +1 -0
- package/dist/services/conversation-clear-save.test.js +57 -0
- package/dist/services/conversation-clear-save.test.js.map +1 -0
- package/dist/services/conversation-events.d.ts +44 -1
- package/dist/services/conversation-events.d.ts.map +1 -1
- package/dist/services/conversation-history-repair.d.ts +25 -0
- package/dist/services/conversation-history-repair.d.ts.map +1 -0
- package/dist/services/conversation-history-repair.js +227 -0
- package/dist/services/conversation-history-repair.js.map +1 -0
- package/dist/services/conversation-history-repair.test.d.ts +2 -0
- package/dist/services/conversation-history-repair.test.d.ts.map +1 -0
- package/dist/services/conversation-history-repair.test.js +76 -0
- package/dist/services/conversation-history-repair.test.js.map +1 -0
- package/dist/services/conversation-integration.test.js +3 -1
- package/dist/services/conversation-integration.test.js.map +1 -1
- package/dist/services/conversation-log-events.d.ts +107 -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 +14 -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 +40 -38
- package/dist/services/conversation-persistence.d.ts.map +1 -1
- package/dist/services/conversation-persistence.js +312 -71
- package/dist/services/conversation-persistence.js.map +1 -1
- package/dist/services/conversation-persistence.test.js +485 -355
- 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 +252 -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 +153 -0
- package/dist/services/conversation-replay.test.js.map +1 -0
- package/dist/services/conversation-result-builder.d.ts.map +1 -1
- package/dist/services/conversation-result-builder.js +8 -2
- package/dist/services/conversation-result-builder.js.map +1 -1
- package/dist/services/conversation-result-builder.test.js +53 -0
- package/dist/services/conversation-result-builder.test.js.map +1 -1
- package/dist/services/conversation-retry-policy.d.ts +24 -0
- package/dist/services/conversation-retry-policy.d.ts.map +1 -1
- package/dist/services/conversation-retry-policy.js +68 -4
- package/dist/services/conversation-retry-policy.js.map +1 -1
- package/dist/services/conversation-retry-policy.test.js +99 -2
- package/dist/services/conversation-retry-policy.test.js.map +1 -1
- package/dist/services/conversation-service.d.ts +12 -2
- package/dist/services/conversation-service.d.ts.map +1 -1
- package/dist/services/conversation-service.js +29 -3
- package/dist/services/conversation-service.js.map +1 -1
- package/dist/services/conversation-session.auto-approval.test.js +2 -1
- package/dist/services/conversation-session.auto-approval.test.js.map +1 -1
- package/dist/services/conversation-session.d.ts +17 -1
- package/dist/services/conversation-session.d.ts.map +1 -1
- package/dist/services/conversation-session.js +580 -134
- package/dist/services/conversation-session.js.map +1 -1
- package/dist/services/conversation-store.d.ts.map +1 -1
- package/dist/services/conversation-store.js +6 -5
- package/dist/services/conversation-store.js.map +1 -1
- package/dist/services/conversation-store.test.js +34 -0
- package/dist/services/conversation-store.test.js.map +1 -1
- 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/logging-contract.d.ts +1 -1
- package/dist/services/logging-service.d.ts +4 -0
- package/dist/services/logging-service.d.ts.map +1 -1
- package/dist/services/logging-service.js +91 -33
- package/dist/services/logging-service.js.map +1 -1
- 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 -1
- package/dist/services/model-service.js.map +1 -1
- package/dist/services/provider-traffic.d.ts +87 -0
- package/dist/services/provider-traffic.d.ts.map +1 -0
- package/dist/services/provider-traffic.js +603 -0
- package/dist/services/provider-traffic.js.map +1 -0
- package/dist/services/provider-traffic.test.d.ts +2 -0
- package/dist/services/provider-traffic.test.d.ts.map +1 -0
- package/dist/services/provider-traffic.test.js +475 -0
- package/dist/services/provider-traffic.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/service-interfaces.d.ts +16 -0
- package/dist/services/service-interfaces.d.ts.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-service.js +6 -6
- package/dist/services/settings-service.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/shell-auto-approval-evaluator.d.ts +1 -1
- package/dist/services/shell-auto-approval-evaluator.d.ts.map +1 -1
- package/dist/services/shell-auto-approval-evaluator.js +284 -81
- package/dist/services/shell-auto-approval-evaluator.js.map +1 -1
- package/dist/services/shell-auto-approval-evaluator.test.js +215 -15
- package/dist/services/shell-auto-approval-evaluator.test.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 +2 -0
- package/dist/services/subagents/subagent-manager.d.ts.map +1 -1
- package/dist/services/subagents/subagent-manager.js +124 -21
- package/dist/services/subagents/subagent-manager.js.map +1 -1
- package/dist/services/subagents/subagent-manager.test.js +453 -0
- package/dist/services/subagents/subagent-manager.test.js.map +1 -1
- package/dist/services/terminal-result-collector.d.ts.map +1 -1
- package/dist/services/terminal-result-collector.js +6 -1
- package/dist/services/terminal-result-collector.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 +35 -0
- package/dist/services/tool-execution-ledger.d.ts.map +1 -0
- package/dist/services/tool-execution-ledger.js +204 -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 +96 -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 +157 -2
- 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/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/command-safety/path-analysis.d.ts.map +1 -1
- package/dist/utils/command-safety/path-analysis.js +143 -35
- package/dist/utils/command-safety/path-analysis.js.map +1 -1
- package/dist/utils/conversation-event-handler.d.ts.map +1 -1
- package/dist/utils/conversation-event-handler.js +52 -4
- package/dist/utils/conversation-event-handler.js.map +1 -1
- package/dist/utils/conversation-event-handler.test.js +175 -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/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/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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import test from 'ava';
|
|
2
2
|
import fs from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
+
import { ModelBehaviorError } from '@openai/agents';
|
|
4
5
|
import { SubagentManager } from './subagent-manager.js';
|
|
5
6
|
import { registerProvider } from '../../providers/registry.js';
|
|
6
7
|
// ========== Mock Utilities ==========
|
|
@@ -877,4 +878,456 @@ test.serial('worker shell tool blocks dangerous/destructive commands and returns
|
|
|
877
878
|
t.true(shellResult.includes('blocked for safety'), 'dangerous command must be blocked');
|
|
878
879
|
t.false(shellResult.includes('exit 0'), 'dangerous command must not execute');
|
|
879
880
|
});
|
|
881
|
+
test.serial('worker shell tool allows YELLOW command when auto-approval evaluator approves', async (t) => {
|
|
882
|
+
const tmpDir = fs.mkdtempSync(path.join(process.env['TMPDIR'] ?? '/tmp', 'term2-test-worker-shell-yellow-ok-'));
|
|
883
|
+
t.teardown(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
884
|
+
let shellResult = null;
|
|
885
|
+
let chatCalls = 0;
|
|
886
|
+
let evaluatorPrompt = '';
|
|
887
|
+
registerProvider({
|
|
888
|
+
id: 'mock-worker-shell-yellow-approved-provider',
|
|
889
|
+
label: 'Mock Worker Shell Yellow Approved Provider',
|
|
890
|
+
createRunner: () => ({
|
|
891
|
+
run: async (agent) => {
|
|
892
|
+
const shellTool = agent.tools.find((tool) => tool.name === 'shell');
|
|
893
|
+
shellResult = await shellTool.invoke({}, JSON.stringify({ command: 'npm run test:verbose -- --help' }), {});
|
|
894
|
+
return {
|
|
895
|
+
status: 'completed',
|
|
896
|
+
finalOutput: 'done',
|
|
897
|
+
history: [],
|
|
898
|
+
messages: [],
|
|
899
|
+
};
|
|
900
|
+
},
|
|
901
|
+
}),
|
|
902
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
903
|
+
});
|
|
904
|
+
const manager = new SubagentManager({
|
|
905
|
+
logger: createMockLogger(),
|
|
906
|
+
settings: createMockSettings({
|
|
907
|
+
'agent.model': 'mock-model',
|
|
908
|
+
'agent.provider': 'mock-worker-shell-yellow-approved-provider',
|
|
909
|
+
'shell.autoApproveMode': 'auto',
|
|
910
|
+
'agent.autoApproveModel': 'mock-auto-approve-model',
|
|
911
|
+
'agent.autoApproveProvider': 'mock-worker-shell-yellow-approved-provider',
|
|
912
|
+
}),
|
|
913
|
+
agentClient: {
|
|
914
|
+
chat: async (message) => {
|
|
915
|
+
chatCalls++;
|
|
916
|
+
evaluatorPrompt = message;
|
|
917
|
+
return '{"results":[{"approved":true,"reasoning":"Looks related and low risk."}]}';
|
|
918
|
+
},
|
|
919
|
+
},
|
|
920
|
+
executionContext: {
|
|
921
|
+
getCwd: () => tmpDir,
|
|
922
|
+
isRemote: () => false,
|
|
923
|
+
getSSHService: () => undefined,
|
|
924
|
+
},
|
|
925
|
+
});
|
|
926
|
+
await manager.run({ role: 'worker', task: 'run help for tests in this repository' });
|
|
927
|
+
t.is(chatCalls, 1);
|
|
928
|
+
t.true(evaluatorPrompt.includes('run help for tests in this repository'));
|
|
929
|
+
t.truthy(shellResult);
|
|
930
|
+
t.false(shellResult.includes('blocked for safety'), 'approved YELLOW command should execute');
|
|
931
|
+
});
|
|
932
|
+
test.serial('worker shell tool blocks YELLOW command when auto-approval evaluator rejects', async (t) => {
|
|
933
|
+
const tmpDir = fs.mkdtempSync(path.join(process.env['TMPDIR'] ?? '/tmp', 'term2-test-worker-shell-yellow-no-'));
|
|
934
|
+
t.teardown(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
935
|
+
let shellResult = null;
|
|
936
|
+
let chatCalls = 0;
|
|
937
|
+
registerProvider({
|
|
938
|
+
id: 'mock-worker-shell-yellow-rejected-provider',
|
|
939
|
+
label: 'Mock Worker Shell Yellow Rejected Provider',
|
|
940
|
+
createRunner: () => ({
|
|
941
|
+
run: async (agent) => {
|
|
942
|
+
const shellTool = agent.tools.find((tool) => tool.name === 'shell');
|
|
943
|
+
shellResult = await shellTool.invoke({}, JSON.stringify({ command: 'npm run test:verbose -- --help' }), {});
|
|
944
|
+
return {
|
|
945
|
+
status: 'completed',
|
|
946
|
+
finalOutput: 'done',
|
|
947
|
+
history: [],
|
|
948
|
+
messages: [],
|
|
949
|
+
};
|
|
950
|
+
},
|
|
951
|
+
}),
|
|
952
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
953
|
+
});
|
|
954
|
+
const manager = new SubagentManager({
|
|
955
|
+
logger: createMockLogger(),
|
|
956
|
+
settings: createMockSettings({
|
|
957
|
+
'agent.model': 'mock-model',
|
|
958
|
+
'agent.provider': 'mock-worker-shell-yellow-rejected-provider',
|
|
959
|
+
'shell.autoApproveMode': 'auto',
|
|
960
|
+
'agent.autoApproveModel': 'mock-auto-approve-model',
|
|
961
|
+
'agent.autoApproveProvider': 'mock-worker-shell-yellow-rejected-provider',
|
|
962
|
+
}),
|
|
963
|
+
agentClient: {
|
|
964
|
+
chat: async () => {
|
|
965
|
+
chatCalls++;
|
|
966
|
+
return '{"results":[{"approved":false,"reasoning":"Not safe."}]}';
|
|
967
|
+
},
|
|
968
|
+
},
|
|
969
|
+
executionContext: {
|
|
970
|
+
getCwd: () => tmpDir,
|
|
971
|
+
isRemote: () => false,
|
|
972
|
+
getSSHService: () => undefined,
|
|
973
|
+
},
|
|
974
|
+
});
|
|
975
|
+
await manager.run({ role: 'worker', task: 'run help for tests' });
|
|
976
|
+
t.is(chatCalls, 1);
|
|
977
|
+
t.truthy(shellResult);
|
|
978
|
+
t.true(shellResult.includes('blocked for safety'), 'rejected YELLOW command should stay blocked');
|
|
979
|
+
});
|
|
980
|
+
test.serial('run() extracts usage from error.state.usage when subagent run fails', async (t) => {
|
|
981
|
+
registerProvider({
|
|
982
|
+
id: 'mock-failed-usage-provider',
|
|
983
|
+
label: 'Mock Failed Usage Provider',
|
|
984
|
+
createRunner: () => ({
|
|
985
|
+
run: async () => {
|
|
986
|
+
const err = new Error('Run failed due to some reason');
|
|
987
|
+
err.state = {
|
|
988
|
+
usage: {
|
|
989
|
+
inputTokens: 15,
|
|
990
|
+
outputTokens: 25,
|
|
991
|
+
},
|
|
992
|
+
};
|
|
993
|
+
throw err;
|
|
994
|
+
},
|
|
995
|
+
}),
|
|
996
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
997
|
+
});
|
|
998
|
+
const settings = createMockSettings({
|
|
999
|
+
'agent.model': 'mock-model',
|
|
1000
|
+
'agent.provider': 'mock-failed-usage-provider',
|
|
1001
|
+
});
|
|
1002
|
+
const manager = new SubagentManager({ logger: createMockLogger(), settings });
|
|
1003
|
+
const result = await manager.run({
|
|
1004
|
+
role: 'explorer',
|
|
1005
|
+
task: 'find files',
|
|
1006
|
+
});
|
|
1007
|
+
t.is(result.status, 'failed');
|
|
1008
|
+
t.deepEqual(result.usage, {
|
|
1009
|
+
prompt_tokens: 15,
|
|
1010
|
+
completion_tokens: 25,
|
|
1011
|
+
total_tokens: 40,
|
|
1012
|
+
});
|
|
1013
|
+
});
|
|
1014
|
+
// ========== Model error retry ==========
|
|
1015
|
+
test.serial('run() retries on recoverable model error (hallucinated tool) and succeeds on second attempt', async (t) => {
|
|
1016
|
+
let runCount = 0;
|
|
1017
|
+
const events = [];
|
|
1018
|
+
const logWarnCalls = [];
|
|
1019
|
+
registerProvider({
|
|
1020
|
+
id: 'mock-retry-recoverable-provider',
|
|
1021
|
+
label: 'Mock Retry Recoverable Provider',
|
|
1022
|
+
createRunner: () => ({
|
|
1023
|
+
run: async () => {
|
|
1024
|
+
runCount++;
|
|
1025
|
+
if (runCount === 1) {
|
|
1026
|
+
throw new ModelBehaviorError('Tool bash not found in agent Explorer.');
|
|
1027
|
+
}
|
|
1028
|
+
return {
|
|
1029
|
+
status: 'completed',
|
|
1030
|
+
finalOutput: 'Success on retry',
|
|
1031
|
+
history: [],
|
|
1032
|
+
messages: [],
|
|
1033
|
+
};
|
|
1034
|
+
},
|
|
1035
|
+
}),
|
|
1036
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1037
|
+
});
|
|
1038
|
+
const manager = new SubagentManager({
|
|
1039
|
+
logger: {
|
|
1040
|
+
...createMockLogger(),
|
|
1041
|
+
warn: (msg, meta) => {
|
|
1042
|
+
logWarnCalls.push({ msg, meta });
|
|
1043
|
+
},
|
|
1044
|
+
},
|
|
1045
|
+
settings: createMockSettings({
|
|
1046
|
+
'agent.model': 'mock-model',
|
|
1047
|
+
'agent.provider': 'mock-retry-recoverable-provider',
|
|
1048
|
+
'agent.retryAttempts': 2,
|
|
1049
|
+
}),
|
|
1050
|
+
onEvent: (event) => events.push(event),
|
|
1051
|
+
});
|
|
1052
|
+
const result = await manager.run({ role: 'explorer', task: 'find all files' });
|
|
1053
|
+
t.is(result.status, 'completed');
|
|
1054
|
+
t.is(runCount, 2);
|
|
1055
|
+
const retryEvent = events.find((e) => e.type === 'retry');
|
|
1056
|
+
t.truthy(retryEvent, 'should emit retry event');
|
|
1057
|
+
t.is(retryEvent.toolName, 'bash');
|
|
1058
|
+
t.is(retryEvent.retryType, 'hallucination');
|
|
1059
|
+
t.is(retryEvent.attempt, 1);
|
|
1060
|
+
t.is(retryEvent.maxRetries, 1);
|
|
1061
|
+
const retryLog = logWarnCalls.find((c) => c.meta?.eventType === 'retry.subagent_model_error');
|
|
1062
|
+
t.truthy(retryLog, 'should log subagent model error retry');
|
|
1063
|
+
});
|
|
1064
|
+
test.serial('run() exhausts retries on repeated recoverable model errors and returns failed result', async (t) => {
|
|
1065
|
+
let runCount = 0;
|
|
1066
|
+
const events = [];
|
|
1067
|
+
registerProvider({
|
|
1068
|
+
id: 'mock-retry-exhaust-provider',
|
|
1069
|
+
label: 'Mock Retry Exhaust Provider',
|
|
1070
|
+
createRunner: () => ({
|
|
1071
|
+
run: async () => {
|
|
1072
|
+
runCount++;
|
|
1073
|
+
throw new ModelBehaviorError('Tool bash not found in agent Explorer.');
|
|
1074
|
+
},
|
|
1075
|
+
}),
|
|
1076
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1077
|
+
});
|
|
1078
|
+
const manager = new SubagentManager({
|
|
1079
|
+
logger: createMockLogger(),
|
|
1080
|
+
settings: createMockSettings({
|
|
1081
|
+
'agent.model': 'mock-model',
|
|
1082
|
+
'agent.provider': 'mock-retry-exhaust-provider',
|
|
1083
|
+
'agent.retryAttempts': 2,
|
|
1084
|
+
}),
|
|
1085
|
+
onEvent: (event) => events.push(event),
|
|
1086
|
+
});
|
|
1087
|
+
const result = await manager.run({ role: 'explorer', task: 'find all files' });
|
|
1088
|
+
t.is(result.status, 'failed');
|
|
1089
|
+
t.truthy(result.error);
|
|
1090
|
+
t.true(result.error.includes('bash'));
|
|
1091
|
+
// Should have tried: initial + MAX_SUBAGENT_MODEL_RETRIES (1) = 2 attempts
|
|
1092
|
+
t.is(runCount, 2);
|
|
1093
|
+
const retryEvents = events.filter((e) => e.type === 'retry');
|
|
1094
|
+
t.is(retryEvents.length, 1, 'should emit one retry event before exhaustion');
|
|
1095
|
+
});
|
|
1096
|
+
test.serial('run() does not retry on non-recoverable ModelBehaviorError', async (t) => {
|
|
1097
|
+
let runCount = 0;
|
|
1098
|
+
const events = [];
|
|
1099
|
+
registerProvider({
|
|
1100
|
+
id: 'mock-no-retry-non-recoverable-provider',
|
|
1101
|
+
label: 'Mock No Retry Non-Recoverable Provider',
|
|
1102
|
+
createRunner: () => ({
|
|
1103
|
+
run: async () => {
|
|
1104
|
+
runCount++;
|
|
1105
|
+
throw new ModelBehaviorError('something else unrelated to tools');
|
|
1106
|
+
},
|
|
1107
|
+
}),
|
|
1108
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1109
|
+
});
|
|
1110
|
+
const manager = new SubagentManager({
|
|
1111
|
+
logger: createMockLogger(),
|
|
1112
|
+
settings: createMockSettings({
|
|
1113
|
+
'agent.model': 'mock-model',
|
|
1114
|
+
'agent.provider': 'mock-no-retry-non-recoverable-provider',
|
|
1115
|
+
'agent.retryAttempts': 2,
|
|
1116
|
+
}),
|
|
1117
|
+
onEvent: (event) => events.push(event),
|
|
1118
|
+
});
|
|
1119
|
+
const result = await manager.run({ role: 'explorer', task: 'find all files' });
|
|
1120
|
+
t.is(result.status, 'failed');
|
|
1121
|
+
t.is(runCount, 1, 'no retry should be attempted');
|
|
1122
|
+
const retryEvents = events.filter((e) => e.type === 'retry');
|
|
1123
|
+
t.is(retryEvents.length, 0);
|
|
1124
|
+
});
|
|
1125
|
+
test.serial('run() aborted subagent returns cancelled status without model-error retry', async (t) => {
|
|
1126
|
+
const events = [];
|
|
1127
|
+
registerProvider({
|
|
1128
|
+
id: 'mock-abort-no-retry-provider',
|
|
1129
|
+
label: 'Mock Abort No Retry Provider',
|
|
1130
|
+
createRunner: () => ({
|
|
1131
|
+
run: async () => {
|
|
1132
|
+
const err = new Error('The operation was aborted');
|
|
1133
|
+
err.name = 'AbortError';
|
|
1134
|
+
throw err;
|
|
1135
|
+
},
|
|
1136
|
+
}),
|
|
1137
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1138
|
+
});
|
|
1139
|
+
const manager = new SubagentManager({
|
|
1140
|
+
logger: createMockLogger(),
|
|
1141
|
+
settings: createMockSettings({
|
|
1142
|
+
'agent.model': 'mock-model',
|
|
1143
|
+
'agent.provider': 'mock-abort-no-retry-provider',
|
|
1144
|
+
'agent.retryAttempts': 2,
|
|
1145
|
+
}),
|
|
1146
|
+
onEvent: (event) => events.push(event),
|
|
1147
|
+
});
|
|
1148
|
+
const result = await manager.run({ role: 'explorer', task: 'find all files' });
|
|
1149
|
+
t.is(result.status, 'cancelled');
|
|
1150
|
+
const retryEvents = events.filter((e) => e.type === 'retry');
|
|
1151
|
+
t.is(retryEvents.length, 0, 'abort errors should not trigger model-error retries');
|
|
1152
|
+
});
|
|
1153
|
+
test.serial('run() retries on transient upstream error via executeWithRetry', async (t) => {
|
|
1154
|
+
let runCount = 0;
|
|
1155
|
+
const logWarnCalls = [];
|
|
1156
|
+
registerProvider({
|
|
1157
|
+
id: 'mock-transient-retry-provider',
|
|
1158
|
+
label: 'Mock Transient Retry Provider',
|
|
1159
|
+
createRunner: () => ({
|
|
1160
|
+
run: async () => {
|
|
1161
|
+
runCount++;
|
|
1162
|
+
if (runCount === 1) {
|
|
1163
|
+
const err = new Error('rate limit');
|
|
1164
|
+
err.status = 429;
|
|
1165
|
+
err.headers = { 'retry-after': '0' };
|
|
1166
|
+
throw err;
|
|
1167
|
+
}
|
|
1168
|
+
return {
|
|
1169
|
+
status: 'completed',
|
|
1170
|
+
finalOutput: 'Success after upstream retry',
|
|
1171
|
+
history: [],
|
|
1172
|
+
messages: [],
|
|
1173
|
+
};
|
|
1174
|
+
},
|
|
1175
|
+
}),
|
|
1176
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1177
|
+
});
|
|
1178
|
+
const manager = new SubagentManager({
|
|
1179
|
+
logger: {
|
|
1180
|
+
...createMockLogger(),
|
|
1181
|
+
warn: (msg, meta) => {
|
|
1182
|
+
logWarnCalls.push({ msg, meta });
|
|
1183
|
+
},
|
|
1184
|
+
},
|
|
1185
|
+
settings: createMockSettings({
|
|
1186
|
+
'agent.model': 'mock-model',
|
|
1187
|
+
'agent.provider': 'mock-transient-retry-provider',
|
|
1188
|
+
'agent.retryAttempts': 2,
|
|
1189
|
+
}),
|
|
1190
|
+
});
|
|
1191
|
+
const result = await manager.run({ role: 'explorer', task: 'find all files' });
|
|
1192
|
+
t.is(result.status, 'completed');
|
|
1193
|
+
t.is(runCount, 2, 'should have retried once after transient error');
|
|
1194
|
+
const upstreamRetry = logWarnCalls.find((c) => c.meta?.eventType === 'retry.upstream');
|
|
1195
|
+
t.truthy(upstreamRetry, 'should log upstream retry');
|
|
1196
|
+
});
|
|
1197
|
+
test.serial('run() does not retry worker after a mutating write tool was invoked before the model error', async (t) => {
|
|
1198
|
+
let runCount = 0;
|
|
1199
|
+
const events = [];
|
|
1200
|
+
registerProvider({
|
|
1201
|
+
id: 'mock-write-then-crash-provider',
|
|
1202
|
+
label: 'Mock Write Then Crash Provider',
|
|
1203
|
+
createRunner: () => ({
|
|
1204
|
+
run: async (agent) => {
|
|
1205
|
+
runCount++;
|
|
1206
|
+
// Invoke a write tool before crashing with a recoverable model error
|
|
1207
|
+
const createFile = agent.tools.find((tool) => tool.name === 'create_file');
|
|
1208
|
+
if (createFile) {
|
|
1209
|
+
await createFile.invoke({}, JSON.stringify({ path: 'touched.ts', content: 'x' }), {});
|
|
1210
|
+
}
|
|
1211
|
+
throw new ModelBehaviorError('Tool bash not found in agent Worker.');
|
|
1212
|
+
},
|
|
1213
|
+
}),
|
|
1214
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1215
|
+
});
|
|
1216
|
+
const tmpDir = fs.mkdtempSync(path.join('/tmp', 'term2-test-write-then-crash-'));
|
|
1217
|
+
t.teardown(() => fs.rmSync(tmpDir, { recursive: true, force: true }));
|
|
1218
|
+
const manager = new SubagentManager({
|
|
1219
|
+
logger: createMockLogger(),
|
|
1220
|
+
settings: createMockSettings({
|
|
1221
|
+
'agent.model': 'mock-model',
|
|
1222
|
+
'agent.provider': 'mock-write-then-crash-provider',
|
|
1223
|
+
'agent.retryAttempts': 2,
|
|
1224
|
+
}),
|
|
1225
|
+
executionContext: {
|
|
1226
|
+
getCwd: () => tmpDir,
|
|
1227
|
+
isRemote: () => false,
|
|
1228
|
+
getSSHService: () => undefined,
|
|
1229
|
+
},
|
|
1230
|
+
onEvent: (event) => events.push(event),
|
|
1231
|
+
});
|
|
1232
|
+
const result = await manager.run({ role: 'worker', task: 'do some work', writeBoundary: ['.'] });
|
|
1233
|
+
t.is(result.status, 'failed');
|
|
1234
|
+
t.is(runCount, 1, 'must not retry when a write tool was invoked before the model error');
|
|
1235
|
+
const retryEvents = events.filter((e) => e.type === 'retry');
|
|
1236
|
+
t.is(retryEvents.length, 0, 'no retry event should be emitted');
|
|
1237
|
+
});
|
|
1238
|
+
test.serial('run() retries read-only subagent (explorer) even after read tools were called', async (t) => {
|
|
1239
|
+
let runCount = 0;
|
|
1240
|
+
registerProvider({
|
|
1241
|
+
id: 'mock-explorer-read-then-crash-provider',
|
|
1242
|
+
label: 'Mock Explorer Read Then Crash Provider',
|
|
1243
|
+
createRunner: () => ({
|
|
1244
|
+
run: async (agent) => {
|
|
1245
|
+
runCount++;
|
|
1246
|
+
if (runCount === 1) {
|
|
1247
|
+
// Call a read tool then throw a recoverable error
|
|
1248
|
+
const grep = agent.tools.find((tool) => tool.name === 'grep');
|
|
1249
|
+
if (grep) {
|
|
1250
|
+
await grep.invoke({}, JSON.stringify({ pattern: 'foo', path: '.' }), {}).catch(() => { });
|
|
1251
|
+
}
|
|
1252
|
+
throw new ModelBehaviorError('Tool bash not found in agent Explorer.');
|
|
1253
|
+
}
|
|
1254
|
+
return { status: 'completed', finalOutput: 'found it', history: [], messages: [] };
|
|
1255
|
+
},
|
|
1256
|
+
}),
|
|
1257
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1258
|
+
});
|
|
1259
|
+
const manager = new SubagentManager({
|
|
1260
|
+
logger: createMockLogger(),
|
|
1261
|
+
settings: createMockSettings({
|
|
1262
|
+
'agent.model': 'mock-model',
|
|
1263
|
+
'agent.provider': 'mock-explorer-read-then-crash-provider',
|
|
1264
|
+
'agent.retryAttempts': 2,
|
|
1265
|
+
}),
|
|
1266
|
+
});
|
|
1267
|
+
const result = await manager.run({ role: 'explorer', task: 'search for something' });
|
|
1268
|
+
t.is(result.status, 'completed');
|
|
1269
|
+
t.is(runCount, 2, 'read-only subagent should retry even after read tools ran');
|
|
1270
|
+
});
|
|
1271
|
+
test.serial('corrective retry task for hallucination names the specific bad tool', async (t) => {
|
|
1272
|
+
const runInputs = [];
|
|
1273
|
+
registerProvider({
|
|
1274
|
+
id: 'mock-corrective-hallucination-provider',
|
|
1275
|
+
label: 'Mock Corrective Hallucination Provider',
|
|
1276
|
+
createRunner: () => ({
|
|
1277
|
+
run: async (_agent, input) => {
|
|
1278
|
+
const inputText = typeof input === 'string' ? input : JSON.stringify(input);
|
|
1279
|
+
runInputs.push(inputText);
|
|
1280
|
+
if (runInputs.length === 1) {
|
|
1281
|
+
throw new ModelBehaviorError('Tool bash not found in agent Explorer.');
|
|
1282
|
+
}
|
|
1283
|
+
return { status: 'completed', finalOutput: 'done', history: [], messages: [] };
|
|
1284
|
+
},
|
|
1285
|
+
}),
|
|
1286
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1287
|
+
});
|
|
1288
|
+
const manager = new SubagentManager({
|
|
1289
|
+
logger: createMockLogger(),
|
|
1290
|
+
settings: createMockSettings({
|
|
1291
|
+
'agent.model': 'mock-model',
|
|
1292
|
+
'agent.provider': 'mock-corrective-hallucination-provider',
|
|
1293
|
+
'agent.retryAttempts': 2,
|
|
1294
|
+
}),
|
|
1295
|
+
});
|
|
1296
|
+
await manager.run({ role: 'explorer', task: 'do something' });
|
|
1297
|
+
t.is(runInputs.length, 2);
|
|
1298
|
+
const retryInput = runInputs[1];
|
|
1299
|
+
t.true(retryInput.includes('"bash"'), 'corrective prompt should name the hallucinated tool');
|
|
1300
|
+
t.true(retryInput.includes('does not exist'), 'corrective prompt should say the tool does not exist');
|
|
1301
|
+
});
|
|
1302
|
+
test.serial('corrective retry task for behavior error instructs model to produce a final answer', async (t) => {
|
|
1303
|
+
const runInputs = [];
|
|
1304
|
+
registerProvider({
|
|
1305
|
+
id: 'mock-corrective-behavior-provider',
|
|
1306
|
+
label: 'Mock Corrective Behavior Provider',
|
|
1307
|
+
createRunner: () => ({
|
|
1308
|
+
run: async (_agent, input) => {
|
|
1309
|
+
const inputText = typeof input === 'string' ? input : JSON.stringify(input);
|
|
1310
|
+
runInputs.push(inputText);
|
|
1311
|
+
if (runInputs.length === 1) {
|
|
1312
|
+
throw new ModelBehaviorError('Model did not produce a final response');
|
|
1313
|
+
}
|
|
1314
|
+
return { status: 'completed', finalOutput: 'done', history: [], messages: [] };
|
|
1315
|
+
},
|
|
1316
|
+
}),
|
|
1317
|
+
fetchModels: async () => [{ id: 'mock-model' }],
|
|
1318
|
+
});
|
|
1319
|
+
const manager = new SubagentManager({
|
|
1320
|
+
logger: createMockLogger(),
|
|
1321
|
+
settings: createMockSettings({
|
|
1322
|
+
'agent.model': 'mock-model',
|
|
1323
|
+
'agent.provider': 'mock-corrective-behavior-provider',
|
|
1324
|
+
'agent.retryAttempts': 2,
|
|
1325
|
+
}),
|
|
1326
|
+
});
|
|
1327
|
+
await manager.run({ role: 'explorer', task: 'do something' });
|
|
1328
|
+
t.is(runInputs.length, 2);
|
|
1329
|
+
const retryInput = runInputs[1];
|
|
1330
|
+
t.true(retryInput.includes('final'), 'corrective prompt for behavior should instruct to produce a final answer');
|
|
1331
|
+
t.true(retryInput.includes('Do not call'), 'should tell model not to call more tools');
|
|
1332
|
+
});
|
|
880
1333
|
//# sourceMappingURL=subagent-manager.test.js.map
|