@within-7/minto 0.3.10 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +2 -2
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/ctx_viz.js +1 -1
- package/dist/commands/effort.js +87 -0
- package/dist/commands/effort.js.map +7 -0
- package/dist/commands/export.js +19 -9
- package/dist/commands/export.js.map +2 -2
- package/dist/commands/ide.js +18 -0
- package/dist/commands/ide.js.map +7 -0
- package/dist/commands/mcp-interactive.js +14 -8
- package/dist/commands/mcp-interactive.js.map +2 -2
- package/dist/commands/memory.js +168 -0
- package/dist/commands/memory.js.map +7 -0
- package/dist/commands/model.js +45 -2
- package/dist/commands/model.js.map +2 -2
- package/dist/commands/outputStyle.js +64 -0
- package/dist/commands/outputStyle.js.map +7 -0
- package/dist/commands/plugin/utils.js +33 -1
- package/dist/commands/plugin/utils.js.map +2 -2
- package/dist/commands/plugin.js +10 -1
- package/dist/commands/plugin.js.map +2 -2
- package/dist/commands/refreshCommands.js +2 -0
- package/dist/commands/refreshCommands.js.map +2 -2
- package/dist/commands/review.js +51 -0
- package/dist/commands/review.js.map +7 -0
- package/dist/commands/terminalSetup.js +6 -0
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands/undo.js +8 -0
- package/dist/commands/undo.js.map +2 -2
- package/dist/commands/vim.js +22 -0
- package/dist/commands/vim.js.map +7 -0
- package/dist/commands.js +12 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/HighlightedCode.js +1 -0
- package/dist/components/HighlightedCode.js.map +2 -2
- package/dist/components/ModelSelector/ModelSelector.js +250 -143
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/PromptInput.js +21 -6
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/PulseLabel.js +44 -0
- package/dist/components/PulseLabel.js.map +7 -0
- package/dist/components/RequestStatusIndicator.js +1 -1
- package/dist/components/RequestStatusIndicator.js.map +1 -1
- package/dist/components/Spinner.js +12 -42
- package/dist/components/Spinner.js.map +3 -3
- package/dist/components/StartupStatus.js +57 -0
- package/dist/components/StartupStatus.js.map +7 -0
- package/dist/components/SubagentBlock.js +43 -6
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/TabbedListView/TabBar.js +13 -8
- package/dist/components/TabbedListView/TabBar.js.map +2 -2
- package/dist/components/TabbedListView/TabbedListView.js +1 -1
- package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
- package/dist/components/TodoPanel.js +1 -1
- package/dist/components/TodoPanel.js.map +1 -1
- package/dist/components/ToolUseLoader.js +5 -0
- package/dist/components/ToolUseLoader.js.map +2 -2
- package/dist/components/TrustDialog.js +0 -2
- package/dist/components/TrustDialog.js.map +2 -2
- package/dist/components/messages/TaskInModuleView.js +1 -1
- package/dist/components/messages/TaskInModuleView.js.map +2 -2
- package/dist/components/messages/TaskToolMessage.js +1 -1
- package/dist/components/messages/TaskToolMessage.js.map +2 -2
- package/dist/components/messages/UserPromptMessage.js +6 -1
- package/dist/components/messages/UserPromptMessage.js.map +2 -2
- package/dist/constants/modelCapabilities.js +103 -18
- package/dist/constants/modelCapabilities.js.map +2 -2
- package/dist/constants/product.js +2 -0
- package/dist/constants/product.js.map +2 -2
- package/dist/constants/prompts/agentPrompt.js +30 -0
- package/dist/constants/prompts/agentPrompt.js.map +7 -0
- package/dist/constants/prompts/codeConventions.js +27 -0
- package/dist/constants/prompts/codeConventions.js.map +7 -0
- package/dist/constants/prompts/doingTasks.js +15 -0
- package/dist/constants/prompts/doingTasks.js.map +7 -0
- package/dist/constants/prompts/envInfo.js +17 -0
- package/dist/constants/prompts/envInfo.js.map +7 -0
- package/dist/constants/prompts/executingWithCare.js +17 -0
- package/dist/constants/prompts/executingWithCare.js.map +7 -0
- package/dist/constants/prompts/identity.js +10 -0
- package/dist/constants/prompts/identity.js.map +7 -0
- package/dist/constants/prompts/index.js +78 -0
- package/dist/constants/prompts/index.js.map +7 -0
- package/dist/constants/prompts/taskManagement.js +60 -0
- package/dist/constants/prompts/taskManagement.js.map +7 -0
- package/dist/constants/prompts/toneAndStyle.js +62 -0
- package/dist/constants/prompts/toneAndStyle.js.map +7 -0
- package/dist/constants/prompts/toolUsagePolicy.js +38 -0
- package/dist/constants/prompts/toolUsagePolicy.js.map +7 -0
- package/dist/constants/prompts.js +5 -176
- package/dist/constants/prompts.js.map +2 -2
- package/dist/constants/providerRegistry.js +235 -0
- package/dist/constants/providerRegistry.js.map +7 -0
- package/dist/constants/providers.js +35 -0
- package/dist/constants/providers.js.map +7 -0
- package/dist/context/PermissionContext.js +0 -1
- package/dist/context/PermissionContext.js.map +2 -2
- package/dist/context.js +87 -31
- package/dist/context.js.map +2 -2
- package/dist/core/backupHook.js +2 -2
- package/dist/core/backupHook.js.map +2 -2
- package/dist/core/config/defaults.js +4 -1
- package/dist/core/config/defaults.js.map +2 -2
- package/dist/core/config/schema.js +7 -1
- package/dist/core/config/schema.js.map +2 -2
- package/dist/core/costTracker.js +18 -0
- package/dist/core/costTracker.js.map +2 -2
- package/dist/core/index.js +0 -1
- package/dist/core/index.js.map +2 -2
- package/dist/core/tokenStatsManager.js +22 -4
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/entrypoints/cli.js +65 -84
- package/dist/entrypoints/cli.js.map +2 -2
- package/dist/hooks/useAgentTokenStats.js +1 -1
- package/dist/hooks/useAgentTokenStats.js.map +2 -2
- package/dist/hooks/useAgentTranscripts.js +2 -1
- package/dist/hooks/useAgentTranscripts.js.map +2 -2
- package/dist/hooks/useBackgroundShells.js +29 -0
- package/dist/hooks/useBackgroundShells.js.map +7 -0
- package/dist/hooks/useCanUseTool.js +1 -1
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useDeferredLoading.js +64 -0
- package/dist/hooks/useDeferredLoading.js.map +7 -0
- package/dist/hooks/useHookStatus.js +1 -1
- package/dist/hooks/useHookStatus.js.map +2 -2
- package/dist/hooks/useSessionTracking.js +55 -0
- package/dist/hooks/useSessionTracking.js.map +7 -0
- package/dist/hooks/useTerminalSize.js +21 -0
- package/dist/hooks/useTerminalSize.js.map +2 -2
- package/dist/hooks/useTextInput.js +1 -0
- package/dist/hooks/useTextInput.js.map +2 -2
- package/dist/hooks/useUnifiedCompletion.js +3 -2
- package/dist/hooks/useUnifiedCompletion.js.map +2 -2
- package/dist/i18n/locales/en.js +8 -9
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +8 -9
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/messages.js +41 -17
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js +94 -1
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +27 -19
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +83 -74
- package/dist/screens/REPL.js.map +2 -2
- package/dist/services/adapters/responsesAPI.js +6 -0
- package/dist/services/adapters/responsesAPI.js.map +2 -2
- package/dist/services/agentTeams/index.js +35 -0
- package/dist/services/agentTeams/index.js.map +7 -0
- package/dist/services/agentTeams/mailbox.js +114 -0
- package/dist/services/agentTeams/mailbox.js.map +7 -0
- package/dist/services/agentTeams/teamManager.js +149 -0
- package/dist/services/agentTeams/teamManager.js.map +7 -0
- package/dist/services/agentTeams/teamTaskStore.js +114 -0
- package/dist/services/agentTeams/teamTaskStore.js.map +7 -0
- package/dist/services/agentTeams/teammateSpawner.js +80 -0
- package/dist/services/agentTeams/teammateSpawner.js.map +7 -0
- package/dist/services/checkpointManager.js +16 -3
- package/dist/services/checkpointManager.js.map +2 -2
- package/dist/services/claude.js +19 -1728
- package/dist/services/claude.js.map +3 -3
- package/dist/services/gpt5ConnectionTest.js +4 -2
- package/dist/services/gpt5ConnectionTest.js.map +2 -2
- package/dist/services/hookExecutor.js +411 -127
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/llm/anthropicProvider.js +807 -0
- package/dist/services/llm/anthropicProvider.js.map +7 -0
- package/dist/services/llm/dispatch.js +218 -0
- package/dist/services/llm/dispatch.js.map +7 -0
- package/dist/services/llm/index.js +44 -0
- package/dist/services/llm/index.js.map +7 -0
- package/dist/services/llm/mintoContext.js +69 -0
- package/dist/services/llm/mintoContext.js.map +7 -0
- package/dist/services/llm/openaiProvider.js +622 -0
- package/dist/services/llm/openaiProvider.js.map +7 -0
- package/dist/services/llm/types.js +157 -0
- package/dist/services/llm/types.js.map +7 -0
- package/dist/services/mcpClient.js +183 -33
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/notifier.js +14 -0
- package/dist/services/notifier.js.map +2 -2
- package/dist/services/oauth.js +4 -2
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +66 -56
- package/dist/services/openai.js.map +3 -3
- package/dist/services/outputStyles.js +102 -21
- package/dist/services/outputStyles.js.map +2 -2
- package/dist/services/plugins/skillMarketplace.js +4 -1
- package/dist/services/plugins/skillMarketplace.js.map +2 -2
- package/dist/services/sentry.js +1 -1
- package/dist/services/sentry.js.map +2 -2
- package/dist/services/sessionMemory.js +16 -3
- package/dist/services/sessionMemory.js.map +2 -2
- package/dist/services/systemReminder.js +350 -3
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/services/taskStore.js +19 -0
- package/dist/services/taskStore.js.map +2 -2
- package/dist/tools/ArchitectTool/ArchitectTool.js.map +1 -1
- package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +1 -1
- package/dist/tools/BashOutputTool/BashOutputTool.js.map +1 -1
- package/dist/tools/BashTool/BashTool.js +28 -0
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/FileEditTool/FileEditTool.js +1 -1
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js +14 -0
- package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
- package/dist/tools/FileWriteTool/FileWriteTool.js +3 -1
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
- package/dist/tools/GlobTool/GlobTool.js.map +1 -1
- package/dist/tools/GrepTool/GrepTool.js.map +1 -1
- package/dist/tools/KillShellTool/KillShellTool.js.map +1 -1
- package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
- package/dist/tools/LspTool/LspTool.js +11 -2
- package/dist/tools/LspTool/LspTool.js.map +2 -2
- package/dist/tools/MCPTool/MCPTool.js.map +1 -1
- package/dist/tools/MemoryReadTool/MemoryReadTool.js +2 -1
- package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +2 -1
- package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +1 -1
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +1 -1
- package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +1 -1
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js +8 -2
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js +2 -0
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
- package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +1 -1
- package/dist/tools/SlashCommandTool/SlashCommandTool.js +174 -18
- package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +3 -3
- package/dist/tools/TaskCreateTool/TaskCreateTool.js.map +1 -1
- package/dist/tools/TaskGetTool/TaskGetTool.js.map +1 -1
- package/dist/tools/TaskListTool/TaskListTool.js.map +1 -1
- package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +1 -1
- package/dist/tools/TaskStopTool/TaskStopTool.js.map +1 -1
- package/dist/tools/TaskTool/TaskTool.js +75 -5
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js +12 -6
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +1 -1
- package/dist/tools/ThinkTool/ThinkTool.js.map +1 -1
- package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +1 -1
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +1 -1
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +1 -1
- package/dist/tools/WebSearchTool/searchProviders.js +2 -1
- package/dist/tools/WebSearchTool/searchProviders.js.map +2 -2
- package/dist/tools/lsTool/lsTool.js.map +2 -2
- package/dist/tools/lsTool/prompt.js.map +1 -1
- package/dist/tools.js +14 -3
- package/dist/tools.js.map +2 -2
- package/dist/types/PermissionMode.js +21 -1
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/agentTeams.js +1 -0
- package/dist/types/agentTeams.js.map +7 -0
- package/dist/types/hooks.js +8 -2
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/plugin.js +1 -1
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/agentLoader.js +25 -3
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/animationManager.js +1 -1
- package/dist/utils/animationManager.js.map +2 -2
- package/dist/utils/ask.js +1 -1
- package/dist/utils/async.js +5 -1
- package/dist/utils/async.js.map +2 -2
- package/dist/utils/autoCompactCore.js +60 -0
- package/dist/utils/autoCompactCore.js.map +2 -2
- package/dist/utils/config.js +26 -128
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configSchema.js +227 -0
- package/dist/utils/configSchema.js.map +7 -0
- package/dist/utils/debugLogger.js.map +2 -2
- package/dist/utils/env.js +4 -3
- package/dist/utils/env.js.map +2 -2
- package/dist/utils/envConfig.js +34 -0
- package/dist/utils/envConfig.js.map +3 -3
- package/dist/utils/gpt5.js +146 -0
- package/dist/utils/gpt5.js.map +7 -0
- package/dist/utils/hookManager.js +374 -140
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/markdown.js +47 -0
- package/dist/utils/markdown.js.map +2 -2
- package/dist/utils/memoizeWithTTL.js +25 -0
- package/dist/utils/memoizeWithTTL.js.map +7 -0
- package/dist/utils/model.js +34 -9
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pluginInstaller.js +34 -5
- package/dist/utils/pluginInstaller.js.map +2 -2
- package/dist/utils/pluginLoader.js +201 -32
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/safeFetch.js +45 -0
- package/dist/utils/safeFetch.js.map +7 -0
- package/dist/utils/skillLoader.js +59 -6
- package/dist/utils/skillLoader.js.map +2 -2
- package/dist/utils/streamingState.js +52 -0
- package/dist/utils/streamingState.js.map +7 -0
- package/dist/utils/style.js +6 -3
- package/dist/utils/style.js.map +2 -2
- package/dist/utils/teamConfig.js +9 -3
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/toolRiskClassification.js +0 -6
- package/dist/utils/toolRiskClassification.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +7 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/autoCompactCore.ts"],
|
|
4
|
-
"sourcesContent": ["import { Message } from '@query'\nimport { countTokens } from './tokens'\nimport { getMessagesGetter, getMessagesSetter } from '@messages'\nimport { getContext } from '@context'\nimport { getCodeStyle } from '@utils/style'\nimport { clearTerminal } from '@utils/terminal'\nimport { resetFileFreshnessSession } from '@services/fileFreshness'\nimport { createUserMessage, normalizeMessagesForAPI } from '@utils/messages'\nimport { queryLLM } from '@services/claude'\nimport { selectAndReadFiles } from './fileRecoveryCore'\nimport { addLineNumbers } from './file'\nimport { getModelManager } from './model'\nimport { getCompressionPrompt } from '@constants/compressionPrompts'\nimport { getCompressionMode } from './compressionMode'\n\n/**\n * Threshold ratio for triggering automatic context compression\n * When context usage exceeds 92% of the model's limit, auto-compact activates\n */\nconst AUTO_COMPACT_THRESHOLD_RATIO = 0.92\n\n/**\n * Retrieves the context length for the main model that should execute compression\n * Uses ModelManager to get the current model's context length\n */\nasync function getCompressionModelContextLimit(): Promise<number> {\n try {\n // \uD83D\uDD27 Fix: Use ModelManager instead of legacy config\n const modelManager = getModelManager()\n const modelProfile = modelManager.getModel('main')\n\n if (modelProfile?.contextLength) {\n return modelProfile.contextLength\n }\n\n // Fallback to a reasonable default\n return 200_000\n } catch (error) {\n return 200_000\n }\n}\n\n/**\n * Get the appropriate compression prompt based on current compression mode\n * This is now handled by the compression mode system\n */\n\n/**\n * Calculates context usage thresholds based on the main model's capabilities\n * Uses the main model context length since compression tasks require a capable model\n */\nasync function calculateThresholds(tokenCount: number) {\n const contextLimit = await getCompressionModelContextLimit()\n const autoCompactThreshold = contextLimit * AUTO_COMPACT_THRESHOLD_RATIO\n\n return {\n isAboveAutoCompactThreshold: tokenCount >= autoCompactThreshold,\n percentUsed: Math.round((tokenCount / contextLimit) * 100),\n tokensRemaining: Math.max(0, autoCompactThreshold - tokenCount),\n contextLimit,\n }\n}\n\n/**\n * Determines if auto-compact should trigger based on token usage\n * Uses the main model context limit since compression requires a capable model\n */\nasync function shouldAutoCompact(messages: Message[]): Promise<boolean> {\n if (messages.length < 3) return false\n\n const tokenCount = countTokens(messages)\n const { isAboveAutoCompactThreshold } = await calculateThresholds(tokenCount)\n\n return isAboveAutoCompactThreshold\n}\n\n/**\n * Main entry point for automatic context compression\n *\n * This function is called before each query to check if the conversation\n * has grown too large and needs compression. When triggered, it:\n * - Generates a structured summary of the conversation using the main model\n * - Recovers recently accessed files to maintain development context\n * - Resets conversation state while preserving essential information\n *\n * Uses the main model for compression tasks to ensure high-quality summaries\n *\n * @param messages Current conversation messages\n * @param toolUseContext Execution context with model and tool configuration\n * @returns Updated messages (compressed if needed) and compression status\n */\nexport async function checkAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<{ messages: Message[]; wasCompacted: boolean }> {\n if (!(await shouldAutoCompact(messages))) {\n return { messages, wasCompacted: false }\n }\n\n try {\n const compactedMessages = await executeAutoCompact(messages, toolUseContext)\n\n return {\n messages: compactedMessages,\n wasCompacted: true,\n }\n } catch (error) {\n // Graceful degradation: if auto-compact fails, continue with original messages\n // This ensures system remains functional even if compression encounters issues\n console.error(\n 'Auto-compact failed, continuing with original messages:',\n error,\n )\n return { messages, wasCompacted: false }\n }\n}\n\n/**\n * Executes the conversation compression process using the main model\n *\n * This function generates a comprehensive summary using the main model\n * which is better suited for complex summarization tasks. It also\n * automatically recovers important files to maintain development context.\n */\nasync function executeAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<Message[]> {\n // Get the compression prompt based on current mode (business or code)\n const compressionMode = getCompressionMode()\n const compressionPrompt = getCompressionPrompt(compressionMode)\n\n const summaryRequest = createUserMessage(compressionPrompt)\n\n const summaryResponse = await queryLLM(\n normalizeMessagesForAPI([...messages, summaryRequest]),\n [\n 'You are a helpful AI assistant tasked with creating comprehensive conversation summaries that preserve all essential context for continuing development work.',\n ],\n 0,\n toolUseContext.options.tools,\n toolUseContext.abortController.signal,\n {\n safeMode: false,\n model: 'main', // \u4F7F\u7528\u6A21\u578B\u6307\u9488\uFF0C\u8BA9queryLLM\u7EDF\u4E00\u89E3\u6790\n prependCLISysprompt: true,\n },\n )\n\n const content = summaryResponse.message.content\n const summary =\n typeof content === 'string'\n ? content\n : content.length > 0 && content[0]?.type === 'text'\n ? content[0].text\n : null\n\n if (!summary) {\n throw new Error(\n 'Failed to generate conversation summary - response did not contain valid text content',\n )\n }\n\n summaryResponse.message.usage = {\n input_tokens: 0,\n output_tokens: summaryResponse.message.usage.output_tokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n }\n\n // Automatic file recovery: preserve recently accessed development files\n // This maintains coding context even after conversation compression\n const recoveredFiles = await selectAndReadFiles()\n\n const compactedMessages = [\n createUserMessage(\n 'Context automatically compressed due to token limit. Essential information preserved.',\n ),\n summaryResponse,\n ]\n\n // Append recovered files to maintain development workflow continuity\n // Files are prioritized by recency and importance, with strict token limits\n if (recoveredFiles.length > 0) {\n for (const file of recoveredFiles) {\n const contentWithLines = addLineNumbers({\n content: file.content,\n startLine: 1,\n })\n const recoveryMessage = createUserMessage(\n `**Recovered File: ${file.path}**\\n\\n\\`\\`\\`\\n${contentWithLines}\\n\\`\\`\\`\\n\\n` +\n `*Automatically recovered (${file.tokens} tokens)${file.truncated ? ' [truncated]' : ''}*`,\n )\n compactedMessages.push(recoveryMessage)\n }\n }\n\n // State cleanup to ensure fresh context after compression\n // Mirrors the cleanup sequence from manual /compact command\n getMessagesSetter()([])\n getContext.cache.clear?.()\n getCodeStyle.cache.clear?.()\n resetFileFreshnessSession()\n\n return compactedMessages\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import { existsSync, mkdirSync, appendFileSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { Message } from '@query'\nimport { countTokens } from './tokens'\nimport { getMessagesGetter, getMessagesSetter } from '@messages'\nimport { getContext } from '@context'\nimport { getCodeStyle } from '@utils/style'\nimport { clearTerminal } from '@utils/terminal'\nimport { resetFileFreshnessSession } from '@services/fileFreshness'\nimport { createUserMessage, normalizeMessagesForAPI } from '@utils/messages'\nimport { queryLLM } from '@services/claude'\nimport { selectAndReadFiles } from './fileRecoveryCore'\nimport { addLineNumbers } from './file'\nimport { getModelManager } from './model'\nimport { getCompressionPrompt } from '@constants/compressionPrompts'\nimport { getCompressionMode } from './compressionMode'\nimport { getHookManager } from './hookManager'\nimport { emitReminderEvent } from '@services/systemReminder'\nimport { CONFIG_BASE_DIR } from '@constants/product'\nimport { getGlobalConfig } from './config'\n\n/**\n * Threshold ratio for triggering automatic context compression\n * When context usage exceeds 92% of the model's limit, auto-compact activates\n */\nconst AUTO_COMPACT_THRESHOLD_RATIO = 0.92\n\n/**\n * Retrieves the context length for the main model that should execute compression\n * Uses ModelManager to get the current model's context length\n */\nasync function getCompressionModelContextLimit(): Promise<number> {\n try {\n // \uD83D\uDD27 Fix: Use ModelManager instead of legacy config\n const modelManager = getModelManager()\n const modelProfile = modelManager.getModel('main')\n\n if (modelProfile?.contextLength) {\n return modelProfile.contextLength\n }\n\n // Fallback to a reasonable default\n return 200_000\n } catch (error) {\n return 200_000\n }\n}\n\n/**\n * Get the appropriate compression prompt based on current compression mode\n * This is now handled by the compression mode system\n */\n\n/**\n * Calculates context usage thresholds based on the main model's capabilities\n * Uses the main model context length since compression tasks require a capable model\n */\nasync function calculateThresholds(tokenCount: number) {\n const contextLimit = await getCompressionModelContextLimit()\n const autoCompactThreshold = contextLimit * AUTO_COMPACT_THRESHOLD_RATIO\n\n return {\n isAboveAutoCompactThreshold: tokenCount >= autoCompactThreshold,\n percentUsed: Math.round((tokenCount / contextLimit) * 100),\n tokensRemaining: Math.max(0, autoCompactThreshold - tokenCount),\n contextLimit,\n }\n}\n\n/**\n * Determines if auto-compact should trigger based on token usage\n * Uses the main model context limit since compression requires a capable model\n */\nasync function shouldAutoCompact(messages: Message[]): Promise<boolean> {\n if (messages.length < 3) return false\n\n const tokenCount = countTokens(messages)\n const { isAboveAutoCompactThreshold } = await calculateThresholds(tokenCount)\n\n return isAboveAutoCompactThreshold\n}\n\n/**\n * Main entry point for automatic context compression\n *\n * This function is called before each query to check if the conversation\n * has grown too large and needs compression. When triggered, it:\n * - Generates a structured summary of the conversation using the main model\n * - Recovers recently accessed files to maintain development context\n * - Resets conversation state while preserving essential information\n *\n * Uses the main model for compression tasks to ensure high-quality summaries\n *\n * @param messages Current conversation messages\n * @param toolUseContext Execution context with model and tool configuration\n * @returns Updated messages (compressed if needed) and compression status\n */\nexport async function checkAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<{ messages: Message[]; wasCompacted: boolean }> {\n if (!(await shouldAutoCompact(messages))) {\n return { messages, wasCompacted: false }\n }\n\n try {\n // Fire PreCompact hook before compaction\n const hookManager = getHookManager()\n if (hookManager) {\n hookManager.executePreCompact('auto').catch(() => {})\n }\n\n const compactedMessages = await executeAutoCompact(messages, toolUseContext)\n\n return {\n messages: compactedMessages,\n wasCompacted: true,\n }\n } catch (error) {\n // Graceful degradation: if auto-compact fails, continue with original messages\n // This ensures system remains functional even if compression encounters issues\n console.error(\n 'Auto-compact failed, continuing with original messages:',\n error,\n )\n return { messages, wasCompacted: false }\n }\n}\n\n/**\n * Patterns that indicate the user wants something remembered across sessions.\n */\nconst REMEMBER_PATTERNS = [\n /\\bremember\\s+(this|that)\\b/i,\n /\\balways\\s+(use|do|prefer|avoid|skip)\\b/i,\n /\\bnever\\s+(use|do|commit|push|deploy)\\b/i,\n /\\bfrom\\s+now\\s+on\\b/i,\n /\\bin\\s+the\\s+future\\b/i,\n /\\bgoing\\s+forward\\b/i,\n /\\bkeep\\s+in\\s+mind\\b/i,\n /\\bdon'?t\\s+forget\\b/i,\n]\n\n/**\n * Extracts \"remember this\" instructions from user messages and appends\n * them to ~/.minto/auto-memory.md. Only active when autoMemory config is true.\n */\nfunction extractAutoMemory(messages: Message[]): void {\n try {\n const config = getGlobalConfig()\n if (!config.autoMemory) return\n\n const memories: string[] = []\n\n for (const msg of messages) {\n if (msg.type !== 'user') continue\n const content = msg.message.content\n const text =\n typeof content === 'string'\n ? content\n : Array.isArray(content)\n ? content\n .filter((b: any) => b.type === 'text')\n .map((b: any) => b.text)\n .join('\\n')\n : ''\n\n if (!text) continue\n\n const matchesPattern = REMEMBER_PATTERNS.some(p => p.test(text))\n if (matchesPattern) {\n // Extract the relevant line(s) containing the pattern\n const lines = text.split('\\n')\n for (const line of lines) {\n const trimmed = line.trim()\n if (trimmed && REMEMBER_PATTERNS.some(p => p.test(trimmed))) {\n memories.push(trimmed)\n }\n }\n }\n }\n\n if (memories.length === 0) return\n\n const autoMemoryDir = join(homedir(), CONFIG_BASE_DIR)\n const autoMemoryPath = join(autoMemoryDir, 'auto-memory.md')\n\n if (!existsSync(autoMemoryDir)) {\n mkdirSync(autoMemoryDir, { recursive: true })\n }\n\n const timestamp = new Date().toISOString().split('T')[0]\n const entry = `\\n## ${timestamp}\\n${memories.map(m => `- ${m}`).join('\\n')}\\n`\n\n appendFileSync(autoMemoryPath, entry, 'utf-8')\n } catch {\n // Graceful degradation: auto-memory extraction is best-effort\n }\n}\n\n/**\n * Executes the conversation compression process using the main model\n *\n * This function generates a comprehensive summary using the main model\n * which is better suited for complex summarization tasks. It also\n * automatically recovers important files to maintain development context.\n */\nasync function executeAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<Message[]> {\n // Get the compression prompt based on current mode (business or code)\n const compressionMode = getCompressionMode()\n const compressionPrompt = getCompressionPrompt(compressionMode)\n\n const summaryRequest = createUserMessage(compressionPrompt)\n\n const summaryResponse = await queryLLM(\n normalizeMessagesForAPI([...messages, summaryRequest]),\n [\n 'You are a helpful AI assistant tasked with creating comprehensive conversation summaries that preserve all essential context for continuing development work.',\n ],\n 0,\n toolUseContext.options.tools,\n toolUseContext.abortController.signal,\n {\n safeMode: false,\n model: 'main', // \u4F7F\u7528\u6A21\u578B\u6307\u9488\uFF0C\u8BA9queryLLM\u7EDF\u4E00\u89E3\u6790\n prependCLISysprompt: true,\n },\n )\n\n const content = summaryResponse.message.content\n const summary =\n typeof content === 'string'\n ? content\n : content.length > 0 && content[0]?.type === 'text'\n ? content[0].text\n : null\n\n if (!summary) {\n throw new Error(\n 'Failed to generate conversation summary - response did not contain valid text content',\n )\n }\n\n summaryResponse.message.usage = {\n input_tokens: 0,\n output_tokens: summaryResponse.message.usage.output_tokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n }\n\n // Automatic file recovery: preserve recently accessed development files\n // This maintains coding context even after conversation compression\n const recoveredFiles = await selectAndReadFiles()\n\n const compactedMessages = [\n createUserMessage(\n 'Context automatically compressed due to token limit. Essential information preserved.',\n ),\n summaryResponse,\n ]\n\n // Append recovered files to maintain development workflow continuity\n // Files are prioritized by recency and importance, with strict token limits\n if (recoveredFiles.length > 0) {\n for (const file of recoveredFiles) {\n const contentWithLines = addLineNumbers({\n content: file.content,\n startLine: 1,\n })\n const recoveryMessage = createUserMessage(\n `**Recovered File: ${file.path}**\\n\\n\\`\\`\\`\\n${contentWithLines}\\n\\`\\`\\`\\n\\n` +\n `*Automatically recovered (${file.tokens} tokens)${file.truncated ? ' [truncated]' : ''}*`,\n )\n compactedMessages.push(recoveryMessage)\n\n emitReminderEvent('compact:file_reference', { filePath: file.path })\n }\n }\n\n // Extract auto-memory from conversation before discarding messages\n extractAutoMemory(messages)\n\n // State cleanup to ensure fresh context after compression\n // Mirrors the cleanup sequence from manual /compact command\n getMessagesSetter()([])\n getContext.cache.clear?.()\n getCodeStyle.cache.clear?.()\n resetFileFreshnessSession()\n\n return compactedMessages\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/utils/config.js
CHANGED
|
@@ -8,6 +8,7 @@ import { randomBytes } from "crypto";
|
|
|
8
8
|
import { safeParseJSON } from "./json.js";
|
|
9
9
|
import { ConfigParseError } from "./errors.js";
|
|
10
10
|
import { debug as debugLogger } from "./debugLogger.js";
|
|
11
|
+
import { safeValidateGlobalConfig } from "./configSchema.js";
|
|
11
12
|
const DEFAULT_PROJECT_CONFIG = {
|
|
12
13
|
allowedTools: [],
|
|
13
14
|
context: {},
|
|
@@ -70,8 +71,8 @@ const DEFAULT_GLOBAL_CONFIG = {
|
|
|
70
71
|
// Default to English
|
|
71
72
|
safeMode: false,
|
|
72
73
|
// Deprecated: use safetyMode instead
|
|
73
|
-
safetyMode: "
|
|
74
|
-
// Default to
|
|
74
|
+
safetyMode: "smart"
|
|
75
|
+
// Default to smart mode — safe tools auto-allowed, dangerous tools need confirmation
|
|
75
76
|
};
|
|
76
77
|
const GLOBAL_CONFIG_KEYS = [
|
|
77
78
|
"autoUpdaterStatus",
|
|
@@ -87,7 +88,10 @@ const GLOBAL_CONFIG_KEYS = [
|
|
|
87
88
|
"maxTokens",
|
|
88
89
|
"compressionMode",
|
|
89
90
|
"language",
|
|
90
|
-
"safetyMode"
|
|
91
|
+
"safetyMode",
|
|
92
|
+
"enableMemoryTools",
|
|
93
|
+
"outputStyle",
|
|
94
|
+
"autoMemory"
|
|
91
95
|
];
|
|
92
96
|
function isGlobalConfigKey(key) {
|
|
93
97
|
return GLOBAL_CONFIG_KEYS.includes(key);
|
|
@@ -127,6 +131,7 @@ function isProjectConfigKey(key) {
|
|
|
127
131
|
function saveGlobalConfig(config) {
|
|
128
132
|
if (process.env.NODE_ENV === "test") {
|
|
129
133
|
for (const key in config) {
|
|
134
|
+
;
|
|
130
135
|
TEST_GLOBAL_CONFIG_FOR_TESTING[key] = config[key];
|
|
131
136
|
}
|
|
132
137
|
return;
|
|
@@ -287,6 +292,15 @@ function getConfig(file, defaultConfig, throwOnInvalid) {
|
|
|
287
292
|
file,
|
|
288
293
|
parsedKeys: Object.keys(parsedConfig).join(", ")
|
|
289
294
|
});
|
|
295
|
+
if (file === GLOBAL_CONFIG_FILE) {
|
|
296
|
+
const validation = safeValidateGlobalConfig(parsedConfig);
|
|
297
|
+
if (!validation.success && validation.errors) {
|
|
298
|
+
debugLogger.warn("CONFIG_VALIDATION", {
|
|
299
|
+
file,
|
|
300
|
+
issues: validation.errors.issues.map((i) => `${i.path.join(".")}: ${i.message}`).join("; ")
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
}
|
|
290
304
|
const finalConfig = {
|
|
291
305
|
...cloneDeep(defaultConfig),
|
|
292
306
|
...parsedConfig
|
|
@@ -619,7 +633,8 @@ async function resolveApiKey(profile) {
|
|
|
619
633
|
return getApiKey(modelName);
|
|
620
634
|
} catch (error) {
|
|
621
635
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
622
|
-
|
|
636
|
+
debugLogger.warn(
|
|
637
|
+
"CREDENTIAL_RESOLVE",
|
|
623
638
|
`Failed to resolve encrypted API key for ${modelName}: ${errorMsg}`
|
|
624
639
|
);
|
|
625
640
|
return null;
|
|
@@ -627,130 +642,13 @@ async function resolveApiKey(profile) {
|
|
|
627
642
|
}
|
|
628
643
|
return profile.apiKey;
|
|
629
644
|
}
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
const now = Date.now();
|
|
638
|
-
const repairedProfile = { ...profile };
|
|
639
|
-
let wasRepaired = false;
|
|
640
|
-
if (isGPT5 !== profile.isGPT5) {
|
|
641
|
-
repairedProfile.isGPT5 = isGPT5;
|
|
642
|
-
wasRepaired = true;
|
|
643
|
-
}
|
|
644
|
-
if (isGPT5) {
|
|
645
|
-
const validReasoningEfforts = ["minimal", "low", "medium", "high"];
|
|
646
|
-
if (!profile.reasoningEffort || !validReasoningEfforts.includes(profile.reasoningEffort)) {
|
|
647
|
-
repairedProfile.reasoningEffort = "medium";
|
|
648
|
-
wasRepaired = true;
|
|
649
|
-
console.log(
|
|
650
|
-
`\u{1F527} GPT-5 Config: Set reasoning effort to 'medium' for ${profile.modelName}`
|
|
651
|
-
);
|
|
652
|
-
}
|
|
653
|
-
if (profile.contextLength < 128e3) {
|
|
654
|
-
repairedProfile.contextLength = 128e3;
|
|
655
|
-
wasRepaired = true;
|
|
656
|
-
console.log(
|
|
657
|
-
`\u{1F527} GPT-5 Config: Updated context length to 128k for ${profile.modelName}`
|
|
658
|
-
);
|
|
659
|
-
}
|
|
660
|
-
if (profile.maxTokens < 4e3) {
|
|
661
|
-
repairedProfile.maxTokens = 8192;
|
|
662
|
-
wasRepaired = true;
|
|
663
|
-
console.log(
|
|
664
|
-
`\u{1F527} GPT-5 Config: Updated max tokens to 8192 for ${profile.modelName}`
|
|
665
|
-
);
|
|
666
|
-
}
|
|
667
|
-
if (profile.provider !== "openai" && profile.provider !== "custom-openai" && profile.provider !== "azure") {
|
|
668
|
-
console.warn(
|
|
669
|
-
`\u26A0\uFE0F GPT-5 Config: Unexpected provider '${profile.provider}' for GPT-5 model ${profile.modelName}. Consider using 'openai' or 'custom-openai'.`
|
|
670
|
-
);
|
|
671
|
-
}
|
|
672
|
-
if (profile.modelName.includes("gpt-5") && !profile.baseURL) {
|
|
673
|
-
repairedProfile.baseURL = "https://api.openai.com/v1";
|
|
674
|
-
wasRepaired = true;
|
|
675
|
-
console.log(
|
|
676
|
-
`\u{1F527} GPT-5 Config: Set default base URL for ${profile.modelName}`
|
|
677
|
-
);
|
|
678
|
-
}
|
|
679
|
-
}
|
|
680
|
-
repairedProfile.validationStatus = wasRepaired ? "auto_repaired" : "valid";
|
|
681
|
-
repairedProfile.lastValidation = now;
|
|
682
|
-
if (wasRepaired) {
|
|
683
|
-
console.log(
|
|
684
|
-
`\u2705 GPT-5 Config: Auto-repaired configuration for ${profile.modelName}`
|
|
685
|
-
);
|
|
686
|
-
}
|
|
687
|
-
return repairedProfile;
|
|
688
|
-
}
|
|
689
|
-
function validateAndRepairAllGPT5Profiles() {
|
|
690
|
-
const config = getGlobalConfig();
|
|
691
|
-
if (!config.modelProfiles) {
|
|
692
|
-
return { repaired: 0, total: 0 };
|
|
693
|
-
}
|
|
694
|
-
let repairCount = 0;
|
|
695
|
-
const repairedProfiles = config.modelProfiles.map((profile) => {
|
|
696
|
-
const repairedProfile = validateAndRepairGPT5Profile(profile);
|
|
697
|
-
if (repairedProfile.validationStatus === "auto_repaired") {
|
|
698
|
-
repairCount++;
|
|
699
|
-
}
|
|
700
|
-
return repairedProfile;
|
|
701
|
-
});
|
|
702
|
-
if (repairCount > 0) {
|
|
703
|
-
const updatedConfig = {
|
|
704
|
-
...config,
|
|
705
|
-
modelProfiles: repairedProfiles
|
|
706
|
-
};
|
|
707
|
-
saveGlobalConfig(updatedConfig);
|
|
708
|
-
console.log(`\u{1F527} GPT-5 Config: Auto-repaired ${repairCount} model profiles`);
|
|
709
|
-
}
|
|
710
|
-
return { repaired: repairCount, total: config.modelProfiles.length };
|
|
711
|
-
}
|
|
712
|
-
function getGPT5ConfigRecommendations(modelName) {
|
|
713
|
-
if (!isGPT5ModelName(modelName)) {
|
|
714
|
-
return {};
|
|
715
|
-
}
|
|
716
|
-
const recommendations = {
|
|
717
|
-
contextLength: 128e3,
|
|
718
|
-
// GPT-5 standard context length
|
|
719
|
-
maxTokens: 8192,
|
|
720
|
-
// Good default for coding tasks
|
|
721
|
-
reasoningEffort: "medium",
|
|
722
|
-
// Balanced for most coding tasks
|
|
723
|
-
isGPT5: true
|
|
724
|
-
};
|
|
725
|
-
if (modelName.includes("gpt-5-mini")) {
|
|
726
|
-
recommendations.maxTokens = 4096;
|
|
727
|
-
recommendations.reasoningEffort = "low";
|
|
728
|
-
} else if (modelName.includes("gpt-5-nano")) {
|
|
729
|
-
recommendations.maxTokens = 2048;
|
|
730
|
-
recommendations.reasoningEffort = "minimal";
|
|
731
|
-
}
|
|
732
|
-
return recommendations;
|
|
733
|
-
}
|
|
734
|
-
function createGPT5ModelProfile(name, modelName, apiKey, baseURL, provider = "openai") {
|
|
735
|
-
const recommendations = getGPT5ConfigRecommendations(modelName);
|
|
736
|
-
const profile = {
|
|
737
|
-
name,
|
|
738
|
-
provider,
|
|
739
|
-
modelName,
|
|
740
|
-
baseURL: baseURL || "https://api.openai.com/v1",
|
|
741
|
-
apiKey,
|
|
742
|
-
maxTokens: recommendations.maxTokens || 8192,
|
|
743
|
-
contextLength: recommendations.contextLength || 128e3,
|
|
744
|
-
reasoningEffort: recommendations.reasoningEffort || "medium",
|
|
745
|
-
isActive: true,
|
|
746
|
-
createdAt: Date.now(),
|
|
747
|
-
isGPT5: true,
|
|
748
|
-
validationStatus: "valid",
|
|
749
|
-
lastValidation: Date.now()
|
|
750
|
-
};
|
|
751
|
-
console.log(`\u2705 Created GPT-5 model profile: ${name} (${modelName})`);
|
|
752
|
-
return profile;
|
|
753
|
-
}
|
|
645
|
+
import {
|
|
646
|
+
isGPT5ModelName,
|
|
647
|
+
validateAndRepairGPT5Profile,
|
|
648
|
+
validateAndRepairAllGPT5Profiles,
|
|
649
|
+
getGPT5ConfigRecommendations,
|
|
650
|
+
createGPT5ModelProfile
|
|
651
|
+
} from "./gpt5.js";
|
|
754
652
|
export {
|
|
755
653
|
DEFAULT_GLOBAL_CONFIG,
|
|
756
654
|
GLOBAL_CONFIG_KEYS,
|
package/dist/utils/config.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/config.ts"],
|
|
4
|
-
"sourcesContent": ["import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs'\nimport { resolve, join, dirname } from 'path'\nimport { cloneDeep, memoize, pick } from 'lodash-es'\nimport { homedir } from 'os'\nimport { GLOBAL_CONFIG_FILE } from './env'\nimport { getCwd } from './state'\nimport { randomBytes } from 'crypto'\nimport { safeParseJSON } from './json'\nimport { ConfigParseError } from './errors'\nimport type { ThemeNames } from './theme'\nimport { debug as debugLogger } from './debugLogger'\nimport { getSessionState, setSessionState } from './sessionState'\nimport type { CompressionMode } from '@constants/compressionPrompts'\n\nexport type McpStdioServerConfig = {\n type?: 'stdio' // Optional for backwards compatibility\n command: string\n args: string[]\n env?: Record<string, string>\n enabled?: boolean\n}\n\nexport type McpSSEServerConfig = {\n type: 'sse'\n url: string\n enabled?: boolean\n}\n\nexport type McpServerConfig = McpStdioServerConfig | McpSSEServerConfig\n\n/**\n * Sandbox configuration for project-level security settings\n */\nexport type SandboxConfigData = {\n /** Whether sandboxing is enabled */\n enabled: boolean\n /** Filesystem access policy */\n filesystem?: {\n writeAllowed?: string[]\n readAllowed?: string[]\n denied?: string[]\n }\n /** Network access policy */\n network?: {\n allowedDomains?: string[]\n promptForNewDomains?: boolean\n blockAll?: boolean\n }\n /** Process isolation policy */\n process?: {\n excludedCommands?: string[]\n maxExecutionTime?: number\n }\n}\n\nexport type ProjectConfig = {\n allowedTools: string[]\n context: Record<string, string>\n contextFiles?: string[]\n history: string[]\n dontCrawlDirectory?: boolean\n enableArchitectTool?: boolean\n mcpContextUris: string[]\n mcpServers?: Record<string, McpServerConfig>\n approvedMcprcServers?: string[]\n rejectedMcprcServers?: string[]\n lastAPIDuration?: number\n lastCost?: number\n lastDuration?: number\n lastSessionId?: string\n exampleFiles?: string[]\n exampleFilesGeneratedAt?: number\n hasTrustDialogAccepted?: boolean\n hasCompletedProjectOnboarding?: boolean\n /** Sandbox configuration for command execution isolation */\n sandbox?: SandboxConfigData\n}\n\nconst DEFAULT_PROJECT_CONFIG: ProjectConfig = {\n allowedTools: [],\n context: {},\n history: [],\n dontCrawlDirectory: false,\n enableArchitectTool: false,\n mcpContextUris: [],\n mcpServers: {},\n approvedMcprcServers: [],\n rejectedMcprcServers: [],\n hasTrustDialogAccepted: false,\n}\n\nfunction defaultConfigForProject(projectPath: string): ProjectConfig {\n const config = { ...DEFAULT_PROJECT_CONFIG }\n if (projectPath === homedir()) {\n config.dontCrawlDirectory = true\n }\n return config\n}\n\nexport type AutoUpdaterStatus =\n | 'disabled'\n | 'enabled'\n | 'no_permissions'\n | 'not_configured'\n\nexport function isAutoUpdaterStatus(value: string): value is AutoUpdaterStatus {\n return ['disabled', 'enabled', 'no_permissions', 'not_configured'].includes(\n value as AutoUpdaterStatus,\n )\n}\n\nexport type NotificationChannel =\n | 'iterm2'\n | 'terminal_bell'\n | 'iterm2_with_bell'\n | 'notifications_disabled'\n\n/**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\nexport type DisplayMode = 'minimal' | 'compact' | 'detailed'\n\n/**\n * Supported UI languages\n */\nexport type UILanguage = 'en' | 'zh-CN'\n\n/**\n * Safety mode for tool execution\n * - 'yolo': All tools allowed without confirmation (default for non-technical users)\n * - 'smart': Safe/monitored tools auto-allowed, dangerous tools need confirmation\n * - 'strict': Only safe tools auto-allowed, all others need confirmation\n * - 'free': Project directory operations auto-allowed, outside requires confirmation\n */\nexport type SafetyMode = 'yolo' | 'smart' | 'strict' | 'free'\n\n/**\n * Get verbose mode label (uses i18n)\n * Import dynamically to avoid circular dependency\n */\nexport function getVerboseLabel(verbose: boolean): string {\n // Dynamic import to avoid circular dependency at module load time\n try {\n const { t } = require('../i18n')\n return verbose ? t('ui.verbose.on') : t('ui.verbose.off')\n } catch {\n // Fallback if i18n not loaded yet\n return verbose ? 'Verbose: On' : 'Verbose: Off'\n }\n}\n\nexport type ProviderType =\n | 'anthropic'\n | 'openai'\n | 'mistral'\n | 'deepseek'\n | 'kimi'\n | 'qwen'\n | 'glm'\n | 'minimax'\n | 'baidu-qianfan'\n | 'siliconflow'\n | 'bigdream'\n | 'opendev'\n | 'xai'\n | 'groq'\n | 'gemini'\n | 'ollama'\n | 'azure'\n | 'custom'\n | 'custom-openai'\n\n// New model system types\nexport type ModelProfile = {\n name: string // User-friendly name\n provider: ProviderType // Provider type\n modelName: string // Primary key - actual model identifier\n baseURL?: string // Custom endpoint\n apiKey: string\n maxTokens: number // Output token limit (for GPT-5, this maps to max_completion_tokens)\n contextLength: number // Context window size\n reasoningEffort?: 'low' | 'medium' | 'high' | 'minimal' | 'medium'\n isActive: boolean // Whether profile is enabled\n createdAt: number // Creation timestamp\n lastUsed?: number // Last usage timestamp\n // \uD83D\uDD25 GPT-5 specific metadata\n isGPT5?: boolean // Auto-detected GPT-5 model flag\n validationStatus?: 'valid' | 'needs_repair' | 'auto_repaired' // Configuration status\n lastValidation?: number // Last validation timestamp\n}\n\n// Legacy type for config migration - includes deprecated 'id' field\ntype LegacyModelProfile = ModelProfile & {\n id?: string\n}\n\n// Legacy global config fields for migration\ntype LegacyGlobalConfigFields = {\n defaultModelId?: string\n defaultModelName?: string\n currentSelectedModelId?: string\n mainAgentModelId?: string\n taskToolModelId?: string\n}\n\nexport type ModelPointerType =\n | 'main'\n | 'task'\n | 'reasoning'\n | 'quick'\n | 'compact'\n\nexport type ModelPointers = {\n main: string // Main dialog model ID\n task: string // Task tool model ID\n reasoning: string // Reasoning model ID\n quick: string // Quick model ID\n compact: string // Compact/summary model ID (for context compression)\n}\n\nexport type AccountInfo = {\n accountUuid: string\n emailAddress: string\n organizationUuid?: string\n}\n\nexport type GlobalConfig = {\n projects?: Record<string, ProjectConfig>\n numStartups: number\n autoUpdaterStatus?: AutoUpdaterStatus\n userID?: string\n theme: ThemeNames\n hasCompletedOnboarding?: boolean\n // Tracks the last version that reset onboarding, used with MIN_VERSION_REQUIRING_ONBOARDING_RESET\n lastOnboardingVersion?: string\n // Tracks the last version for which release notes were seen, used for managing release notes\n lastReleaseNotesSeen?: string\n mcpServers?: Record<string, McpServerConfig>\n preferredNotifChannel: NotificationChannel\n /**\n * Verbose mode: shows full parameters and complete outputs when enabled\n * - false: Concise output (default)\n * - true: Detailed/verbose output\n */\n verbose: boolean\n /**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\n displayMode?: DisplayMode\n customApiKeyResponses?: {\n approved?: string[]\n rejected?: string[]\n }\n primaryProvider?: ProviderType\n maxTokens?: number\n hasAcknowledgedCostThreshold?: boolean\n oauthAccount?: AccountInfo\n iterm2KeyBindingInstalled?: boolean // Legacy - keeping for backward compatibility\n shiftEnterKeyBindingInstalled?: boolean\n proxy?: string\n stream?: boolean\n\n // New model system\n modelProfiles?: ModelProfile[] // Model configuration list\n modelPointers?: ModelPointers // Model pointer system\n defaultModelName?: string // Default model\n // Update notifications\n lastDismissedUpdateVersion?: string\n // Compression mode\n compressionMode?: CompressionMode // Compression algorithm mode ('business' or 'code')\n // Thinking mode (Phase 4.2)\n thinking?: boolean // Whether thinking/extended reasoning mode is enabled\n // UI Language\n language?: UILanguage // UI language ('en' or 'zh-CN')\n /**\n * @deprecated Use safetyMode instead. Kept for backward compatibility.\n * Safe mode: when enabled, requires user confirmation for all tool executions\n */\n safeMode?: boolean\n /**\n * Safety mode for tool execution (4-tier system):\n * - 'yolo': All tools allowed without confirmation (default for non-technical users)\n * - 'smart': Safe/monitored tools auto-allowed, dangerous tools need confirmation\n * - 'strict': Only safe tools auto-allowed, all others need confirmation\n * - 'free': Project directory operations auto-allowed, outside requires confirmation\n */\n safetyMode?: SafetyMode\n // Claude Code plugin auto-sync\n autoSyncClaudeCode?: boolean\n}\n\nexport const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n numStartups: 0,\n autoUpdaterStatus: 'not_configured',\n theme: 'dark' as ThemeNames,\n preferredNotifChannel: 'iterm2',\n verbose: false,\n primaryProvider: 'anthropic' as ProviderType,\n customApiKeyResponses: {\n approved: [],\n rejected: [],\n },\n stream: true,\n\n // New model system defaults\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n lastDismissedUpdateVersion: undefined,\n compressionMode: 'business', // Default to business consulting compression\n thinking: false, // Default to thinking mode off (Phase 4.2)\n language: 'en', // Default to English\n safeMode: false, // Deprecated: use safetyMode instead\n safetyMode: 'yolo', // Default to YOLO mode for non-technical users (zero interruption)\n}\n\nexport const GLOBAL_CONFIG_KEYS = [\n 'autoUpdaterStatus',\n 'theme',\n 'hasCompletedOnboarding',\n 'lastOnboardingVersion',\n 'lastReleaseNotesSeen',\n 'verbose',\n 'customApiKeyResponses',\n 'primaryProvider',\n 'preferredNotifChannel',\n 'shiftEnterKeyBindingInstalled',\n 'maxTokens',\n 'compressionMode',\n 'language',\n 'safetyMode',\n] as const\n\nexport type GlobalConfigKey = (typeof GLOBAL_CONFIG_KEYS)[number]\n\nexport function isGlobalConfigKey(key: string): key is GlobalConfigKey {\n return GLOBAL_CONFIG_KEYS.includes(key as GlobalConfigKey)\n}\n\nexport const PROJECT_CONFIG_KEYS = [\n 'dontCrawlDirectory',\n 'enableArchitectTool',\n 'hasTrustDialogAccepted',\n 'hasCompletedProjectOnboarding',\n] as const\n\nexport type ProjectConfigKey = (typeof PROJECT_CONFIG_KEYS)[number]\n\nexport function checkHasTrustDialogAccepted(): boolean {\n let currentPath = getCwd()\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n while (true) {\n const projectConfig = config.projects?.[currentPath]\n if (projectConfig?.hasTrustDialogAccepted) {\n return true\n }\n const parentPath = resolve(currentPath, '..')\n // Stop if we've reached the root (when parent is same as current)\n if (parentPath === currentPath) {\n break\n }\n currentPath = parentPath\n }\n\n return false\n}\n\n// We have to put this test code here because Jest doesn't support mocking ES modules :O\nconst TEST_GLOBAL_CONFIG_FOR_TESTING: GlobalConfig = {\n ...DEFAULT_GLOBAL_CONFIG,\n autoUpdaterStatus: 'disabled',\n}\nconst TEST_PROJECT_CONFIG_FOR_TESTING: ProjectConfig = {\n ...DEFAULT_PROJECT_CONFIG,\n}\n\nexport function isProjectConfigKey(key: string): key is ProjectConfigKey {\n return PROJECT_CONFIG_KEYS.includes(key as ProjectConfigKey)\n}\n\nexport function saveGlobalConfig(config: GlobalConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in config) {\n TEST_GLOBAL_CONFIG_FOR_TESTING[key] = config[key]\n }\n return\n }\n\n // \u76F4\u63A5\u4FDD\u5B58\u914D\u7F6E\uFF08\u65E0\u9700\u6E05\u9664\u7F13\u5B58\uFF0C\u56E0\u4E3A\u5DF2\u79FB\u9664\u7F13\u5B58\uFF09\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG).projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\n/**\n * Migrate legacy displayMode to verbose boolean\n */\nfunction migrateDisplayModeToVerbose(config: GlobalConfig): GlobalConfig {\n // If verbose is already set, no migration needed\n if (config.verbose !== undefined) {\n return config\n }\n\n // Check for legacy displayMode field\n const legacyConfig = config as GlobalConfig & { displayMode?: DisplayMode }\n if (legacyConfig.displayMode !== undefined) {\n const migratedConfig: GlobalConfig = {\n ...config,\n verbose: legacyConfig.displayMode === 'detailed',\n }\n // Remove legacy field\n delete (migratedConfig as any).displayMode\n return migratedConfig\n }\n\n // Default to false if no verbose or displayMode\n return {\n ...config,\n verbose: false,\n }\n}\n\n// \u4E34\u65F6\u79FB\u9664\u7F13\u5B58\uFF0C\u786E\u4FDD\u603B\u662F\u83B7\u53D6\u6700\u65B0\u914D\u7F6E\nexport function getGlobalConfig(): GlobalConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_GLOBAL_CONFIG_FOR_TESTING\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n const migratedConfig = migrateModelProfilesRemoveId(config)\n const displayMigratedConfig = migrateDisplayModeToVerbose(migratedConfig)\n\n // Apply model profile deduplication\n if (\n displayMigratedConfig.modelProfiles &&\n displayMigratedConfig.modelProfiles.length > 0\n ) {\n const originalCount = displayMigratedConfig.modelProfiles.length\n const deduplicatedProfiles = deduplicateModelProfiles(\n displayMigratedConfig.modelProfiles,\n )\n const deduplicatedCount = deduplicatedProfiles.length\n\n // If duplicates were found and removed, auto-save the deduplicated config\n if (deduplicatedCount < originalCount) {\n debugLogger.state('CONFIG_DEDUPLICATE_PROFILES', {\n originalCount: String(originalCount),\n deduplicatedCount: String(deduplicatedCount),\n removedCount: String(originalCount - deduplicatedCount),\n })\n const configToSave = {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n // Save the deduplicated config (avoid recursion by using saveConfig directly)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...configToSave,\n projects: config.projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n return configToSave\n }\n\n return {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n }\n\n return displayMigratedConfig\n}\n\nexport function getAnthropicApiKey(): null | string {\n return process.env.ANTHROPIC_API_KEY || null\n}\n\nexport function normalizeApiKeyForConfig(apiKey: string): string {\n return apiKey?.slice(-20) ?? ''\n}\n\nexport function getCustomApiKeyStatus(\n truncatedApiKey: string,\n): 'approved' | 'rejected' | 'new' {\n const config = getGlobalConfig()\n if (config.customApiKeyResponses?.approved?.includes(truncatedApiKey)) {\n return 'approved'\n }\n if (config.customApiKeyResponses?.rejected?.includes(truncatedApiKey)) {\n return 'rejected'\n }\n return 'new'\n}\n\n/**\n * Atomically write content to a file using temp file + rename pattern.\n * This prevents data corruption if writes are interrupted or multiple processes\n * attempt to write concurrently.\n *\n * @param filePath - The target file path to write to\n * @param content - The content to write\n * @throws {Error} If write or rename operation fails\n */\nfunction atomicWriteFileSync(filePath: string, content: string): void {\n const dir = dirname(filePath)\n const tempPath = join(\n dir,\n `.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`,\n )\n\n try {\n // Write to temporary file\n writeFileSync(tempPath, content, 'utf-8')\n // Atomically rename temp to target (atomic on most filesystems)\n renameSync(tempPath, filePath)\n } catch (error) {\n // Clean up temporary file on failure\n try {\n rmSync(tempPath, { force: true })\n } catch {\n // Ignore cleanup errors\n }\n throw error\n }\n}\n\nfunction saveConfig<A extends object>(\n file: string,\n config: A,\n defaultConfig: A,\n): void {\n // Filter out any values that match the defaults\n const filteredConfig = Object.fromEntries(\n Object.entries(config).filter(\n ([key, value]) =>\n JSON.stringify(value) !== JSON.stringify(defaultConfig[key as keyof A]),\n ),\n )\n try {\n atomicWriteFileSync(file, JSON.stringify(filteredConfig, null, 2))\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (\n err?.code === 'EACCES' ||\n err?.code === 'EPERM' ||\n err?.code === 'EROFS'\n ) {\n debugLogger.state('CONFIG_SAVE_SKIPPED', {\n file,\n reason: String(err.code),\n })\n return\n }\n throw error\n }\n}\n\n// Flag to track if config reading is allowed\nlet configReadingAllowed = false\n\nexport function enableConfigs(): void {\n // Any reads to configuration before this flag is set show an console warning\n // to prevent us from adding config reading during module initialization\n configReadingAllowed = true\n // We only check the global config because currently all the configs share a file\n getConfig(\n GLOBAL_CONFIG_FILE,\n DEFAULT_GLOBAL_CONFIG,\n true /* throw on invalid */,\n )\n}\n\nfunction getConfig<A>(\n file: string,\n defaultConfig: A,\n throwOnInvalid?: boolean,\n): A {\n // \u7B80\u5316\u914D\u7F6E\u8BBF\u95EE\u903B\u8F91\uFF0C\u79FB\u9664\u590D\u6742\u7684\u65F6\u5E8F\u68C0\u67E5\n\n debugLogger.state('CONFIG_LOAD_START', {\n file,\n fileExists: String(existsSync(file)),\n throwOnInvalid: String(!!throwOnInvalid),\n })\n\n if (!existsSync(file)) {\n debugLogger.state('CONFIG_LOAD_DEFAULT', {\n file,\n reason: 'file_not_exists',\n defaultConfigKeys: Object.keys(defaultConfig as object).join(', '),\n })\n return cloneDeep(defaultConfig)\n }\n\n try {\n const fileContent = readFileSync(file, 'utf-8')\n debugLogger.state('CONFIG_FILE_READ', {\n file,\n contentLength: String(fileContent.length),\n contentPreview:\n fileContent.substring(0, 100) + (fileContent.length > 100 ? '...' : ''),\n })\n\n try {\n const parsedConfig = JSON.parse(fileContent)\n debugLogger.state('CONFIG_JSON_PARSED', {\n file,\n parsedKeys: Object.keys(parsedConfig).join(', '),\n })\n\n // Handle backward compatibility - remove logic for deleted fields\n const finalConfig = {\n ...cloneDeep(defaultConfig),\n ...parsedConfig,\n }\n\n debugLogger.state('CONFIG_LOAD_SUCCESS', {\n file,\n finalConfigKeys: Object.keys(finalConfig as object).join(', '),\n })\n\n return finalConfig\n } catch (error) {\n // Throw a ConfigParseError with the file path and default config\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n debugLogger.error('CONFIG_JSON_PARSE_ERROR', {\n file,\n errorMessage,\n errorType:\n error instanceof Error ? error.constructor.name : typeof error,\n contentLength: String(fileContent.length),\n })\n\n throw new ConfigParseError(errorMessage, file, defaultConfig)\n }\n } catch (error: unknown) {\n // Re-throw ConfigParseError if throwOnInvalid is true\n if (error instanceof ConfigParseError && throwOnInvalid) {\n debugLogger.error('CONFIG_PARSE_ERROR_RETHROWN', {\n file,\n throwOnInvalid: String(throwOnInvalid),\n errorMessage: error.message,\n })\n throw error\n }\n\n debugLogger.warn('CONFIG_FALLBACK_TO_DEFAULT', {\n file,\n errorType: error instanceof Error ? error.constructor.name : typeof error,\n errorMessage: error instanceof Error ? error.message : String(error),\n action: 'using_default_config',\n })\n\n return cloneDeep(defaultConfig)\n }\n}\n\nexport function getCurrentProjectConfig(): ProjectConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_PROJECT_CONFIG_FOR_TESTING\n }\n\n const absolutePath = resolve(getCwd())\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n if (!config.projects) {\n return defaultConfigForProject(absolutePath)\n }\n\n const projectConfig =\n config.projects[absolutePath] ?? defaultConfigForProject(absolutePath)\n // Not sure how this became a string\n // TODO: Fix upstream\n if (typeof projectConfig.allowedTools === 'string') {\n projectConfig.allowedTools =\n (safeParseJSON(projectConfig.allowedTools) as string[]) ?? []\n }\n return projectConfig\n}\n\nexport function saveCurrentProjectConfig(projectConfig: ProjectConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in projectConfig) {\n TEST_PROJECT_CONFIG_FOR_TESTING[key] = projectConfig[key]\n }\n return\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: {\n ...config.projects,\n [resolve(getCwd())]: projectConfig,\n },\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\nexport async function isAutoUpdaterDisabled(): Promise<boolean> {\n return getGlobalConfig().autoUpdaterStatus === 'disabled'\n}\n\nexport const TEST_MCPRC_CONFIG_FOR_TESTING: Record<string, McpServerConfig> = {}\n\nexport function clearMcprcConfigForTesting(): void {\n if (process.env.NODE_ENV === 'test') {\n Object.keys(TEST_MCPRC_CONFIG_FOR_TESTING).forEach(key => {\n delete TEST_MCPRC_CONFIG_FOR_TESTING[key]\n })\n }\n}\n\nexport function addMcprcServerForTesting(\n name: string,\n server: McpServerConfig,\n): void {\n if (process.env.NODE_ENV === 'test') {\n TEST_MCPRC_CONFIG_FOR_TESTING[name] = server\n }\n}\n\nexport function removeMcprcServerForTesting(name: string): void {\n if (process.env.NODE_ENV === 'test') {\n if (!TEST_MCPRC_CONFIG_FOR_TESTING[name]) {\n throw new Error(`No MCP server found with name: ${name} in .mcprc`)\n }\n delete TEST_MCPRC_CONFIG_FOR_TESTING[name]\n }\n}\n\nexport const getMcprcConfig = memoize(\n (): Record<string, McpServerConfig> => {\n if (process.env.NODE_ENV === 'test') {\n return TEST_MCPRC_CONFIG_FOR_TESTING\n }\n\n const mcprcPath = join(getCwd(), '.mcprc')\n if (!existsSync(mcprcPath)) {\n return {}\n }\n\n try {\n const mcprcContent = readFileSync(mcprcPath, 'utf-8')\n const config = safeParseJSON(mcprcContent)\n if (config && typeof config === 'object') {\n // Logging removed\n return config as Record<string, McpServerConfig>\n }\n } catch {\n // Ignore errors reading/parsing .mcprc (they're logged in safeParseJSON)\n }\n return {}\n },\n // This function returns the same value as long as the cwd and mcprc file content remain the same\n () => {\n const cwd = getCwd()\n const mcprcPath = join(cwd, '.mcprc')\n if (existsSync(mcprcPath)) {\n try {\n const stat = readFileSync(mcprcPath, 'utf-8')\n return `${cwd}:${stat}`\n } catch {\n return cwd\n }\n }\n return cwd\n },\n)\n\nexport function getOrCreateUserID(): string {\n const config = getGlobalConfig()\n if (config.userID) {\n return config.userID\n }\n\n const userID = randomBytes(32).toString('hex')\n saveGlobalConfig({ ...config, userID })\n return userID\n}\n\nexport function getConfigForCLI(key: string, global: boolean): unknown {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getGlobalConfig()[key]\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${PROJECT_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getCurrentProjectConfig()[key]\n }\n}\n\nexport function setConfigForCLI(\n key: string,\n value: unknown,\n global: boolean,\n): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n\n if (key === 'autoUpdaterStatus' && !isAutoUpdaterStatus(value as string)) {\n console.error(\n `Error: Invalid value for autoUpdaterStatus. Must be one of: disabled, enabled, no_permissions, not_configured`,\n )\n process.exit(1)\n }\n\n const currentConfig = getGlobalConfig()\n saveGlobalConfig({\n ...currentConfig,\n [key]: value,\n })\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n saveCurrentProjectConfig({\n ...currentConfig,\n [key]: value,\n })\n }\n // Wait for the output to be flushed, to avoid clearing the screen.\n setTimeout(() => {\n // Without this we hang indefinitely.\n process.exit(0)\n }, 100)\n}\n\nexport function deleteConfigForCLI(key: string, global: boolean): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n const currentConfig = getGlobalConfig()\n delete currentConfig[key]\n saveGlobalConfig(currentConfig)\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n delete currentConfig[key]\n saveCurrentProjectConfig(currentConfig)\n }\n}\n\nexport function listConfigForCLI(global: true): GlobalConfig\nexport function listConfigForCLI(global: false): ProjectConfig\nexport function listConfigForCLI(global: boolean): object {\n if (global) {\n const currentConfig = pick(getGlobalConfig(), GLOBAL_CONFIG_KEYS)\n return currentConfig\n } else {\n return pick(getCurrentProjectConfig(), PROJECT_CONFIG_KEYS)\n }\n}\n\nexport function getOpenAIApiKey(): string | undefined {\n return process.env.OPENAI_API_KEY\n}\n\n// Configuration migration utility functions\nfunction migrateModelProfilesRemoveId(config: GlobalConfig): GlobalConfig {\n if (!config.modelProfiles) return config\n\n // Cast to legacy type for migration - config may have old fields\n const legacyConfig = config as GlobalConfig & LegacyGlobalConfigFields\n\n // 1. Remove id field from ModelProfile objects and build ID to modelName mapping\n const idToModelNameMap = new Map<string, string>()\n const migratedProfiles = config.modelProfiles.map(profile => {\n // Cast to legacy type that includes optional id field\n const legacyProfile = profile as LegacyModelProfile\n // Build mapping before removing id field\n if (legacyProfile.id && profile.modelName) {\n idToModelNameMap.set(legacyProfile.id, profile.modelName)\n }\n\n // Remove id field, keep everything else\n const { id, ...profileWithoutId } = legacyProfile\n return profileWithoutId as ModelProfile\n })\n\n // 2. Migrate ModelPointers from IDs to modelNames\n const migratedPointers: ModelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }\n\n if (config.modelPointers) {\n Object.entries(config.modelPointers).forEach(([pointer, value]) => {\n if (value) {\n // If value looks like an old ID (model_xxx), map it to modelName\n const modelName = idToModelNameMap.get(value) || value\n migratedPointers[pointer as ModelPointerType] = modelName\n }\n })\n }\n\n // 3. Migrate legacy config fields\n let defaultModelName: string | undefined\n if (legacyConfig.defaultModelId) {\n defaultModelName =\n idToModelNameMap.get(legacyConfig.defaultModelId) ||\n legacyConfig.defaultModelId\n } else if (legacyConfig.defaultModelName) {\n defaultModelName = legacyConfig.defaultModelName\n }\n\n // 4. Remove legacy fields and return migrated config\n const migratedConfig: GlobalConfig & Partial<LegacyGlobalConfigFields> = {\n ...config,\n }\n delete migratedConfig.defaultModelId\n delete migratedConfig.currentSelectedModelId\n delete migratedConfig.mainAgentModelId\n delete migratedConfig.taskToolModelId\n\n return {\n ...migratedConfig,\n modelProfiles: migratedProfiles,\n modelPointers: migratedPointers,\n defaultModelName,\n }\n}\n\n// New model system utility functions\n\n/**\n * Deduplicate model profiles by modelName, keeping the one with the latest createdAt timestamp.\n *\n * @param profiles - Array of model profiles to deduplicate\n * @returns Deduplicated array of model profiles\n */\nexport function deduplicateModelProfiles(\n profiles: ModelProfile[],\n): ModelProfile[] {\n if (!profiles || profiles.length === 0) {\n return []\n }\n\n // Use Map to track the latest profile for each modelName\n const profileMap = new Map<string, ModelProfile>()\n\n for (const profile of profiles) {\n const existing = profileMap.get(profile.modelName)\n\n if (!existing) {\n // First occurrence of this modelName\n profileMap.set(profile.modelName, profile)\n } else {\n // Keep the one with the latest createdAt timestamp\n if (profile.createdAt > existing.createdAt) {\n profileMap.set(profile.modelName, profile)\n }\n }\n }\n\n // Return as array, preserving insertion order (which follows original array order for first occurrences)\n return Array.from(profileMap.values())\n}\n\nexport function setAllPointersToModel(modelName: string): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n main: modelName,\n task: modelName,\n reasoning: modelName,\n quick: modelName,\n compact: modelName,\n },\n defaultModelName: modelName,\n }\n saveGlobalConfig(updatedConfig)\n}\n\nexport function setModelPointer(\n pointer: ModelPointerType,\n modelName: string,\n): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n ...config.modelPointers,\n [pointer]: modelName,\n },\n }\n saveGlobalConfig(updatedConfig)\n\n // \uD83D\uDD27 Fix: Force ModelManager reload after config change\n // Import here to avoid circular dependency\n import('./model').then(({ reloadModelManager }) => {\n reloadModelManager()\n })\n}\n\n// Credential resolution functions for secure API key management\n\n/**\n * Resolve an API key for a ModelProfile.\n * Supports both plaintext keys (backward compatibility) and encrypted references.\n *\n * For plaintext keys (legacy):\n * Returns the key directly from the profile\n *\n * For encrypted references (encrypted:modelName):\n * Retrieves the key from the encrypted credential store\n *\n * @param profile The model profile to resolve the API key for\n * @returns The resolved API key, or null if not found\n * @throws Error if credential store access fails\n */\nexport async function resolveApiKey(\n profile: ModelProfile,\n): Promise<string | null> {\n if (!profile.apiKey) {\n return null\n }\n\n // Check if this is an encrypted reference\n if (profile.apiKey.startsWith('encrypted:')) {\n // Extract model name from the encrypted reference\n const modelName = profile.apiKey.slice('encrypted:'.length)\n\n // Import dynamically to avoid circular dependencies\n try {\n const { getApiKey } = await import('./credentials')\n return getApiKey(modelName)\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error)\n console.warn(\n `Failed to resolve encrypted API key for ${modelName}: ${errorMsg}`,\n )\n return null\n }\n }\n\n // Return plaintext key for backward compatibility\n return profile.apiKey\n}\n\n// \uD83D\uDD25 GPT-5 Configuration Validation and Auto-Repair Functions\n\n/**\n * Check if a model name represents a GPT-5 model\n */\nexport function isGPT5ModelName(modelName: string): boolean {\n if (!modelName || typeof modelName !== 'string') return false\n const lowerName = modelName.toLowerCase()\n return lowerName.startsWith('gpt-5') || lowerName.includes('gpt-5')\n}\n\n/**\n * Validate and auto-repair GPT-5 model configuration\n */\nexport function validateAndRepairGPT5Profile(\n profile: ModelProfile,\n): ModelProfile {\n const isGPT5 = isGPT5ModelName(profile.modelName)\n const now = Date.now()\n\n // Create a working copy\n const repairedProfile: ModelProfile = { ...profile }\n let wasRepaired = false\n\n // \uD83D\uDD27 Set GPT-5 detection flag\n if (isGPT5 !== profile.isGPT5) {\n repairedProfile.isGPT5 = isGPT5\n wasRepaired = true\n }\n\n if (isGPT5) {\n // \uD83D\uDD27 GPT-5 Parameter Validation and Repair\n\n // 1. Reasoning effort validation\n const validReasoningEfforts = ['minimal', 'low', 'medium', 'high']\n if (\n !profile.reasoningEffort ||\n !validReasoningEfforts.includes(profile.reasoningEffort)\n ) {\n repairedProfile.reasoningEffort = 'medium' // Default for coding tasks\n wasRepaired = true\n console.log(\n `\uD83D\uDD27 GPT-5 Config: Set reasoning effort to 'medium' for ${profile.modelName}`,\n )\n }\n\n // 2. Context length validation (GPT-5 models typically have 128k context)\n if (profile.contextLength < 128000) {\n repairedProfile.contextLength = 128000\n wasRepaired = true\n console.log(\n `\uD83D\uDD27 GPT-5 Config: Updated context length to 128k for ${profile.modelName}`,\n )\n }\n\n // 3. Output tokens validation (reasonable defaults for GPT-5)\n if (profile.maxTokens < 4000) {\n repairedProfile.maxTokens = 8192 // Good default for coding tasks\n wasRepaired = true\n console.log(\n `\uD83D\uDD27 GPT-5 Config: Updated max tokens to 8192 for ${profile.modelName}`,\n )\n }\n\n // 4. Provider validation\n if (\n profile.provider !== 'openai' &&\n profile.provider !== 'custom-openai' &&\n profile.provider !== 'azure'\n ) {\n console.warn(\n `\u26A0\uFE0F GPT-5 Config: Unexpected provider '${profile.provider}' for GPT-5 model ${profile.modelName}. Consider using 'openai' or 'custom-openai'.`,\n )\n }\n\n // 5. Base URL validation for official models\n if (profile.modelName.includes('gpt-5') && !profile.baseURL) {\n repairedProfile.baseURL = 'https://api.openai.com/v1'\n wasRepaired = true\n console.log(\n `\uD83D\uDD27 GPT-5 Config: Set default base URL for ${profile.modelName}`,\n )\n }\n }\n\n // Update validation metadata\n repairedProfile.validationStatus = wasRepaired ? 'auto_repaired' : 'valid'\n repairedProfile.lastValidation = now\n\n if (wasRepaired) {\n console.log(\n `\u2705 GPT-5 Config: Auto-repaired configuration for ${profile.modelName}`,\n )\n }\n\n return repairedProfile\n}\n\n/**\n * Validate and repair all GPT-5 profiles in the global configuration\n */\nexport function validateAndRepairAllGPT5Profiles(): {\n repaired: number\n total: number\n} {\n const config = getGlobalConfig()\n if (!config.modelProfiles) {\n return { repaired: 0, total: 0 }\n }\n\n let repairCount = 0\n const repairedProfiles = config.modelProfiles.map(profile => {\n const repairedProfile = validateAndRepairGPT5Profile(profile)\n if (repairedProfile.validationStatus === 'auto_repaired') {\n repairCount++\n }\n return repairedProfile\n })\n\n // Save the repaired configuration\n if (repairCount > 0) {\n const updatedConfig = {\n ...config,\n modelProfiles: repairedProfiles,\n }\n saveGlobalConfig(updatedConfig)\n console.log(`\uD83D\uDD27 GPT-5 Config: Auto-repaired ${repairCount} model profiles`)\n }\n\n return { repaired: repairCount, total: config.modelProfiles.length }\n}\n\n/**\n * Get GPT-5 configuration recommendations for a specific model\n */\nexport function getGPT5ConfigRecommendations(\n modelName: string,\n): Partial<ModelProfile> {\n if (!isGPT5ModelName(modelName)) {\n return {}\n }\n\n const recommendations: Partial<ModelProfile> = {\n contextLength: 128000, // GPT-5 standard context length\n maxTokens: 8192, // Good default for coding tasks\n reasoningEffort: 'medium', // Balanced for most coding tasks\n isGPT5: true,\n }\n\n // Model-specific optimizations\n if (modelName.includes('gpt-5-mini')) {\n recommendations.maxTokens = 4096 // Smaller default for mini\n recommendations.reasoningEffort = 'low' // Faster for simple tasks\n } else if (modelName.includes('gpt-5-nano')) {\n recommendations.maxTokens = 2048 // Even smaller for nano\n recommendations.reasoningEffort = 'minimal' // Fastest option\n }\n\n return recommendations\n}\n\n/**\n * Create a properly configured GPT-5 model profile\n */\nexport function createGPT5ModelProfile(\n name: string,\n modelName: string,\n apiKey: string,\n baseURL?: string,\n provider: ProviderType = 'openai',\n): ModelProfile {\n const recommendations = getGPT5ConfigRecommendations(modelName)\n\n const profile: ModelProfile = {\n name,\n provider,\n modelName,\n baseURL: baseURL || 'https://api.openai.com/v1',\n apiKey,\n maxTokens: recommendations.maxTokens || 8192,\n contextLength: recommendations.contextLength || 128000,\n reasoningEffort: recommendations.reasoningEffort || 'medium',\n isActive: true,\n createdAt: Date.now(),\n isGPT5: true,\n validationStatus: 'valid',\n lastValidation: Date.now(),\n }\n\n console.log(`\u2705 Created GPT-5 model profile: ${name} (${modelName})`)\n return profile\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { existsSync, readFileSync, writeFileSync, renameSync, rmSync } from 'fs'\nimport { resolve, join, dirname } from 'path'\nimport { cloneDeep, memoize, pick } from 'lodash-es'\nimport { homedir } from 'os'\nimport { GLOBAL_CONFIG_FILE } from './env'\nimport { getCwd } from './state'\nimport { randomBytes } from 'crypto'\nimport { safeParseJSON } from './json'\nimport { ConfigParseError } from './errors'\nimport type { ThemeNames } from './theme'\nimport { debug as debugLogger } from './debugLogger'\nimport { safeValidateGlobalConfig } from './configSchema'\n\n// Re-export canonical types derived from Zod schemas (single source of truth)\nexport type {\n McpStdioServerConfig,\n McpSSEServerConfig,\n McpHTTPServerConfig,\n McpServerConfig,\n AutoUpdaterStatus,\n NotificationChannel,\n ProviderType,\n UILanguage,\n SafetyMode,\n ReasoningEffort,\n ModelProfile,\n ModelPointerType,\n ModelPointers,\n AccountInfo,\n SandboxConfigData,\n CompressionMode,\n} from './configSchema'\n\n// Import types locally for use in this file\nimport type {\n McpServerConfig,\n AutoUpdaterStatus,\n NotificationChannel,\n ProviderType,\n UILanguage,\n SafetyMode,\n ModelProfile,\n ModelPointerType,\n ModelPointers,\n AccountInfo,\n SandboxConfigData,\n CompressionMode,\n} from './configSchema'\nimport { getSessionState, setSessionState } from './sessionState'\n// CompressionMode now re-exported from configSchema.ts\n\n// Types McpStdioServerConfig, McpSSEServerConfig, McpHTTPServerConfig,\n// McpServerConfig, SandboxConfigData are now derived from Zod schemas\n// and re-exported from configSchema.ts above.\n\n// ProjectConfig uses Zod-derived sub-types but keeps manual definition\n// due to .passthrough() in Zod schema generating incompatible index signatures.\nexport type ProjectConfig = {\n allowedTools: string[]\n context: Record<string, string>\n contextFiles?: string[]\n history: string[]\n dontCrawlDirectory?: boolean\n enableArchitectTool?: boolean\n mcpContextUris: string[]\n mcpServers?: Record<string, McpServerConfig>\n approvedMcprcServers?: string[]\n rejectedMcprcServers?: string[]\n lastAPIDuration?: number\n lastCost?: number\n lastDuration?: number\n lastSessionId?: string\n exampleFiles?: string[]\n exampleFilesGeneratedAt?: number\n hasTrustDialogAccepted?: boolean\n hasCompletedProjectOnboarding?: boolean\n sandbox?: SandboxConfigData\n [key: string]: unknown\n}\n\nconst DEFAULT_PROJECT_CONFIG: ProjectConfig = {\n allowedTools: [],\n context: {},\n history: [],\n dontCrawlDirectory: false,\n enableArchitectTool: false,\n mcpContextUris: [],\n mcpServers: {},\n approvedMcprcServers: [],\n rejectedMcprcServers: [],\n hasTrustDialogAccepted: false,\n}\n\nfunction defaultConfigForProject(projectPath: string): ProjectConfig {\n const config = { ...DEFAULT_PROJECT_CONFIG }\n if (projectPath === homedir()) {\n config.dontCrawlDirectory = true\n }\n return config\n}\n\n// AutoUpdaterStatus now derived from Zod schema in configSchema.ts\n\nexport function isAutoUpdaterStatus(value: string): value is AutoUpdaterStatus {\n return ['disabled', 'enabled', 'no_permissions', 'not_configured'].includes(\n value as AutoUpdaterStatus,\n )\n}\n\n// NotificationChannel now derived from Zod schema in configSchema.ts\n\n/**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\nexport type DisplayMode = 'minimal' | 'compact' | 'detailed'\n\n// UILanguage now derived from Zod schema in configSchema.ts\n\n// SafetyMode now derived from Zod schema in configSchema.ts\n\n/**\n * Get verbose mode label (uses i18n)\n * Import dynamically to avoid circular dependency\n */\nexport function getVerboseLabel(verbose: boolean): string {\n // Dynamic import to avoid circular dependency at module load time\n try {\n const { t } = require('../i18n')\n return verbose ? t('ui.verbose.on') : t('ui.verbose.off')\n } catch {\n // Fallback if i18n not loaded yet\n return verbose ? 'Verbose: On' : 'Verbose: Off'\n }\n}\n\n// ProviderType now derived from Zod schema in configSchema.ts\n\n// ModelProfile now derived from Zod schema in configSchema.ts\n\n// Legacy type for config migration - includes deprecated 'id' field\ntype LegacyModelProfile = ModelProfile & {\n id?: string\n}\n\n// Legacy global config fields for migration\ntype LegacyGlobalConfigFields = {\n defaultModelId?: string\n defaultModelName?: string\n currentSelectedModelId?: string\n mainAgentModelId?: string\n taskToolModelId?: string\n}\n\n// ModelPointerType, ModelPointers, AccountInfo now derived from Zod schema in configSchema.ts\n\nexport type GlobalConfig = {\n projects?: Record<string, ProjectConfig>\n numStartups: number\n autoUpdaterStatus?: AutoUpdaterStatus\n userID?: string\n theme: ThemeNames\n hasCompletedOnboarding?: boolean\n // Tracks the last version that reset onboarding, used with MIN_VERSION_REQUIRING_ONBOARDING_RESET\n lastOnboardingVersion?: string\n // Tracks the last version for which release notes were seen, used for managing release notes\n lastReleaseNotesSeen?: string\n mcpServers?: Record<string, McpServerConfig>\n preferredNotifChannel: NotificationChannel\n /**\n * Verbose mode: shows full parameters and complete outputs when enabled\n * - false: Concise output (default)\n * - true: Detailed/verbose output\n */\n verbose: boolean\n /**\n * @deprecated Use verbose boolean instead. Kept for backward compatibility migration.\n */\n displayMode?: DisplayMode\n customApiKeyResponses?: {\n approved?: string[]\n rejected?: string[]\n }\n primaryProvider?: ProviderType\n maxTokens?: number\n hasAcknowledgedCostThreshold?: boolean\n oauthAccount?: AccountInfo\n iterm2KeyBindingInstalled?: boolean // Legacy - keeping for backward compatibility\n shiftEnterKeyBindingInstalled?: boolean\n proxy?: string\n stream?: boolean\n\n // New model system\n modelProfiles?: ModelProfile[] // Model configuration list\n modelPointers?: ModelPointers // Model pointer system\n defaultModelName?: string // Default model\n // Update notifications\n lastDismissedUpdateVersion?: string\n // Compression mode\n compressionMode?: CompressionMode // Compression algorithm mode ('business' or 'code')\n // Thinking mode (Phase 4.2)\n thinking?: boolean // Whether thinking/extended reasoning mode is enabled\n // UI Language\n language?: UILanguage // UI language ('en' or 'zh-CN')\n /**\n * @deprecated Use safetyMode instead. Kept for backward compatibility.\n * Safe mode: when enabled, requires user confirmation for all tool executions\n */\n safeMode?: boolean\n /**\n * Safety mode for tool execution (4-tier system):\n * - 'yolo': All tools allowed without confirmation (default for non-technical users)\n * - 'smart': Safe/monitored tools auto-allowed, dangerous tools need confirmation\n * - 'strict': Only safe tools auto-allowed, all others need confirmation\n * - 'free': Project directory operations auto-allowed, outside requires confirmation\n */\n safetyMode?: SafetyMode\n // Claude Code plugin auto-sync\n autoSyncClaudeCode?: boolean\n // Enable experimental memory tools (read/write persistent agent memory)\n enableMemoryTools?: boolean\n // Output style selection (CC compat)\n outputStyle?: string\n // Auto-memory: extract key decisions during auto-compact\n autoMemory?: boolean\n // File backup for /undo\n backupEnabled?: boolean\n}\n\nexport const DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n numStartups: 0,\n autoUpdaterStatus: 'not_configured',\n theme: 'dark',\n preferredNotifChannel: 'iterm2',\n verbose: false,\n primaryProvider: 'anthropic',\n customApiKeyResponses: {\n approved: [],\n rejected: [],\n },\n stream: true,\n\n // New model system defaults\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n lastDismissedUpdateVersion: undefined,\n compressionMode: 'business', // Default to business consulting compression\n thinking: false, // Default to thinking mode off (Phase 4.2)\n language: 'en', // Default to English\n safeMode: false, // Deprecated: use safetyMode instead\n safetyMode: 'smart', // Default to smart mode \u2014 safe tools auto-allowed, dangerous tools need confirmation\n}\n\nexport const GLOBAL_CONFIG_KEYS = [\n 'autoUpdaterStatus',\n 'theme',\n 'hasCompletedOnboarding',\n 'lastOnboardingVersion',\n 'lastReleaseNotesSeen',\n 'verbose',\n 'customApiKeyResponses',\n 'primaryProvider',\n 'preferredNotifChannel',\n 'shiftEnterKeyBindingInstalled',\n 'maxTokens',\n 'compressionMode',\n 'language',\n 'safetyMode',\n 'enableMemoryTools',\n 'outputStyle',\n 'autoMemory',\n] as const\n\nexport type GlobalConfigKey = (typeof GLOBAL_CONFIG_KEYS)[number]\n\nexport function isGlobalConfigKey(key: string): key is GlobalConfigKey {\n return GLOBAL_CONFIG_KEYS.includes(key as GlobalConfigKey)\n}\n\nexport const PROJECT_CONFIG_KEYS = [\n 'dontCrawlDirectory',\n 'enableArchitectTool',\n 'hasTrustDialogAccepted',\n 'hasCompletedProjectOnboarding',\n] as const\n\nexport type ProjectConfigKey = (typeof PROJECT_CONFIG_KEYS)[number]\n\nexport function checkHasTrustDialogAccepted(): boolean {\n let currentPath = getCwd()\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n while (true) {\n const projectConfig = config.projects?.[currentPath]\n if (projectConfig?.hasTrustDialogAccepted) {\n return true\n }\n const parentPath = resolve(currentPath, '..')\n // Stop if we've reached the root (when parent is same as current)\n if (parentPath === currentPath) {\n break\n }\n currentPath = parentPath\n }\n\n return false\n}\n\n// We have to put this test code here because Jest doesn't support mocking ES modules :O\nconst TEST_GLOBAL_CONFIG_FOR_TESTING: GlobalConfig = {\n ...DEFAULT_GLOBAL_CONFIG,\n autoUpdaterStatus: 'disabled',\n}\nconst TEST_PROJECT_CONFIG_FOR_TESTING: ProjectConfig = {\n ...DEFAULT_PROJECT_CONFIG,\n}\n\nexport function isProjectConfigKey(key: string): key is ProjectConfigKey {\n return PROJECT_CONFIG_KEYS.includes(key as ProjectConfigKey)\n}\n\nexport function saveGlobalConfig(config: GlobalConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in config) {\n ;(TEST_GLOBAL_CONFIG_FOR_TESTING as Record<string, unknown>)[key] = (\n config as Record<string, unknown>\n )[key]\n }\n return\n }\n\n // \u76F4\u63A5\u4FDD\u5B58\u914D\u7F6E\uFF08\u65E0\u9700\u6E05\u9664\u7F13\u5B58\uFF0C\u56E0\u4E3A\u5DF2\u79FB\u9664\u7F13\u5B58\uFF09\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG).projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\n/**\n * Migrate legacy displayMode to verbose boolean\n */\nfunction migrateDisplayModeToVerbose(config: GlobalConfig): GlobalConfig {\n // If verbose is already set, no migration needed\n if (config.verbose !== undefined) {\n return config\n }\n\n // Check for legacy displayMode field\n const legacyConfig = config as GlobalConfig & { displayMode?: DisplayMode }\n if (legacyConfig.displayMode !== undefined) {\n const migratedConfig: GlobalConfig = {\n ...config,\n verbose: legacyConfig.displayMode === 'detailed',\n }\n // Remove legacy field\n delete (migratedConfig as Record<string, unknown>).displayMode\n return migratedConfig\n }\n\n // Default to false if no verbose or displayMode\n return {\n ...config,\n verbose: false,\n }\n}\n\n// \u4E34\u65F6\u79FB\u9664\u7F13\u5B58\uFF0C\u786E\u4FDD\u603B\u662F\u83B7\u53D6\u6700\u65B0\u914D\u7F6E\nexport function getGlobalConfig(): GlobalConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_GLOBAL_CONFIG_FOR_TESTING\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n const migratedConfig = migrateModelProfilesRemoveId(config)\n const displayMigratedConfig = migrateDisplayModeToVerbose(migratedConfig)\n\n // Apply model profile deduplication\n if (\n displayMigratedConfig.modelProfiles &&\n displayMigratedConfig.modelProfiles.length > 0\n ) {\n const originalCount = displayMigratedConfig.modelProfiles.length\n const deduplicatedProfiles = deduplicateModelProfiles(\n displayMigratedConfig.modelProfiles,\n )\n const deduplicatedCount = deduplicatedProfiles.length\n\n // If duplicates were found and removed, auto-save the deduplicated config\n if (deduplicatedCount < originalCount) {\n debugLogger.state('CONFIG_DEDUPLICATE_PROFILES', {\n originalCount: String(originalCount),\n deduplicatedCount: String(deduplicatedCount),\n removedCount: String(originalCount - deduplicatedCount),\n })\n const configToSave = {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n // Save the deduplicated config (avoid recursion by using saveConfig directly)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...configToSave,\n projects: config.projects,\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n return configToSave\n }\n\n return {\n ...displayMigratedConfig,\n modelProfiles: deduplicatedProfiles,\n }\n }\n\n return displayMigratedConfig\n}\n\nexport function getAnthropicApiKey(): null | string {\n return process.env.ANTHROPIC_API_KEY || null\n}\n\nexport function normalizeApiKeyForConfig(apiKey: string): string {\n return apiKey?.slice(-20) ?? ''\n}\n\nexport function getCustomApiKeyStatus(\n truncatedApiKey: string,\n): 'approved' | 'rejected' | 'new' {\n const config = getGlobalConfig()\n if (config.customApiKeyResponses?.approved?.includes(truncatedApiKey)) {\n return 'approved'\n }\n if (config.customApiKeyResponses?.rejected?.includes(truncatedApiKey)) {\n return 'rejected'\n }\n return 'new'\n}\n\n/**\n * Atomically write content to a file using temp file + rename pattern.\n * This prevents data corruption if writes are interrupted or multiple processes\n * attempt to write concurrently.\n *\n * @param filePath - The target file path to write to\n * @param content - The content to write\n * @throws {Error} If write or rename operation fails\n */\nfunction atomicWriteFileSync(filePath: string, content: string): void {\n const dir = dirname(filePath)\n const tempPath = join(\n dir,\n `.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`,\n )\n\n try {\n // Write to temporary file\n writeFileSync(tempPath, content, 'utf-8')\n // Atomically rename temp to target (atomic on most filesystems)\n renameSync(tempPath, filePath)\n } catch (error) {\n // Clean up temporary file on failure\n try {\n rmSync(tempPath, { force: true })\n } catch {\n // Ignore cleanup errors\n }\n throw error\n }\n}\n\nfunction saveConfig<A extends object>(\n file: string,\n config: A,\n defaultConfig: A,\n): void {\n // Filter out any values that match the defaults\n const filteredConfig = Object.fromEntries(\n Object.entries(config).filter(\n ([key, value]) =>\n JSON.stringify(value) !== JSON.stringify(defaultConfig[key as keyof A]),\n ),\n )\n try {\n atomicWriteFileSync(file, JSON.stringify(filteredConfig, null, 2))\n } catch (error) {\n const err = error as NodeJS.ErrnoException\n if (\n err?.code === 'EACCES' ||\n err?.code === 'EPERM' ||\n err?.code === 'EROFS'\n ) {\n debugLogger.state('CONFIG_SAVE_SKIPPED', {\n file,\n reason: String(err.code),\n })\n return\n }\n throw error\n }\n}\n\n// Flag to track if config reading is allowed\nlet configReadingAllowed = false\n\nexport function enableConfigs(): void {\n // Any reads to configuration before this flag is set show an console warning\n // to prevent us from adding config reading during module initialization\n configReadingAllowed = true\n // We only check the global config because currently all the configs share a file\n getConfig(\n GLOBAL_CONFIG_FILE,\n DEFAULT_GLOBAL_CONFIG,\n true /* throw on invalid */,\n )\n}\n\nfunction getConfig<A>(\n file: string,\n defaultConfig: A,\n throwOnInvalid?: boolean,\n): A {\n // \u7B80\u5316\u914D\u7F6E\u8BBF\u95EE\u903B\u8F91\uFF0C\u79FB\u9664\u590D\u6742\u7684\u65F6\u5E8F\u68C0\u67E5\n\n debugLogger.state('CONFIG_LOAD_START', {\n file,\n fileExists: String(existsSync(file)),\n throwOnInvalid: String(!!throwOnInvalid),\n })\n\n if (!existsSync(file)) {\n debugLogger.state('CONFIG_LOAD_DEFAULT', {\n file,\n reason: 'file_not_exists',\n defaultConfigKeys: Object.keys(defaultConfig as object).join(', '),\n })\n return cloneDeep(defaultConfig)\n }\n\n try {\n const fileContent = readFileSync(file, 'utf-8')\n debugLogger.state('CONFIG_FILE_READ', {\n file,\n contentLength: String(fileContent.length),\n contentPreview:\n fileContent.substring(0, 100) + (fileContent.length > 100 ? '...' : ''),\n })\n\n try {\n const parsedConfig = JSON.parse(fileContent)\n debugLogger.state('CONFIG_JSON_PARSED', {\n file,\n parsedKeys: Object.keys(parsedConfig).join(', '),\n })\n\n // Zod validation \u2014 monitor mode (log only, never reject)\n if (file === GLOBAL_CONFIG_FILE) {\n const validation = safeValidateGlobalConfig(parsedConfig)\n if (!validation.success && validation.errors) {\n debugLogger.warn('CONFIG_VALIDATION', {\n file,\n issues: validation.errors.issues\n .map(i => `${i.path.join('.')}: ${i.message}`)\n .join('; '),\n })\n }\n }\n\n // Handle backward compatibility - remove logic for deleted fields\n const finalConfig = {\n ...cloneDeep(defaultConfig),\n ...parsedConfig,\n }\n\n debugLogger.state('CONFIG_LOAD_SUCCESS', {\n file,\n finalConfigKeys: Object.keys(finalConfig as object).join(', '),\n })\n\n return finalConfig\n } catch (error) {\n // Throw a ConfigParseError with the file path and default config\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n\n debugLogger.error('CONFIG_JSON_PARSE_ERROR', {\n file,\n errorMessage,\n errorType:\n error instanceof Error ? error.constructor.name : typeof error,\n contentLength: String(fileContent.length),\n })\n\n throw new ConfigParseError(errorMessage, file, defaultConfig)\n }\n } catch (error: unknown) {\n // Re-throw ConfigParseError if throwOnInvalid is true\n if (error instanceof ConfigParseError && throwOnInvalid) {\n debugLogger.error('CONFIG_PARSE_ERROR_RETHROWN', {\n file,\n throwOnInvalid: String(throwOnInvalid),\n errorMessage: error.message,\n })\n throw error\n }\n\n debugLogger.warn('CONFIG_FALLBACK_TO_DEFAULT', {\n file,\n errorType: error instanceof Error ? error.constructor.name : typeof error,\n errorMessage: error instanceof Error ? error.message : String(error),\n action: 'using_default_config',\n })\n\n return cloneDeep(defaultConfig)\n }\n}\n\nexport function getCurrentProjectConfig(): ProjectConfig {\n if (process.env.NODE_ENV === 'test') {\n return TEST_PROJECT_CONFIG_FOR_TESTING\n }\n\n const absolutePath = resolve(getCwd())\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n\n if (!config.projects) {\n return defaultConfigForProject(absolutePath)\n }\n\n const projectConfig =\n config.projects[absolutePath] ?? defaultConfigForProject(absolutePath)\n // Guard: allowedTools may be serialized as a JSON string in some config paths\n if (typeof projectConfig.allowedTools === 'string') {\n projectConfig.allowedTools =\n (safeParseJSON(projectConfig.allowedTools) as string[]) ?? []\n }\n return projectConfig\n}\n\nexport function saveCurrentProjectConfig(projectConfig: ProjectConfig): void {\n if (process.env.NODE_ENV === 'test') {\n for (const key in projectConfig) {\n TEST_PROJECT_CONFIG_FOR_TESTING[key] = projectConfig[key]\n }\n return\n }\n const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG)\n saveConfig(\n GLOBAL_CONFIG_FILE,\n {\n ...config,\n projects: {\n ...config.projects,\n [resolve(getCwd())]: projectConfig,\n },\n },\n DEFAULT_GLOBAL_CONFIG,\n )\n}\n\nexport async function isAutoUpdaterDisabled(): Promise<boolean> {\n return getGlobalConfig().autoUpdaterStatus === 'disabled'\n}\n\nexport const TEST_MCPRC_CONFIG_FOR_TESTING: Record<string, McpServerConfig> = {}\n\nexport function clearMcprcConfigForTesting(): void {\n if (process.env.NODE_ENV === 'test') {\n Object.keys(TEST_MCPRC_CONFIG_FOR_TESTING).forEach(key => {\n delete TEST_MCPRC_CONFIG_FOR_TESTING[key]\n })\n }\n}\n\nexport function addMcprcServerForTesting(\n name: string,\n server: McpServerConfig,\n): void {\n if (process.env.NODE_ENV === 'test') {\n TEST_MCPRC_CONFIG_FOR_TESTING[name] = server\n }\n}\n\nexport function removeMcprcServerForTesting(name: string): void {\n if (process.env.NODE_ENV === 'test') {\n if (!TEST_MCPRC_CONFIG_FOR_TESTING[name]) {\n throw new Error(`No MCP server found with name: ${name} in .mcprc`)\n }\n delete TEST_MCPRC_CONFIG_FOR_TESTING[name]\n }\n}\n\nexport const getMcprcConfig = memoize(\n (): Record<string, McpServerConfig> => {\n if (process.env.NODE_ENV === 'test') {\n return TEST_MCPRC_CONFIG_FOR_TESTING\n }\n\n const mcprcPath = join(getCwd(), '.mcprc')\n if (!existsSync(mcprcPath)) {\n return {}\n }\n\n try {\n const mcprcContent = readFileSync(mcprcPath, 'utf-8')\n const config = safeParseJSON(mcprcContent)\n if (config && typeof config === 'object') {\n // Logging removed\n return config as Record<string, McpServerConfig>\n }\n } catch {\n // Ignore errors reading/parsing .mcprc (they're logged in safeParseJSON)\n }\n return {}\n },\n // This function returns the same value as long as the cwd and mcprc file content remain the same\n () => {\n const cwd = getCwd()\n const mcprcPath = join(cwd, '.mcprc')\n if (existsSync(mcprcPath)) {\n try {\n const stat = readFileSync(mcprcPath, 'utf-8')\n return `${cwd}:${stat}`\n } catch {\n return cwd\n }\n }\n return cwd\n },\n)\n\nexport function getOrCreateUserID(): string {\n const config = getGlobalConfig()\n if (config.userID) {\n return config.userID\n }\n\n const userID = randomBytes(32).toString('hex')\n saveGlobalConfig({ ...config, userID })\n return userID\n}\n\nexport function getConfigForCLI(key: string, global: boolean): unknown {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getGlobalConfig()[key]\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: '${key}' is not a valid config key. Valid keys are: ${PROJECT_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n return getCurrentProjectConfig()[key]\n }\n}\n\nexport function setConfigForCLI(\n key: string,\n value: unknown,\n global: boolean,\n): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n\n if (key === 'autoUpdaterStatus' && !isAutoUpdaterStatus(value as string)) {\n console.error(\n `Error: Invalid value for autoUpdaterStatus. Must be one of: disabled, enabled, no_permissions, not_configured`,\n )\n process.exit(1)\n }\n\n const currentConfig = getGlobalConfig()\n saveGlobalConfig({\n ...currentConfig,\n [key]: value,\n })\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot set '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n saveCurrentProjectConfig({\n ...currentConfig,\n [key]: value,\n })\n }\n // Wait for the output to be flushed, to avoid clearing the screen.\n setTimeout(() => {\n // Without this we hang indefinitely.\n process.exit(0)\n }, 100)\n}\n\nexport function deleteConfigForCLI(key: string, global: boolean): void {\n if (global) {\n if (!isGlobalConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${GLOBAL_CONFIG_KEYS.join(', ')}`,\n )\n process.exit(1)\n }\n const currentConfig = getGlobalConfig()\n delete currentConfig[key]\n saveGlobalConfig(currentConfig)\n } else {\n if (!isProjectConfigKey(key)) {\n console.error(\n `Error: Cannot delete '${key}'. Only these keys can be modified: ${PROJECT_CONFIG_KEYS.join(', ')}. Did you mean --global?`,\n )\n process.exit(1)\n }\n const currentConfig = getCurrentProjectConfig()\n delete currentConfig[key]\n saveCurrentProjectConfig(currentConfig)\n }\n}\n\nexport function listConfigForCLI(global: true): GlobalConfig\nexport function listConfigForCLI(global: false): ProjectConfig\nexport function listConfigForCLI(global: boolean): object {\n if (global) {\n const currentConfig = pick(getGlobalConfig(), GLOBAL_CONFIG_KEYS)\n return currentConfig\n } else {\n return pick(getCurrentProjectConfig(), PROJECT_CONFIG_KEYS)\n }\n}\n\nexport function getOpenAIApiKey(): string | undefined {\n return process.env.OPENAI_API_KEY\n}\n\n// Configuration migration utility functions\nfunction migrateModelProfilesRemoveId(config: GlobalConfig): GlobalConfig {\n if (!config.modelProfiles) return config\n\n // Cast to legacy type for migration - config may have old fields\n const legacyConfig = config as GlobalConfig & LegacyGlobalConfigFields\n\n // 1. Remove id field from ModelProfile objects and build ID to modelName mapping\n const idToModelNameMap = new Map<string, string>()\n const migratedProfiles = config.modelProfiles.map(profile => {\n // Cast to legacy type that includes optional id field\n const legacyProfile = profile as LegacyModelProfile\n // Build mapping before removing id field\n if (legacyProfile.id && profile.modelName) {\n idToModelNameMap.set(legacyProfile.id, profile.modelName)\n }\n\n // Remove id field, keep everything else\n const { id, ...profileWithoutId } = legacyProfile\n return profileWithoutId as ModelProfile\n })\n\n // 2. Migrate ModelPointers from IDs to modelNames\n const migratedPointers: ModelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }\n\n if (config.modelPointers) {\n Object.entries(config.modelPointers).forEach(([pointer, value]) => {\n if (value) {\n // If value looks like an old ID (model_xxx), map it to modelName\n const modelName = idToModelNameMap.get(value) || value\n migratedPointers[pointer as ModelPointerType] = modelName\n }\n })\n }\n\n // 3. Migrate legacy config fields\n let defaultModelName: string | undefined\n if (legacyConfig.defaultModelId) {\n defaultModelName =\n idToModelNameMap.get(legacyConfig.defaultModelId) ||\n legacyConfig.defaultModelId\n } else if (legacyConfig.defaultModelName) {\n defaultModelName = legacyConfig.defaultModelName\n }\n\n // 4. Remove legacy fields and return migrated config\n const migratedConfig: GlobalConfig & Partial<LegacyGlobalConfigFields> = {\n ...config,\n }\n delete migratedConfig.defaultModelId\n delete migratedConfig.currentSelectedModelId\n delete migratedConfig.mainAgentModelId\n delete migratedConfig.taskToolModelId\n\n return {\n ...migratedConfig,\n modelProfiles: migratedProfiles,\n modelPointers: migratedPointers,\n defaultModelName,\n }\n}\n\n// New model system utility functions\n\n/**\n * Deduplicate model profiles by modelName, keeping the one with the latest createdAt timestamp.\n *\n * @param profiles - Array of model profiles to deduplicate\n * @returns Deduplicated array of model profiles\n */\nexport function deduplicateModelProfiles(\n profiles: ModelProfile[],\n): ModelProfile[] {\n if (!profiles || profiles.length === 0) {\n return []\n }\n\n // Use Map to track the latest profile for each modelName\n const profileMap = new Map<string, ModelProfile>()\n\n for (const profile of profiles) {\n const existing = profileMap.get(profile.modelName)\n\n if (!existing) {\n // First occurrence of this modelName\n profileMap.set(profile.modelName, profile)\n } else {\n // Keep the one with the latest createdAt timestamp\n if (profile.createdAt > existing.createdAt) {\n profileMap.set(profile.modelName, profile)\n }\n }\n }\n\n // Return as array, preserving insertion order (which follows original array order for first occurrences)\n return Array.from(profileMap.values())\n}\n\nexport function setAllPointersToModel(modelName: string): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n main: modelName,\n task: modelName,\n reasoning: modelName,\n quick: modelName,\n compact: modelName,\n },\n defaultModelName: modelName,\n }\n saveGlobalConfig(updatedConfig)\n}\n\nexport function setModelPointer(\n pointer: ModelPointerType,\n modelName: string,\n): void {\n const config = getGlobalConfig()\n const updatedConfig = {\n ...config,\n modelPointers: {\n ...config.modelPointers,\n [pointer]: modelName,\n },\n }\n saveGlobalConfig(updatedConfig)\n\n // \uD83D\uDD27 Fix: Force ModelManager reload after config change\n // Import here to avoid circular dependency\n import('./model').then(({ reloadModelManager }) => {\n reloadModelManager()\n })\n}\n\n// Credential resolution functions for secure API key management\n\n/**\n * Resolve an API key for a ModelProfile.\n * Supports both plaintext keys (backward compatibility) and encrypted references.\n *\n * For plaintext keys (legacy):\n * Returns the key directly from the profile\n *\n * For encrypted references (encrypted:modelName):\n * Retrieves the key from the encrypted credential store\n *\n * @param profile The model profile to resolve the API key for\n * @returns The resolved API key, or null if not found\n * @throws Error if credential store access fails\n */\nexport async function resolveApiKey(\n profile: ModelProfile,\n): Promise<string | null> {\n if (!profile.apiKey) {\n return null\n }\n\n // Check if this is an encrypted reference\n if (profile.apiKey.startsWith('encrypted:')) {\n // Extract model name from the encrypted reference\n const modelName = profile.apiKey.slice('encrypted:'.length)\n\n // Import dynamically to avoid circular dependencies\n try {\n const { getApiKey } = await import('./credentials')\n return getApiKey(modelName)\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error)\n debugLogger.warn(\n 'CREDENTIAL_RESOLVE',\n `Failed to resolve encrypted API key for ${modelName}: ${errorMsg}`,\n )\n return null\n }\n }\n\n // Return plaintext key for backward compatibility\n return profile.apiKey\n}\n\n// GPT-5 functions extracted to src/utils/gpt5.ts \u2014 re-exported for backward compatibility\nexport {\n isGPT5ModelName,\n validateAndRepairGPT5Profile,\n validateAndRepairAllGPT5Profiles,\n getGPT5ConfigRecommendations,\n createGPT5ModelProfile,\n} from './gpt5'\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|