@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,280 +1,14 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import envPaths from 'env-paths';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import deepEqual from 'fast-deep-equal';
|
|
6
4
|
import { LoggingService } from './logging-service.js';
|
|
7
|
-
|
|
8
|
-
import '../providers/index.js';
|
|
9
|
-
import { getAllProviders, getProvider, upsertProvider, } from '../providers/index.js';
|
|
10
|
-
import { getAllWebSearchProviders } from '../providers/web-search/index.js';
|
|
5
|
+
import { getProvider, upsertProvider } from '../providers/index.js';
|
|
11
6
|
import { createOpenAICompatibleProviderDefinition } from '../providers/openai-compatible.provider.js';
|
|
7
|
+
import { DEFAULT_SETTINGS, OPTIONAL_DEFAULT_KEYS, RUNTIME_MODIFIABLE_SETTINGS, SENSITIVE_SETTING_KEYS, SettingsSchema, } from './settings-schema.js';
|
|
8
|
+
import { buildEnvOverrides, isTestEnvironment, parseBooleanEnv } from './settings-env.js';
|
|
9
|
+
import { flattenSettings, mergeSettings, trackSettingSources } from './settings-merger.js';
|
|
10
|
+
import { hasMissingKeys, loadSettingsFromFile, saveSettingsToFile, stripSensitiveSettings, } from './settings-persistence.js';
|
|
12
11
|
const paths = envPaths('term2');
|
|
13
|
-
// Define schemas for validation
|
|
14
|
-
const AgentSettingsSchema = z.object({
|
|
15
|
-
model: z.string().min(1).default('gpt-5.1'),
|
|
16
|
-
// 'default' signals we should *not* explicitly pass a reasoningEffort
|
|
17
|
-
// to the API, allowing it to decide what to use.
|
|
18
|
-
reasoningEffort: z
|
|
19
|
-
.enum(['default', 'none', 'minimal', 'low', 'medium', 'high'])
|
|
20
|
-
.default('default'),
|
|
21
|
-
// Temperature controls randomness. We keep it optional so providers/models
|
|
22
|
-
// can use their own defaults when unset.
|
|
23
|
-
temperature: z.number().min(0).max(2).optional(),
|
|
24
|
-
maxTurns: z.number().int().positive().default(100),
|
|
25
|
-
retryAttempts: z.number().int().nonnegative().default(2),
|
|
26
|
-
// NOTE: We do NOT validate provider existence here because the provider
|
|
27
|
-
// registry can be extended at runtime from settings.json (custom providers).
|
|
28
|
-
// We validate/fallback after SettingsService loads and registers runtime providers.
|
|
29
|
-
provider: z
|
|
30
|
-
.string()
|
|
31
|
-
.min(1)
|
|
32
|
-
.default('openai')
|
|
33
|
-
.describe('Provider to use for the agent'),
|
|
34
|
-
openrouter: z
|
|
35
|
-
.object({
|
|
36
|
-
apiKey: z.string().optional(),
|
|
37
|
-
baseUrl: z.string().url().optional(),
|
|
38
|
-
referrer: z.string().optional(),
|
|
39
|
-
title: z.string().optional(),
|
|
40
|
-
})
|
|
41
|
-
.optional(),
|
|
42
|
-
mentorModel: z.string().optional().describe('Model to use as a mentor'),
|
|
43
|
-
mentorProvider: z
|
|
44
|
-
.string()
|
|
45
|
-
.min(1)
|
|
46
|
-
.optional()
|
|
47
|
-
.describe('Provider to use for the mentor model (defaults to agent.provider when unset)'),
|
|
48
|
-
mentorReasoningEffort: z
|
|
49
|
-
.enum(['default', 'none', 'minimal', 'low', 'medium', 'high'])
|
|
50
|
-
.default('default')
|
|
51
|
-
.describe('Reasoning effort for the mentor model'),
|
|
52
|
-
useFlexServiceTier: z
|
|
53
|
-
.boolean()
|
|
54
|
-
.optional()
|
|
55
|
-
.default(false)
|
|
56
|
-
.describe('Use OpenAI Flex Service Tier to reduce costs (OpenAI only)'),
|
|
57
|
-
});
|
|
58
|
-
const ShellSettingsSchema = z.object({
|
|
59
|
-
timeout: z.number().int().positive().default(120000),
|
|
60
|
-
maxOutputLines: z.number().int().positive().default(1000),
|
|
61
|
-
maxOutputChars: z.number().int().positive().default(10000),
|
|
62
|
-
});
|
|
63
|
-
const UISettingsSchema = z.object({
|
|
64
|
-
historySize: z.number().int().positive().default(1000),
|
|
65
|
-
});
|
|
66
|
-
const LoggingSettingsSchema = z.object({
|
|
67
|
-
logLevel: z
|
|
68
|
-
.enum(['error', 'warn', 'info', 'security', 'debug'])
|
|
69
|
-
.default('info'),
|
|
70
|
-
disableLogging: z.boolean().optional().default(false),
|
|
71
|
-
debugLogging: z.boolean().optional().default(false),
|
|
72
|
-
suppressConsoleOutput: z.boolean().optional().default(true),
|
|
73
|
-
});
|
|
74
|
-
const EnvironmentSettingsSchema = z.object({
|
|
75
|
-
nodeEnv: z.string().optional(),
|
|
76
|
-
});
|
|
77
|
-
const AppSettingsSchema = z.object({
|
|
78
|
-
shellPath: z.string().optional(),
|
|
79
|
-
// Independent mode flags that can be enabled together and persist across sessions
|
|
80
|
-
// mentorMode: uses simplified mentor prompt and enables ask_mentor tool (if mentorModel configured)
|
|
81
|
-
// editMode: auto-approves apply_patch operations within cwd for faster file editing
|
|
82
|
-
// liteMode: minimal context for general terminal assistance (no codebase tools/prompts)
|
|
83
|
-
mentorMode: z.boolean().optional().default(false),
|
|
84
|
-
editMode: z.boolean().optional().default(false),
|
|
85
|
-
liteMode: z.boolean().optional().default(false),
|
|
86
|
-
});
|
|
87
|
-
const ToolsSettingsSchema = z.object({
|
|
88
|
-
logFileOperations: z.boolean().optional().default(true),
|
|
89
|
-
enableEditHealing: z.boolean().optional().default(true),
|
|
90
|
-
editHealingModel: z.string().optional().default('gpt-4o-mini'),
|
|
91
|
-
});
|
|
92
|
-
const DebugSettingsSchema = z.object({
|
|
93
|
-
debugBashTool: z.boolean().optional().default(false),
|
|
94
|
-
});
|
|
95
|
-
const SSHSettingsSchema = z.object({
|
|
96
|
-
enabled: z.boolean().default(false),
|
|
97
|
-
host: z.string().optional(),
|
|
98
|
-
port: z.number().int().positive().default(22),
|
|
99
|
-
username: z.string().optional(),
|
|
100
|
-
remoteDir: z.string().optional(),
|
|
101
|
-
});
|
|
102
|
-
const WebSearchSettingsSchema = z.object({
|
|
103
|
-
provider: z.string().optional(),
|
|
104
|
-
tavily: z.object({
|
|
105
|
-
apiKey: z.string().optional(),
|
|
106
|
-
}).optional(),
|
|
107
|
-
});
|
|
108
|
-
const CustomProviderSchema = z.object({
|
|
109
|
-
name: z.string().min(1),
|
|
110
|
-
baseUrl: z.string().url(),
|
|
111
|
-
apiKey: z.string().optional(),
|
|
112
|
-
});
|
|
113
|
-
/**
|
|
114
|
-
* Settings that are sensitive and should NEVER be saved to disk.
|
|
115
|
-
* These are only loaded from environment variables.
|
|
116
|
-
*/
|
|
117
|
-
function getSensitiveSettingKeys() {
|
|
118
|
-
const keys = new Set(['app.shellPath']);
|
|
119
|
-
// Add provider-specific sensitive keys
|
|
120
|
-
for (const provider of getAllProviders()) {
|
|
121
|
-
if (provider.sensitiveSettingKeys) {
|
|
122
|
-
for (const key of provider.sensitiveSettingKeys) {
|
|
123
|
-
keys.add(key);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
// Add web search provider-specific sensitive keys
|
|
128
|
-
for (const provider of getAllWebSearchProviders()) {
|
|
129
|
-
if (provider.sensitiveSettingKeys) {
|
|
130
|
-
for (const key of provider.sensitiveSettingKeys) {
|
|
131
|
-
keys.add(key);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return keys;
|
|
136
|
-
}
|
|
137
|
-
const SENSITIVE_SETTING_KEYS = getSensitiveSettingKeys();
|
|
138
|
-
const SettingsSchema = z.object({
|
|
139
|
-
providers: z.array(CustomProviderSchema).optional().default([]),
|
|
140
|
-
agent: AgentSettingsSchema.optional(),
|
|
141
|
-
shell: ShellSettingsSchema.optional(),
|
|
142
|
-
ui: UISettingsSchema.optional(),
|
|
143
|
-
logging: LoggingSettingsSchema.optional(),
|
|
144
|
-
environment: EnvironmentSettingsSchema.optional(),
|
|
145
|
-
app: AppSettingsSchema.optional(),
|
|
146
|
-
tools: ToolsSettingsSchema.optional(),
|
|
147
|
-
debug: DebugSettingsSchema.optional(),
|
|
148
|
-
ssh: SSHSettingsSchema.optional(),
|
|
149
|
-
webSearch: WebSearchSettingsSchema.optional(),
|
|
150
|
-
});
|
|
151
|
-
/**
|
|
152
|
-
* Centralized list of all setting keys for consistency across the app.
|
|
153
|
-
* Used by settings command UI and other components to avoid duplication.
|
|
154
|
-
*/
|
|
155
|
-
export const SETTING_KEYS = {
|
|
156
|
-
AGENT_MODEL: 'agent.model',
|
|
157
|
-
AGENT_REASONING_EFFORT: 'agent.reasoningEffort',
|
|
158
|
-
AGENT_TEMPERATURE: 'agent.temperature',
|
|
159
|
-
AGENT_PROVIDER: 'agent.provider',
|
|
160
|
-
AGENT_MAX_TURNS: 'agent.maxTurns',
|
|
161
|
-
AGENT_RETRY_ATTEMPTS: 'agent.retryAttempts',
|
|
162
|
-
AGENT_OPENROUTER_API_KEY: 'agent.openrouter.apiKey', // Sensitive - env only
|
|
163
|
-
AGENT_OPENROUTER_BASE_URL: 'agent.openrouter.baseUrl', // Sensitive - env only
|
|
164
|
-
AGENT_OPENROUTER_REFERRER: 'agent.openrouter.referrer', // Sensitive - env only
|
|
165
|
-
AGENT_OPENROUTER_TITLE: 'agent.openrouter.title', // Sensitive - env only
|
|
166
|
-
AGENT_MENTOR_MODEL: 'agent.mentorModel',
|
|
167
|
-
AGENT_MENTOR_PROVIDER: 'agent.mentorProvider',
|
|
168
|
-
AGENT_MENTOR_REASONING_EFFORT: 'agent.mentorReasoningEffort',
|
|
169
|
-
AGENT_USE_FLEX_SERVICE_TIER: 'agent.useFlexServiceTier',
|
|
170
|
-
SHELL_TIMEOUT: 'shell.timeout',
|
|
171
|
-
SHELL_MAX_OUTPUT_LINES: 'shell.maxOutputLines',
|
|
172
|
-
SHELL_MAX_OUTPUT_CHARS: 'shell.maxOutputChars',
|
|
173
|
-
UI_HISTORY_SIZE: 'ui.historySize',
|
|
174
|
-
LOGGING_LOG_LEVEL: 'logging.logLevel',
|
|
175
|
-
LOGGING_DISABLE: 'logging.disableLogging',
|
|
176
|
-
LOGGING_DEBUG: 'logging.debugLogging',
|
|
177
|
-
LOGGING_SUPPRESS_CONSOLE: 'logging.suppressConsoleOutput',
|
|
178
|
-
ENV_NODE_ENV: 'environment.nodeEnv',
|
|
179
|
-
APP_SHELL_PATH: 'app.shellPath', // Sensitive - env only
|
|
180
|
-
APP_MENTOR_MODE: 'app.mentorMode',
|
|
181
|
-
APP_EDIT_MODE: 'app.editMode',
|
|
182
|
-
APP_LITE_MODE: 'app.liteMode',
|
|
183
|
-
TOOLS_LOG_FILE_OPS: 'tools.logFileOperations',
|
|
184
|
-
TOOLS_ENABLE_EDIT_HEALING: 'tools.enableEditHealing',
|
|
185
|
-
TOOLS_EDIT_HEALING_MODEL: 'tools.editHealingModel',
|
|
186
|
-
DEBUG_BASH_TOOL: 'debug.debugBashTool',
|
|
187
|
-
SSH_ENABLED: 'ssh.enabled',
|
|
188
|
-
SSH_HOST: 'ssh.host',
|
|
189
|
-
SSH_PORT: 'ssh.port',
|
|
190
|
-
SSH_USERNAME: 'ssh.username',
|
|
191
|
-
SSH_REMOTE_DIR: 'ssh.remoteDir',
|
|
192
|
-
WEB_SEARCH_PROVIDER: 'webSearch.provider',
|
|
193
|
-
WEB_SEARCH_TAVILY_API_KEY: 'webSearch.tavily.apiKey', // Sensitive - env only
|
|
194
|
-
};
|
|
195
|
-
// Define which settings are modifiable at runtime
|
|
196
|
-
const RUNTIME_MODIFIABLE_SETTINGS = new Set([
|
|
197
|
-
SETTING_KEYS.AGENT_MODEL,
|
|
198
|
-
SETTING_KEYS.AGENT_REASONING_EFFORT,
|
|
199
|
-
SETTING_KEYS.AGENT_TEMPERATURE,
|
|
200
|
-
SETTING_KEYS.AGENT_PROVIDER,
|
|
201
|
-
SETTING_KEYS.AGENT_MENTOR_MODEL,
|
|
202
|
-
SETTING_KEYS.AGENT_MENTOR_PROVIDER,
|
|
203
|
-
SETTING_KEYS.AGENT_MENTOR_REASONING_EFFORT,
|
|
204
|
-
SETTING_KEYS.AGENT_USE_FLEX_SERVICE_TIER,
|
|
205
|
-
SETTING_KEYS.SHELL_TIMEOUT,
|
|
206
|
-
SETTING_KEYS.SHELL_MAX_OUTPUT_LINES,
|
|
207
|
-
SETTING_KEYS.SHELL_MAX_OUTPUT_CHARS,
|
|
208
|
-
SETTING_KEYS.LOGGING_LOG_LEVEL,
|
|
209
|
-
SETTING_KEYS.LOGGING_SUPPRESS_CONSOLE,
|
|
210
|
-
SETTING_KEYS.APP_MENTOR_MODE,
|
|
211
|
-
SETTING_KEYS.APP_EDIT_MODE,
|
|
212
|
-
SETTING_KEYS.APP_LITE_MODE,
|
|
213
|
-
]);
|
|
214
|
-
// Note: Sensitive settings are NOT in RUNTIME_MODIFIABLE_SETTINGS because they
|
|
215
|
-
// cannot be modified at all - they can only be set via environment variables at startup.
|
|
216
|
-
// app.mentorMode and app.editMode are runtime-modifiable AND persisted to disk so they
|
|
217
|
-
// survive across sessions (user's mode preference is preserved).
|
|
218
|
-
// Some settings with default values are optional to persist
|
|
219
|
-
const OPTIONAL_DEFAULT_KEYS = new Set([]);
|
|
220
|
-
// Default settings
|
|
221
|
-
const DEFAULT_SETTINGS = {
|
|
222
|
-
providers: [],
|
|
223
|
-
agent: {
|
|
224
|
-
model: 'gpt-5.1',
|
|
225
|
-
reasoningEffort: 'default',
|
|
226
|
-
maxTurns: 100,
|
|
227
|
-
retryAttempts: 2,
|
|
228
|
-
provider: 'openai',
|
|
229
|
-
openrouter: {
|
|
230
|
-
// defaults empty; can be provided via env or config
|
|
231
|
-
// defaults empty; can be provided via env or config
|
|
232
|
-
},
|
|
233
|
-
mentorModel: undefined,
|
|
234
|
-
mentorProvider: undefined,
|
|
235
|
-
mentorReasoningEffort: 'default',
|
|
236
|
-
useFlexServiceTier: false,
|
|
237
|
-
},
|
|
238
|
-
shell: {
|
|
239
|
-
timeout: 120000,
|
|
240
|
-
maxOutputLines: 1000,
|
|
241
|
-
maxOutputChars: 10000,
|
|
242
|
-
},
|
|
243
|
-
ui: {
|
|
244
|
-
historySize: 1000,
|
|
245
|
-
},
|
|
246
|
-
logging: {
|
|
247
|
-
logLevel: 'info',
|
|
248
|
-
disableLogging: false,
|
|
249
|
-
debugLogging: false,
|
|
250
|
-
suppressConsoleOutput: true,
|
|
251
|
-
},
|
|
252
|
-
environment: {
|
|
253
|
-
nodeEnv: undefined,
|
|
254
|
-
},
|
|
255
|
-
app: {
|
|
256
|
-
shellPath: undefined,
|
|
257
|
-
mentorMode: false,
|
|
258
|
-
editMode: false,
|
|
259
|
-
liteMode: false,
|
|
260
|
-
},
|
|
261
|
-
tools: {
|
|
262
|
-
logFileOperations: true,
|
|
263
|
-
enableEditHealing: true,
|
|
264
|
-
editHealingModel: 'gpt-4o-mini',
|
|
265
|
-
},
|
|
266
|
-
debug: {
|
|
267
|
-
debugBashTool: false,
|
|
268
|
-
},
|
|
269
|
-
ssh: {
|
|
270
|
-
enabled: false,
|
|
271
|
-
port: 22,
|
|
272
|
-
},
|
|
273
|
-
webSearch: {
|
|
274
|
-
provider: 'tavily',
|
|
275
|
-
tavily: {},
|
|
276
|
-
},
|
|
277
|
-
};
|
|
278
12
|
/**
|
|
279
13
|
* Service for managing application settings.
|
|
280
14
|
* Follows singleton pattern and supports:
|
|
@@ -292,19 +26,6 @@ export class SettingsService {
|
|
|
292
26
|
disableFilePersistence;
|
|
293
27
|
listeners = new Set();
|
|
294
28
|
loggingService;
|
|
295
|
-
// Detect if running in test environment
|
|
296
|
-
//
|
|
297
|
-
// We intentionally use a broad set of signals because different test runners
|
|
298
|
-
// set different environment variables. This prevents unit/integration tests
|
|
299
|
-
// from writing to disk by default (which can cause flaky tests and polluted
|
|
300
|
-
// developer machines/CI workspaces).
|
|
301
|
-
isTestEnvironment() {
|
|
302
|
-
return (process.env.NODE_ENV === 'test' ||
|
|
303
|
-
process.env.VITEST !== undefined ||
|
|
304
|
-
process.env.AVA_PATH !== undefined ||
|
|
305
|
-
process.env.JEST_WORKER_ID !== undefined ||
|
|
306
|
-
process.env.TERM2_TEST_MODE === 'true');
|
|
307
|
-
}
|
|
308
29
|
constructor(options) {
|
|
309
30
|
const { settingsDir = path.join(paths.log), disableLogging = false, disableFilePersistence, cli = {}, env = {}, loggingService, } = options ?? {};
|
|
310
31
|
const resolvedDisableLogging = disableLogging || parseBooleanEnv(process.env.DISABLE_LOGGING);
|
|
@@ -319,8 +40,7 @@ export class SettingsService {
|
|
|
319
40
|
});
|
|
320
41
|
// Disk persistence can be explicitly disabled (e.g., for tests), and is
|
|
321
42
|
// also automatically disabled when running under a known test runner.
|
|
322
|
-
this.disableFilePersistence =
|
|
323
|
-
disableFilePersistence ?? this.isTestEnvironment();
|
|
43
|
+
this.disableFilePersistence = disableFilePersistence ?? isTestEnvironment();
|
|
324
44
|
// Ensure settings directory exists
|
|
325
45
|
if (!fs.existsSync(this.settingsDir)) {
|
|
326
46
|
try {
|
|
@@ -329,9 +49,7 @@ export class SettingsService {
|
|
|
329
49
|
catch (error) {
|
|
330
50
|
if (!this.disableLogging) {
|
|
331
51
|
this.loggingService.error('Failed to create settings directory', {
|
|
332
|
-
error: error instanceof Error
|
|
333
|
-
? error.message
|
|
334
|
-
: String(error),
|
|
52
|
+
error: error instanceof Error ? error.message : String(error),
|
|
335
53
|
path: this.settingsDir,
|
|
336
54
|
});
|
|
337
55
|
}
|
|
@@ -341,8 +59,11 @@ export class SettingsService {
|
|
|
341
59
|
const settingsFilePath = path.join(this.settingsDir, 'settings.json');
|
|
342
60
|
const configFileExisted = fs.existsSync(settingsFilePath);
|
|
343
61
|
const { validated: fileConfig, raw: rawFileConfig } = this.loadFromFile();
|
|
344
|
-
this.settings =
|
|
345
|
-
|
|
62
|
+
this.settings = mergeSettings(DEFAULT_SETTINGS, fileConfig, env, cli, {
|
|
63
|
+
disableLogging: this.disableLogging,
|
|
64
|
+
loggingService: this.loggingService,
|
|
65
|
+
});
|
|
66
|
+
this.sources = trackSettingSources(DEFAULT_SETTINGS, fileConfig, env, cli);
|
|
346
67
|
// Register any runtime-defined providers from settings.json so they appear
|
|
347
68
|
// in the model selection menu and can be selected as agent.provider.
|
|
348
69
|
this.registerRuntimeProviders();
|
|
@@ -357,24 +78,21 @@ export class SettingsService {
|
|
|
357
78
|
catch (error) {
|
|
358
79
|
if (!this.disableLogging) {
|
|
359
80
|
this.loggingService.warn('Failed to apply logging level from settings', {
|
|
360
|
-
error: error instanceof Error
|
|
361
|
-
? error.message
|
|
362
|
-
: String(error),
|
|
81
|
+
error: error instanceof Error ? error.message : String(error),
|
|
363
82
|
loggingLevel: this.settings.logging.logLevel,
|
|
364
83
|
});
|
|
365
84
|
}
|
|
366
85
|
}
|
|
367
86
|
if (!this.disableLogging) {
|
|
368
87
|
this.loggingService.info('SettingsService initialized', {
|
|
369
|
-
cliOverrides: Object.keys(
|
|
370
|
-
envOverrides: Object.keys(
|
|
371
|
-
configOverrides: Object.keys(
|
|
88
|
+
cliOverrides: Object.keys(flattenSettings(cli)).length > 0,
|
|
89
|
+
envOverrides: Object.keys(flattenSettings(env)).length > 0,
|
|
90
|
+
configOverrides: Object.keys(flattenSettings(fileConfig)).length > 0,
|
|
372
91
|
});
|
|
373
92
|
}
|
|
374
93
|
// Check if file config is missing any keys that exist in defaults
|
|
375
94
|
// Use raw file config (pre-Zod) to detect missing keys since Zod adds defaults
|
|
376
|
-
const shouldUpdateFile = configFileExisted &&
|
|
377
|
-
this.hasMissingKeys(rawFileConfig, DEFAULT_SETTINGS);
|
|
95
|
+
const shouldUpdateFile = configFileExisted && this.hasMissingKeys(rawFileConfig, DEFAULT_SETTINGS);
|
|
378
96
|
// If there was no config file on disk, persist the current merged settings so
|
|
379
97
|
// users get a settings.json created at startup (rather than waiting for a
|
|
380
98
|
// manual change). saveToFile is safe and handles errors/logging internally.
|
|
@@ -412,7 +130,9 @@ export class SettingsService {
|
|
|
412
130
|
const existing = getProvider(providerId);
|
|
413
131
|
if (existing && !existing.isRuntimeDefined) {
|
|
414
132
|
if (!this.disableLogging) {
|
|
415
|
-
this.loggingService.warn('Skipping custom provider because it conflicts with a built-in provider id', {
|
|
133
|
+
this.loggingService.warn('Skipping custom provider because it conflicts with a built-in provider id', {
|
|
134
|
+
providerId,
|
|
135
|
+
});
|
|
416
136
|
}
|
|
417
137
|
continue;
|
|
418
138
|
}
|
|
@@ -420,18 +140,14 @@ export class SettingsService {
|
|
|
420
140
|
upsertProvider(createOpenAICompatibleProviderDefinition({
|
|
421
141
|
name: String(providerId),
|
|
422
142
|
baseUrl: String(baseUrl),
|
|
423
|
-
apiKey: p?.apiKey
|
|
424
|
-
? String(p.apiKey)
|
|
425
|
-
: undefined,
|
|
143
|
+
apiKey: p?.apiKey ? String(p.apiKey) : undefined,
|
|
426
144
|
}));
|
|
427
145
|
}
|
|
428
146
|
catch (error) {
|
|
429
147
|
if (!this.disableLogging) {
|
|
430
148
|
this.loggingService.warn('Failed to register custom provider', {
|
|
431
149
|
providerId,
|
|
432
|
-
error: error instanceof Error
|
|
433
|
-
? error.message
|
|
434
|
-
: String(error),
|
|
150
|
+
error: error instanceof Error ? error.message : String(error),
|
|
435
151
|
});
|
|
436
152
|
}
|
|
437
153
|
}
|
|
@@ -442,7 +158,9 @@ export class SettingsService {
|
|
|
442
158
|
if (getProvider(current))
|
|
443
159
|
return;
|
|
444
160
|
if (!this.disableLogging) {
|
|
445
|
-
this.loggingService.warn('Configured agent.provider is not registered; falling back to openai', {
|
|
161
|
+
this.loggingService.warn('Configured agent.provider is not registered; falling back to openai', {
|
|
162
|
+
provider: current,
|
|
163
|
+
});
|
|
446
164
|
}
|
|
447
165
|
this.settings.agent.provider = 'openai';
|
|
448
166
|
this.sources.set('agent.provider', 'default');
|
|
@@ -515,9 +233,7 @@ export class SettingsService {
|
|
|
515
233
|
catch (err) {
|
|
516
234
|
if (!this.disableLogging) {
|
|
517
235
|
this.loggingService.warn('Failed to update logging level at runtime', {
|
|
518
|
-
error: err instanceof Error
|
|
519
|
-
? err.message
|
|
520
|
-
: String(err),
|
|
236
|
+
error: err instanceof Error ? err.message : String(err),
|
|
521
237
|
loggingLevel: value,
|
|
522
238
|
});
|
|
523
239
|
}
|
|
@@ -530,9 +246,7 @@ export class SettingsService {
|
|
|
530
246
|
catch (err) {
|
|
531
247
|
if (!this.disableLogging) {
|
|
532
248
|
this.loggingService.warn('Failed to update console output suppression at runtime', {
|
|
533
|
-
error: err instanceof Error
|
|
534
|
-
? err.message
|
|
535
|
-
: String(err),
|
|
249
|
+
error: err instanceof Error ? err.message : String(err),
|
|
536
250
|
suppressConsoleOutput: value,
|
|
537
251
|
});
|
|
538
252
|
}
|
|
@@ -600,9 +314,7 @@ export class SettingsService {
|
|
|
600
314
|
catch (error) {
|
|
601
315
|
if (!this.disableLogging) {
|
|
602
316
|
this.loggingService.warn('Settings change listener threw', {
|
|
603
|
-
error: error instanceof Error
|
|
604
|
-
? error.message
|
|
605
|
-
: String(error),
|
|
317
|
+
error: error instanceof Error ? error.message : String(error),
|
|
606
318
|
changedKey,
|
|
607
319
|
});
|
|
608
320
|
}
|
|
@@ -781,38 +493,12 @@ export class SettingsService {
|
|
|
781
493
|
* Returns both raw (pre-Zod) and validated data
|
|
782
494
|
*/
|
|
783
495
|
loadFromFile() {
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
const parsed = JSON.parse(content);
|
|
791
|
-
// Validate and parse with Zod
|
|
792
|
-
const validated = SettingsSchema.safeParse(parsed);
|
|
793
|
-
if (!validated.success) {
|
|
794
|
-
if (!this.disableLogging) {
|
|
795
|
-
this.loggingService.warn('Settings file contains invalid values', {
|
|
796
|
-
errors: validated.error.issues.map(issue => ({
|
|
797
|
-
path: issue.path.join('.'),
|
|
798
|
-
message: issue.message,
|
|
799
|
-
})),
|
|
800
|
-
});
|
|
801
|
-
}
|
|
802
|
-
// Return empty object to trigger defaults
|
|
803
|
-
return { validated: {}, raw: parsed };
|
|
804
|
-
}
|
|
805
|
-
return { validated: validated.data, raw: parsed };
|
|
806
|
-
}
|
|
807
|
-
catch (error) {
|
|
808
|
-
if (!this.disableLogging) {
|
|
809
|
-
this.loggingService.error('Failed to load settings file', {
|
|
810
|
-
error: error instanceof Error ? error.message : String(error),
|
|
811
|
-
settingsFile: path.join(this.settingsDir, 'settings.json'),
|
|
812
|
-
});
|
|
813
|
-
}
|
|
814
|
-
return { validated: {}, raw: {} };
|
|
815
|
-
}
|
|
496
|
+
return loadSettingsFromFile({
|
|
497
|
+
settingsDir: this.settingsDir,
|
|
498
|
+
schema: SettingsSchema,
|
|
499
|
+
disableLogging: this.disableLogging,
|
|
500
|
+
loggingService: this.loggingService,
|
|
501
|
+
});
|
|
816
502
|
}
|
|
817
503
|
/**
|
|
818
504
|
* Save settings to file, excluding sensitive values
|
|
@@ -821,293 +507,22 @@ export class SettingsService {
|
|
|
821
507
|
if (this.disableFilePersistence) {
|
|
822
508
|
return;
|
|
823
509
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
const settingsToSave = this.stripSensitiveSettings(this.settings);
|
|
832
|
-
const newContent = JSON.stringify(settingsToSave, null, 2);
|
|
833
|
-
// Only write if file doesn't exist or content has changed
|
|
834
|
-
// Compare parsed objects rather than string content to avoid false positives
|
|
835
|
-
// from formatting differences
|
|
836
|
-
if (fs.existsSync(settingsFile)) {
|
|
837
|
-
try {
|
|
838
|
-
const existingContent = fs.readFileSync(settingsFile, 'utf-8');
|
|
839
|
-
const existingParsed = JSON.parse(existingContent);
|
|
840
|
-
// Deep equality check that ignores formatting and key order
|
|
841
|
-
// Uses fast-deep-equal library for robust comparison
|
|
842
|
-
if (deepEqual(existingParsed, settingsToSave)) {
|
|
843
|
-
return; // No changes, don't write
|
|
844
|
-
}
|
|
845
|
-
}
|
|
846
|
-
catch (parseError) {
|
|
847
|
-
// If we can't parse the existing file, write the new content anyway
|
|
848
|
-
// This handles corrupted files gracefully
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
fs.writeFileSync(settingsFile, newContent, 'utf-8');
|
|
852
|
-
}
|
|
853
|
-
catch (error) {
|
|
854
|
-
if (!this.disableLogging) {
|
|
855
|
-
this.loggingService.error('Failed to save settings file', {
|
|
856
|
-
error: error instanceof Error ? error.message : String(error),
|
|
857
|
-
settingsFile: path.join(this.settingsDir, 'settings.json'),
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
/**
|
|
863
|
-
* Remove sensitive settings that should never be persisted to disk
|
|
864
|
-
*/
|
|
865
|
-
stripSensitiveSettings(settings) {
|
|
866
|
-
const cleaned = JSON.parse(JSON.stringify(settings));
|
|
867
|
-
// Remove sensitive openrouter fields (keep non-secret config)
|
|
868
|
-
if (cleaned.agent?.openrouter) {
|
|
869
|
-
delete cleaned.agent.openrouter.apiKey;
|
|
870
|
-
delete cleaned.agent.openrouter.baseUrl;
|
|
871
|
-
delete cleaned.agent.openrouter.referrer;
|
|
872
|
-
delete cleaned.agent.openrouter.title;
|
|
873
|
-
// Only keep model if it's set (it's not sensitive)
|
|
874
|
-
if (Object.keys(cleaned.agent.openrouter).length === 0) {
|
|
875
|
-
delete cleaned.agent.openrouter;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
// Remove sensitive app settings
|
|
879
|
-
if (cleaned.app) {
|
|
880
|
-
delete cleaned.app.shellPath;
|
|
881
|
-
// mentorMode and editMode are persisted so they survive across sessions
|
|
882
|
-
}
|
|
883
|
-
return cleaned;
|
|
510
|
+
saveSettingsToFile({
|
|
511
|
+
settingsDir: this.settingsDir,
|
|
512
|
+
settings: this.settings,
|
|
513
|
+
stripSensitiveSettings,
|
|
514
|
+
disableLogging: this.disableLogging,
|
|
515
|
+
loggingService: this.loggingService,
|
|
516
|
+
});
|
|
884
517
|
}
|
|
885
518
|
/**
|
|
886
519
|
* Check if target object is missing any keys that exist in source
|
|
887
520
|
*/
|
|
888
521
|
hasMissingKeys(target, source, prefix = '') {
|
|
889
|
-
|
|
890
|
-
if (!source.hasOwnProperty(key))
|
|
891
|
-
continue;
|
|
892
|
-
const pathKey = prefix ? `${prefix}.${key}` : key;
|
|
893
|
-
const sourceValue = source[key];
|
|
894
|
-
if (!(key in target)) {
|
|
895
|
-
// Skip optional default keys when deciding whether to rewrite file
|
|
896
|
-
if (OPTIONAL_DEFAULT_KEYS.has(pathKey)) {
|
|
897
|
-
continue;
|
|
898
|
-
}
|
|
899
|
-
// If the default value is undefined, treat it as optional for persistence
|
|
900
|
-
if (typeof sourceValue === 'undefined') {
|
|
901
|
-
continue;
|
|
902
|
-
}
|
|
903
|
-
return true;
|
|
904
|
-
}
|
|
905
|
-
const targetValue = target[key];
|
|
906
|
-
// Recursively check nested objects
|
|
907
|
-
if (sourceValue &&
|
|
908
|
-
typeof sourceValue === 'object' &&
|
|
909
|
-
!Array.isArray(sourceValue) &&
|
|
910
|
-
targetValue &&
|
|
911
|
-
typeof targetValue === 'object' &&
|
|
912
|
-
!Array.isArray(targetValue)) {
|
|
913
|
-
if (this.hasMissingKeys(targetValue, sourceValue, pathKey)) {
|
|
914
|
-
return true;
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
}
|
|
918
|
-
return false;
|
|
522
|
+
return hasMissingKeys(target, source, OPTIONAL_DEFAULT_KEYS, prefix);
|
|
919
523
|
}
|
|
920
|
-
/**
|
|
921
|
-
* Flatten nested object to dot notation
|
|
922
|
-
*/
|
|
923
|
-
flattenSettings(obj, prefix = '') {
|
|
924
|
-
const result = {};
|
|
925
|
-
for (const key in obj) {
|
|
926
|
-
if (!obj.hasOwnProperty(key))
|
|
927
|
-
continue;
|
|
928
|
-
const value = obj[key];
|
|
929
|
-
const newKey = prefix ? `${prefix}.${key}` : key;
|
|
930
|
-
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
931
|
-
Object.assign(result, this.flattenSettings(value, newKey));
|
|
932
|
-
}
|
|
933
|
-
else {
|
|
934
|
-
result[newKey] = value;
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
return result;
|
|
938
|
-
}
|
|
939
|
-
/**
|
|
940
|
-
* Merge multiple settings sources with proper precedence
|
|
941
|
-
*/
|
|
942
|
-
merge(defaults, fileConfig, env, cli) {
|
|
943
|
-
// Deep merge starting with defaults
|
|
944
|
-
const result = JSON.parse(JSON.stringify(defaults));
|
|
945
|
-
// Merge file config
|
|
946
|
-
this.deepMerge(result, fileConfig);
|
|
947
|
-
// Merge env
|
|
948
|
-
this.deepMerge(result, env);
|
|
949
|
-
// Merge cli (highest priority)
|
|
950
|
-
this.deepMerge(result, cli);
|
|
951
|
-
// Ensure all required fields are present
|
|
952
|
-
const merged = {
|
|
953
|
-
providers: result.providers ||
|
|
954
|
-
JSON.parse(JSON.stringify(defaults.providers)),
|
|
955
|
-
agent: result.agent || JSON.parse(JSON.stringify(defaults.agent)),
|
|
956
|
-
shell: result.shell || JSON.parse(JSON.stringify(defaults.shell)),
|
|
957
|
-
ui: result.ui || JSON.parse(JSON.stringify(defaults.ui)),
|
|
958
|
-
logging: result.logging || JSON.parse(JSON.stringify(defaults.logging)),
|
|
959
|
-
environment: result.environment ||
|
|
960
|
-
JSON.parse(JSON.stringify(defaults.environment)),
|
|
961
|
-
app: result.app || JSON.parse(JSON.stringify(defaults.app)),
|
|
962
|
-
tools: result.tools || JSON.parse(JSON.stringify(defaults.tools)),
|
|
963
|
-
debug: result.debug || JSON.parse(JSON.stringify(defaults.debug)),
|
|
964
|
-
ssh: result.ssh || JSON.parse(JSON.stringify(defaults.ssh)),
|
|
965
|
-
webSearch: result.webSearch ||
|
|
966
|
-
JSON.parse(JSON.stringify(defaults.webSearch)),
|
|
967
|
-
};
|
|
968
|
-
// Validate final result
|
|
969
|
-
const validated = SettingsSchema.safeParse(merged);
|
|
970
|
-
if (validated.success) {
|
|
971
|
-
// Ensure we return a complete SettingsData object
|
|
972
|
-
return {
|
|
973
|
-
providers: merged.providers,
|
|
974
|
-
agent: merged.agent,
|
|
975
|
-
shell: merged.shell,
|
|
976
|
-
ui: merged.ui,
|
|
977
|
-
logging: merged.logging,
|
|
978
|
-
environment: merged.environment,
|
|
979
|
-
app: merged.app,
|
|
980
|
-
tools: merged.tools,
|
|
981
|
-
debug: merged.debug,
|
|
982
|
-
ssh: merged.ssh,
|
|
983
|
-
webSearch: merged.webSearch,
|
|
984
|
-
};
|
|
985
|
-
}
|
|
986
|
-
// If validation fails, return defaults
|
|
987
|
-
if (!this.disableLogging) {
|
|
988
|
-
this.loggingService.warn('Final merged settings failed validation, using defaults', {
|
|
989
|
-
errors: validated.error.issues.map(issue => ({
|
|
990
|
-
path: issue.path.join('.'),
|
|
991
|
-
message: issue.message,
|
|
992
|
-
})),
|
|
993
|
-
});
|
|
994
|
-
}
|
|
995
|
-
return defaults;
|
|
996
|
-
}
|
|
997
|
-
/**
|
|
998
|
-
* Deep merge source into target
|
|
999
|
-
*/
|
|
1000
|
-
deepMerge(target, source) {
|
|
1001
|
-
for (const key in source) {
|
|
1002
|
-
if (!source.hasOwnProperty(key))
|
|
1003
|
-
continue;
|
|
1004
|
-
const sourceValue = source[key];
|
|
1005
|
-
if (sourceValue &&
|
|
1006
|
-
typeof sourceValue === 'object' &&
|
|
1007
|
-
!Array.isArray(sourceValue)) {
|
|
1008
|
-
if (!target[key] || typeof target[key] !== 'object') {
|
|
1009
|
-
target[key] = {};
|
|
1010
|
-
}
|
|
1011
|
-
this.deepMerge(target[key], sourceValue);
|
|
1012
|
-
}
|
|
1013
|
-
else {
|
|
1014
|
-
target[key] = sourceValue;
|
|
1015
|
-
}
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
/**
|
|
1019
|
-
* Track the source of each setting
|
|
1020
|
-
*/
|
|
1021
|
-
trackSources(defaults, fileConfig, env, cli) {
|
|
1022
|
-
const flatDefaults = this.flattenSettings(defaults);
|
|
1023
|
-
const flatFileConfig = this.flattenSettings(fileConfig);
|
|
1024
|
-
const flatEnv = this.flattenSettings(env);
|
|
1025
|
-
const flatCli = this.flattenSettings(cli);
|
|
1026
|
-
// For each possible setting key, determine its source
|
|
1027
|
-
for (const key in flatDefaults) {
|
|
1028
|
-
if (flatCli.hasOwnProperty(key)) {
|
|
1029
|
-
this.sources.set(key, 'cli');
|
|
1030
|
-
}
|
|
1031
|
-
else if (flatEnv.hasOwnProperty(key)) {
|
|
1032
|
-
this.sources.set(key, 'env');
|
|
1033
|
-
}
|
|
1034
|
-
else if (flatFileConfig.hasOwnProperty(key)) {
|
|
1035
|
-
this.sources.set(key, 'config');
|
|
1036
|
-
}
|
|
1037
|
-
else {
|
|
1038
|
-
this.sources.set(key, 'default');
|
|
1039
|
-
}
|
|
1040
|
-
}
|
|
1041
|
-
}
|
|
1042
|
-
}
|
|
1043
|
-
/**
|
|
1044
|
-
* Build environment-derived overrides from process.env
|
|
1045
|
-
* Exported for use in CLI initialization
|
|
1046
|
-
*/
|
|
1047
|
-
export function buildEnvOverrides() {
|
|
1048
|
-
const env = (typeof process !== 'undefined' ? process.env : {});
|
|
1049
|
-
const openrouter = {};
|
|
1050
|
-
if (env.OPENROUTER_API_KEY)
|
|
1051
|
-
openrouter.apiKey = env.OPENROUTER_API_KEY;
|
|
1052
|
-
if (env.OPENROUTER_MODEL)
|
|
1053
|
-
openrouter.model = env.OPENROUTER_MODEL;
|
|
1054
|
-
if (env.OPENROUTER_BASE_URL)
|
|
1055
|
-
openrouter.baseUrl = env.OPENROUTER_BASE_URL;
|
|
1056
|
-
if (env.OPENROUTER_REFERRER)
|
|
1057
|
-
openrouter.referrer = env.OPENROUTER_REFERRER;
|
|
1058
|
-
if (env.OPENROUTER_TITLE)
|
|
1059
|
-
openrouter.title = env.OPENROUTER_TITLE;
|
|
1060
|
-
const logging = {};
|
|
1061
|
-
if (env.LOG_LEVEL)
|
|
1062
|
-
logging.logLevel = env.LOG_LEVEL;
|
|
1063
|
-
if (env.DISABLE_LOGGING !== undefined)
|
|
1064
|
-
logging.disableLogging = String(env.DISABLE_LOGGING) === 'true';
|
|
1065
|
-
if (env.DEBUG_LOGGING !== undefined)
|
|
1066
|
-
logging.debugLogging = true;
|
|
1067
|
-
const environment = {
|
|
1068
|
-
nodeEnv: env.NODE_ENV,
|
|
1069
|
-
};
|
|
1070
|
-
const app = {
|
|
1071
|
-
shellPath: env.SHELL || env.COMSPEC,
|
|
1072
|
-
};
|
|
1073
|
-
const tools = {};
|
|
1074
|
-
if (env.LOG_FILE_OPERATIONS !== undefined)
|
|
1075
|
-
tools.logFileOperations = String(env.LOG_FILE_OPERATIONS) !== 'false';
|
|
1076
|
-
const debug = {};
|
|
1077
|
-
if (env.DEBUG_BASH_TOOL !== undefined)
|
|
1078
|
-
debug.debugBashTool = true;
|
|
1079
|
-
const webSearch = {};
|
|
1080
|
-
if (env.TAVILY_API_KEY) {
|
|
1081
|
-
webSearch.tavily = { apiKey: env.TAVILY_API_KEY };
|
|
1082
|
-
}
|
|
1083
|
-
if (env.WEB_SEARCH_PROVIDER) {
|
|
1084
|
-
webSearch.provider = env.WEB_SEARCH_PROVIDER;
|
|
1085
|
-
}
|
|
1086
|
-
const agent = { openrouter };
|
|
1087
|
-
return {
|
|
1088
|
-
agent,
|
|
1089
|
-
logging,
|
|
1090
|
-
environment,
|
|
1091
|
-
app,
|
|
1092
|
-
tools,
|
|
1093
|
-
debug,
|
|
1094
|
-
webSearch,
|
|
1095
|
-
};
|
|
1096
524
|
}
|
|
1097
|
-
|
|
1098
|
-
if (typeof value !== 'string') {
|
|
1099
|
-
return false;
|
|
1100
|
-
}
|
|
1101
|
-
const normalized = value.trim().toLowerCase();
|
|
1102
|
-
return normalized === '1' || normalized === 'true' || normalized === 'yes';
|
|
1103
|
-
};
|
|
1104
|
-
const isTestEnvironment = () => {
|
|
1105
|
-
return (process.env.NODE_ENV === 'test' ||
|
|
1106
|
-
process.env.VITEST !== undefined ||
|
|
1107
|
-
process.env.AVA_PATH !== undefined ||
|
|
1108
|
-
process.env.JEST_WORKER_ID !== undefined ||
|
|
1109
|
-
process.env.TERM2_TEST_MODE === 'true');
|
|
1110
|
-
};
|
|
525
|
+
export { buildEnvOverrides } from './settings-env.js';
|
|
1111
526
|
/**
|
|
1112
527
|
* @deprecated DO NOT USE - Singleton pattern is deprecated
|
|
1113
528
|
*
|
|
@@ -1124,8 +539,7 @@ const isTestEnvironment = () => {
|
|
|
1124
539
|
const _settingsServiceInstance = new SettingsService({
|
|
1125
540
|
env: buildEnvOverrides(),
|
|
1126
541
|
loggingService: new LoggingService({
|
|
1127
|
-
disableLogging: parseBooleanEnv(process.env.DISABLE_LOGGING) ||
|
|
1128
|
-
isTestEnvironment(),
|
|
542
|
+
disableLogging: parseBooleanEnv(process.env.DISABLE_LOGGING) || isTestEnvironment(),
|
|
1129
543
|
debugLogging: parseBooleanEnv(process.env.DEBUG_LOGGING),
|
|
1130
544
|
}),
|
|
1131
545
|
});
|
|
@@ -1152,15 +566,5 @@ export const settingsService = new Proxy(_settingsServiceInstance, {
|
|
|
1152
566
|
`See source/app.tsx for an example of proper dependency injection.`);
|
|
1153
567
|
},
|
|
1154
568
|
});
|
|
1155
|
-
|
|
1156
|
-
* Publicly exported list of sensitive settings for UI/CLI components to use.
|
|
1157
|
-
* These settings should only be configured via environment variables.
|
|
1158
|
-
*/
|
|
1159
|
-
export const SENSITIVE_SETTINGS = {
|
|
1160
|
-
AGENT_OPENROUTER_API_KEY: 'agent.openrouter.apiKey',
|
|
1161
|
-
AGENT_OPENROUTER_BASE_URL: 'agent.openrouter.baseUrl',
|
|
1162
|
-
AGENT_OPENROUTER_REFERRER: 'agent.openrouter.referrer',
|
|
1163
|
-
AGENT_OPENROUTER_TITLE: 'agent.openrouter.title',
|
|
1164
|
-
APP_SHELL_PATH: 'app.shellPath',
|
|
1165
|
-
};
|
|
569
|
+
export { SETTING_KEYS, SENSITIVE_SETTINGS } from './settings-schema.js';
|
|
1166
570
|
//# sourceMappingURL=settings-service.js.map
|