@within-7/minto 0.4.0 → 0.4.2
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 +7 -0
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +1 -1
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/constants.js +2 -2
- package/dist/commands/agents/constants.js.map +2 -2
- package/dist/commands/clear.js +4 -3
- package/dist/commands/clear.js.map +2 -2
- package/dist/commands/compact.js +2 -2
- package/dist/commands/compact.js.map +1 -1
- package/dist/commands/context.js +3 -1
- package/dist/commands/context.js.map +2 -2
- package/dist/commands/login.js +128 -0
- package/dist/commands/login.js.map +7 -0
- package/dist/commands/memory.js +33 -82
- package/dist/commands/memory.js.map +2 -2
- package/dist/commands/quit.js +3 -1
- package/dist/commands/quit.js.map +2 -2
- package/dist/commands/resume.js +39 -239
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/tasks.js +1 -1
- package/dist/commands/tasks.js.map +2 -2
- package/dist/commands/terminalSetup.js +6 -2
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands.js +2 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AgentDetailView.js +126 -0
- package/dist/components/AgentDetailView.js.map +7 -0
- package/dist/components/AgentThinkingBlock.js +1 -1
- package/dist/components/AgentThinkingBlock.js.map +2 -2
- package/dist/components/AgentViewBanner.js +22 -0
- package/dist/components/AgentViewBanner.js.map +7 -0
- package/dist/components/HeaderBar.js +1 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +8 -1
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +26 -8
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/IdleNotificationBar.js +10 -0
- package/dist/components/IdleNotificationBar.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +55 -20
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/PromptInput.js +186 -115
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/RewindPanel.js +272 -0
- package/dist/components/RewindPanel.js.map +7 -0
- package/dist/components/Spinner.js +10 -21
- package/dist/components/Spinner.js.map +2 -2
- package/dist/components/StreamingTextPreview.js +29 -0
- package/dist/components/StreamingTextPreview.js.map +7 -0
- package/dist/components/SubagentBlock.js +3 -2
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/SubagentProgress.js +4 -4
- package/dist/components/SubagentProgress.js.map +2 -2
- package/dist/components/TabbedListView/SearchInput.js +1 -1
- package/dist/components/TabbedListView/SearchInput.js.map +2 -2
- package/dist/components/TabbedListView/TabbedListView.js +87 -41
- package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
- package/dist/components/TaskCard.js +4 -4
- package/dist/components/TaskCard.js.map +2 -2
- package/dist/components/TeamMemberPanel.js +107 -0
- package/dist/components/TeamMemberPanel.js.map +7 -0
- package/dist/components/ThinkingSelector.js +84 -0
- package/dist/components/ThinkingSelector.js.map +7 -0
- package/dist/components/TitledDivider.js +26 -0
- package/dist/components/TitledDivider.js.map +7 -0
- package/dist/components/TodoPanel.js +31 -30
- package/dist/components/TodoPanel.js.map +2 -2
- package/dist/components/TokenWarning.js +28 -7
- package/dist/components/TokenWarning.js.map +2 -2
- package/dist/components/messages/AssistantTextMessage.js +5 -2
- package/dist/components/messages/AssistantTextMessage.js.map +2 -2
- package/dist/components/messages/AssistantToolUseMessage.js +9 -1
- package/dist/components/messages/AssistantToolUseMessage.js.map +2 -2
- package/dist/components/messages/DefaultToolResultFallback.js +11 -0
- package/dist/components/messages/DefaultToolResultFallback.js.map +7 -0
- package/dist/components/messages/ParallelTasksGroupView.js +14 -6
- package/dist/components/messages/ParallelTasksGroupView.js.map +2 -2
- package/dist/components/messages/TaskInModuleView.js +27 -27
- package/dist/components/messages/TaskInModuleView.js.map +2 -2
- package/dist/components/messages/UserGuidanceMessage.js +26 -0
- package/dist/components/messages/UserGuidanceMessage.js.map +7 -0
- package/dist/components/messages/UserPromptMessage.js +2 -1
- package/dist/components/messages/UserPromptMessage.js.map +2 -2
- package/dist/components/messages/UserTeamNotificationMessage.js +91 -0
- package/dist/components/messages/UserTeamNotificationMessage.js.map +7 -0
- package/dist/components/messages/UserTextMessage.js +8 -0
- package/dist/components/messages/UserTextMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js +4 -2
- package/dist/components/messages/UserToolResultMessage/UserToolRejectMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js +18 -1
- package/dist/components/messages/UserToolResultMessage/UserToolResultMessage.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js +12 -1
- package/dist/components/messages/UserToolResultMessage/UserToolSuccessMessage.js.map +2 -2
- package/dist/components/permissions/PermissionRequest.js +4 -0
- package/dist/components/permissions/PermissionRequest.js.map +2 -2
- package/dist/components/permissions/PlanApprovalRequest.js +164 -0
- package/dist/components/permissions/PlanApprovalRequest.js.map +7 -0
- package/dist/constants/agentTeams.js +17 -0
- package/dist/constants/agentTeams.js.map +7 -0
- package/dist/constants/macros.js +2 -1
- package/dist/constants/macros.js.map +2 -2
- package/dist/constants/prompts/agentPrompt.js +1 -0
- package/dist/constants/prompts/agentPrompt.js.map +2 -2
- package/dist/constants/prompts/autoMemory.js +39 -0
- package/dist/constants/prompts/autoMemory.js.map +7 -0
- package/dist/constants/prompts/codeConventions.js +1 -13
- package/dist/constants/prompts/codeConventions.js.map +2 -2
- package/dist/constants/prompts/doingTasks.js +21 -2
- package/dist/constants/prompts/doingTasks.js.map +2 -2
- package/dist/constants/prompts/envInfo.js +6 -7
- package/dist/constants/prompts/envInfo.js.map +2 -2
- package/dist/constants/prompts/index.js +27 -5
- package/dist/constants/prompts/index.js.map +2 -2
- package/dist/constants/prompts/taskManagement.js +2 -43
- package/dist/constants/prompts/taskManagement.js.map +2 -2
- package/dist/constants/prompts/teamOverlays.js +50 -0
- package/dist/constants/prompts/teamOverlays.js.map +7 -0
- package/dist/constants/prompts/toneAndStyle.js +4 -29
- package/dist/constants/prompts/toneAndStyle.js.map +2 -2
- package/dist/constants/prompts/toolUsagePolicy.js +7 -22
- package/dist/constants/prompts/toolUsagePolicy.js.map +2 -2
- package/dist/constants/toolInputExamples.js +2 -2
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/context.js +39 -6
- package/dist/context.js.map +2 -2
- package/dist/core/backupManager.js +1 -1
- package/dist/core/backupManager.js.map +2 -2
- package/dist/core/permissions/rules/planModeRule.js +1 -1
- package/dist/core/permissions/rules/planModeRule.js.map +1 -1
- package/dist/core/permissions/rules/safeModeRule.js +1 -1
- package/dist/core/permissions/rules/safeModeRule.js.map +1 -1
- package/dist/engine/AgentEngine.js +902 -0
- package/dist/engine/AgentEngine.js.map +7 -0
- package/dist/engine/EngineRegistry.js +89 -0
- package/dist/engine/EngineRegistry.js.map +7 -0
- package/dist/engine/foregroundAdapter.js +191 -0
- package/dist/engine/foregroundAdapter.js.map +7 -0
- package/dist/engine/index.js +15 -0
- package/dist/engine/index.js.map +7 -0
- package/dist/engine/types.js +1 -0
- package/dist/engine/types.js.map +7 -0
- package/dist/entrypoints/cli.js +410 -79
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/hooks/useAgentEngine.js +129 -0
- package/dist/hooks/useAgentEngine.js.map +7 -0
- package/dist/hooks/useAgentTokenStats.js +0 -16
- package/dist/hooks/useAgentTokenStats.js.map +2 -2
- package/dist/hooks/useCanUseTool.js +47 -2
- package/dist/hooks/useCanUseTool.js.map +2 -2
- package/dist/hooks/useDeferredLoading.js +4 -1
- package/dist/hooks/useDeferredLoading.js.map +2 -2
- package/dist/hooks/useIdleNotifications.js +66 -0
- package/dist/hooks/useIdleNotifications.js.map +7 -0
- package/dist/hooks/useSessionTracking.js +9 -7
- package/dist/hooks/useSessionTracking.js.map +2 -2
- package/dist/hooks/useTeamMembers.js +51 -0
- package/dist/hooks/useTeamMembers.js.map +7 -0
- package/dist/i18n/locales/en.js +77 -12
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +77 -12
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js +113 -7
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +135 -37
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +504 -361
- package/dist/screens/REPL.js.map +3 -3
- package/dist/screens/ResumeConversation.js +199 -14
- package/dist/screens/ResumeConversation.js.map +2 -2
- package/dist/services/adapters/base.js.map +1 -1
- package/dist/services/agentTeams/backends/headless.js +108 -0
- package/dist/services/agentTeams/backends/headless.js.map +7 -0
- package/dist/services/agentTeams/backends/inProcess.js +102 -0
- package/dist/services/agentTeams/backends/inProcess.js.map +7 -0
- package/dist/services/agentTeams/backends/resolver.js +18 -0
- package/dist/services/agentTeams/backends/resolver.js.map +7 -0
- package/dist/services/agentTeams/backends/tmux.js +168 -0
- package/dist/services/agentTeams/backends/tmux.js.map +7 -0
- package/dist/services/agentTeams/backends/types.js +1 -0
- package/dist/services/agentTeams/backends/types.js.map +7 -0
- package/dist/services/agentTeams/heartbeat.js +88 -0
- package/dist/services/agentTeams/heartbeat.js.map +7 -0
- package/dist/services/agentTeams/index.js +42 -2
- package/dist/services/agentTeams/index.js.map +2 -2
- package/dist/services/agentTeams/injectionChannel.js +105 -0
- package/dist/services/agentTeams/injectionChannel.js.map +7 -0
- package/dist/services/agentTeams/mailbox.js +410 -30
- package/dist/services/agentTeams/mailbox.js.map +2 -2
- package/dist/services/agentTeams/messageFormatter.js +80 -0
- package/dist/services/agentTeams/messageFormatter.js.map +7 -0
- package/dist/services/agentTeams/permissionDelegation.js +71 -0
- package/dist/services/agentTeams/permissionDelegation.js.map +7 -0
- package/dist/services/agentTeams/teamEvents.js +45 -0
- package/dist/services/agentTeams/teamEvents.js.map +7 -0
- package/dist/services/agentTeams/teamManager.js +251 -34
- package/dist/services/agentTeams/teamManager.js.map +2 -2
- package/dist/services/agentTeams/teamTaskStore.js +290 -61
- package/dist/services/agentTeams/teamTaskStore.js.map +2 -2
- package/dist/services/agentTeams/teammateSpawner.js +99 -18
- package/dist/services/agentTeams/teammateSpawner.js.map +2 -2
- package/dist/services/hookExecutor.js +51 -8
- package/dist/services/hookExecutor.js.map +2 -2
- package/dist/services/llm/anthropicProvider.js +56 -59
- package/dist/services/llm/anthropicProvider.js.map +2 -2
- package/dist/services/llm/dispatch.js +24 -5
- package/dist/services/llm/dispatch.js.map +2 -2
- package/dist/services/llm/openaiProvider.js +115 -136
- package/dist/services/llm/openaiProvider.js.map +3 -3
- package/dist/services/llm/types.js +89 -15
- package/dist/services/llm/types.js.map +2 -2
- package/dist/services/mcpClient.js +80 -4
- package/dist/services/mcpClient.js.map +2 -2
- package/dist/services/mintoAuth.js +299 -0
- package/dist/services/mintoAuth.js.map +7 -0
- package/dist/services/oauth.js +3 -3
- package/dist/services/oauth.js.map +2 -2
- package/dist/services/openai.js +91 -20
- package/dist/services/openai.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +11 -5
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +4 -2
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/sandbox/sandboxController.js +11 -3
- package/dist/services/sandbox/sandboxController.js.map +2 -2
- package/dist/services/sessionMemoryInjector.js +77 -0
- package/dist/services/sessionMemoryInjector.js.map +7 -0
- package/dist/services/systemReminder.js +130 -8
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/services/taskStore.js +199 -8
- package/dist/services/taskStore.js.map +3 -3
- package/dist/services/topicDetector.js +169 -0
- package/dist/services/topicDetector.js.map +7 -0
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js +0 -13
- package/dist/tools/AskExpertModelTool/AskExpertModelTool.js.map +2 -2
- package/dist/tools/BashTool/BashTool.js +51 -28
- package/dist/tools/BashTool/BashTool.js.map +2 -2
- package/dist/tools/BashTool/prompt.js +95 -118
- package/dist/tools/BashTool/prompt.js.map +2 -2
- package/dist/tools/BashTool/utils.js +39 -1
- package/dist/tools/BashTool/utils.js.map +2 -2
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js +121 -0
- package/dist/tools/EnterWorktreeTool/EnterWorktreeTool.js.map +7 -0
- package/dist/tools/EnterWorktreeTool/prompt.js +22 -0
- package/dist/tools/EnterWorktreeTool/prompt.js.map +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js +9 -4
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileEditTool/prompt.js +3 -7
- package/dist/tools/FileEditTool/prompt.js.map +2 -2
- package/dist/tools/FileReadTool/FileReadTool.js +125 -3
- package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
- package/dist/tools/FileReadTool/prompt.js +1 -2
- package/dist/tools/FileReadTool/prompt.js.map +2 -2
- package/dist/tools/FileWriteTool/prompt.js +3 -5
- package/dist/tools/FileWriteTool/prompt.js.map +2 -2
- package/dist/tools/GlobTool/GlobTool.js +3 -2
- package/dist/tools/GlobTool/GlobTool.js.map +2 -2
- package/dist/tools/GrepTool/GrepTool.js +16 -5
- package/dist/tools/GrepTool/GrepTool.js.map +2 -2
- package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
- package/dist/tools/MCPSearchTool/MCPSearchTool.js +172 -0
- package/dist/tools/MCPSearchTool/MCPSearchTool.js.map +7 -0
- package/dist/tools/MCPSearchTool/prompt.js +77 -0
- package/dist/tools/MCPSearchTool/prompt.js.map +7 -0
- package/dist/tools/MultiEditTool/prompt.js +4 -7
- package/dist/tools/MultiEditTool/prompt.js.map +2 -2
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js +12 -8
- package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js +54 -1
- package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
- package/dist/tools/PlanModeTool/prompt.js +23 -74
- package/dist/tools/PlanModeTool/prompt.js.map +2 -2
- package/dist/tools/SendMessageTool/SendMessageTool.js +341 -0
- package/dist/tools/SendMessageTool/SendMessageTool.js.map +7 -0
- package/dist/tools/SendMessageTool/prompt.js +44 -0
- package/dist/tools/SendMessageTool/prompt.js.map +7 -0
- package/dist/tools/TaskCreateTool/prompt.js +15 -4
- package/dist/tools/TaskCreateTool/prompt.js.map +2 -2
- package/dist/tools/TaskListTool/prompt.js +18 -3
- package/dist/tools/TaskListTool/prompt.js.map +2 -2
- package/dist/tools/TaskOutputTool/prompt.js +4 -3
- package/dist/tools/TaskOutputTool/prompt.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +762 -98
- package/dist/tools/TaskTool/TaskTool.js.map +3 -3
- package/dist/tools/TaskTool/constants.js +8 -2
- package/dist/tools/TaskTool/constants.js.map +2 -2
- package/dist/tools/TaskTool/prompt.js +74 -70
- package/dist/tools/TaskTool/prompt.js.map +2 -2
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js +15 -1
- package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +2 -2
- package/dist/tools/TeamCreateTool/TeamCreateTool.js +129 -0
- package/dist/tools/TeamCreateTool/TeamCreateTool.js.map +7 -0
- package/dist/tools/TeamCreateTool/prompt.js +58 -0
- package/dist/tools/TeamCreateTool/prompt.js.map +7 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js +151 -0
- package/dist/tools/TeamDeleteTool/TeamDeleteTool.js.map +7 -0
- package/dist/tools/TeamDeleteTool/prompt.js +16 -0
- package/dist/tools/TeamDeleteTool/prompt.js.map +7 -0
- package/dist/tools/URLFetcherTool/URLFetcherTool.js +106 -15
- package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +3 -2
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/WebSearchTool.js +2 -1
- package/dist/tools/WebSearchTool/WebSearchTool.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +5 -4
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/tools.js +100 -20
- package/dist/tools.js.map +2 -2
- package/dist/types/PermissionMode.js +35 -6
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/hooks.js +2 -0
- package/dist/types/hooks.js.map +2 -2
- package/dist/types/plugin.js +2 -0
- package/dist/types/plugin.js.map +3 -3
- package/dist/utils/CircuitBreaker.js +15 -9
- package/dist/utils/CircuitBreaker.js.map +2 -2
- package/dist/utils/agentLoader.js +249 -112
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/animationManager.js +40 -3
- package/dist/utils/animationManager.js.map +2 -2
- package/dist/utils/ask.js +7 -6
- package/dist/utils/ask.js.map +2 -2
- package/dist/utils/atomicWrite.js +23 -0
- package/dist/utils/atomicWrite.js.map +7 -0
- package/dist/utils/autoCompactCore.js +73 -56
- package/dist/utils/autoCompactCore.js.map +2 -2
- package/dist/utils/autoMemoryPaths.js +89 -0
- package/dist/utils/autoMemoryPaths.js.map +7 -0
- package/dist/utils/config.js +63 -38
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configSchema.js +13 -8
- package/dist/utils/configSchema.js.map +2 -2
- package/dist/utils/credentials/index.js +14 -0
- package/dist/utils/credentials/index.js.map +2 -2
- package/dist/utils/dualPath.js +24 -0
- package/dist/utils/dualPath.js.map +7 -0
- package/dist/utils/exit.js +66 -7
- package/dist/utils/exit.js.map +2 -2
- package/dist/utils/externalEditor.js +155 -0
- package/dist/utils/externalEditor.js.map +7 -0
- package/dist/utils/fileLock.js +67 -0
- package/dist/utils/fileLock.js.map +7 -0
- package/dist/utils/format.js +24 -14
- package/dist/utils/format.js.map +2 -2
- package/dist/utils/globalErrorHandler.js +5 -96
- package/dist/utils/globalErrorHandler.js.map +3 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js +5 -3
- package/dist/utils/groupHandlers/parallelTasksHandler.js.map +2 -2
- package/dist/utils/groupHandlers/taskHandler.js +2 -2
- package/dist/utils/groupHandlers/taskHandler.js.map +2 -2
- package/dist/utils/hookManager.js +64 -6
- package/dist/utils/hookManager.js.map +2 -2
- package/dist/utils/log.js +6 -2
- package/dist/utils/log.js.map +2 -2
- package/dist/utils/markdown.js +237 -19
- package/dist/utils/markdown.js.map +2 -2
- package/dist/utils/messageContextManager.js +18 -5
- package/dist/utils/messageContextManager.js.map +2 -2
- package/dist/utils/messageGroupManager.js +1 -1
- package/dist/utils/messageGroupManager.js.map +2 -2
- package/dist/utils/messages.js +104 -46
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/model.js +2 -2
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pasteCache.js +8 -4
- package/dist/utils/pasteCache.js.map +2 -2
- package/dist/utils/pluginLoader.js +18 -0
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/secureKeyStorage.js +36 -7
- package/dist/utils/secureKeyStorage.js.map +2 -2
- package/dist/utils/simpleMode.js +7 -0
- package/dist/utils/simpleMode.js.map +7 -0
- package/dist/utils/streamingState.js +11 -1
- package/dist/utils/streamingState.js.map +2 -2
- package/dist/utils/taskDisplayUtils.js +2 -1
- package/dist/utils/taskDisplayUtils.js.map +2 -2
- package/dist/utils/teamConfig.js +2 -2
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/thinking.js +6 -2
- package/dist/utils/thinking.js.map +3 -3
- package/dist/utils/tokenProgress.js +55 -0
- package/dist/utils/tokenProgress.js.map +7 -0
- package/dist/utils/toolRiskClassification.js +26 -17
- package/dist/utils/toolRiskClassification.js.map +2 -2
- package/dist/utils/tooling/toolError.js +12 -0
- package/dist/utils/tooling/toolError.js.map +7 -0
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +10 -8
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, appendFileSync } from "fs";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { homedir } from "os";
|
|
4
1
|
import { countTokens } from "./tokens.js";
|
|
5
2
|
import { getMessagesSetter } from "../messages.js";
|
|
6
3
|
import { getContext } from "../context.js";
|
|
@@ -15,13 +12,14 @@ import { getCompressionPrompt } from "../constants/compressionPrompts.js";
|
|
|
15
12
|
import { getCompressionMode } from "./compressionMode.js";
|
|
16
13
|
import { getHookManager } from "./hookManager.js";
|
|
17
14
|
import { emitReminderEvent } from "../services/systemReminder.js";
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
|
|
15
|
+
import { createSessionMemory } from "../services/sessionMemory.js";
|
|
16
|
+
import { resetSessionMemoryCache } from "../services/sessionMemoryInjector.js";
|
|
17
|
+
import { clearAgentCache } from "./agentLoader.js";
|
|
18
|
+
const AUTO_COMPACT_THRESHOLD_RATIO = 0.835;
|
|
21
19
|
async function getCompressionModelContextLimit() {
|
|
22
20
|
try {
|
|
23
21
|
const modelManager = getModelManager();
|
|
24
|
-
const modelProfile = modelManager.getModel("main");
|
|
22
|
+
const modelProfile = modelManager.getModel("compact") ?? modelManager.getModel("main");
|
|
25
23
|
if (modelProfile?.contextLength) {
|
|
26
24
|
return modelProfile.contextLength;
|
|
27
25
|
}
|
|
@@ -69,52 +67,6 @@ async function checkAutoCompact(messages, toolUseContext) {
|
|
|
69
67
|
return { messages, wasCompacted: false };
|
|
70
68
|
}
|
|
71
69
|
}
|
|
72
|
-
const REMEMBER_PATTERNS = [
|
|
73
|
-
/\bremember\s+(this|that)\b/i,
|
|
74
|
-
/\balways\s+(use|do|prefer|avoid|skip)\b/i,
|
|
75
|
-
/\bnever\s+(use|do|commit|push|deploy)\b/i,
|
|
76
|
-
/\bfrom\s+now\s+on\b/i,
|
|
77
|
-
/\bin\s+the\s+future\b/i,
|
|
78
|
-
/\bgoing\s+forward\b/i,
|
|
79
|
-
/\bkeep\s+in\s+mind\b/i,
|
|
80
|
-
/\bdon'?t\s+forget\b/i
|
|
81
|
-
];
|
|
82
|
-
function extractAutoMemory(messages) {
|
|
83
|
-
try {
|
|
84
|
-
const config = getGlobalConfig();
|
|
85
|
-
if (!config.autoMemory) return;
|
|
86
|
-
const memories = [];
|
|
87
|
-
for (const msg of messages) {
|
|
88
|
-
if (msg.type !== "user") continue;
|
|
89
|
-
const content = msg.message.content;
|
|
90
|
-
const text = typeof content === "string" ? content : Array.isArray(content) ? content.filter((b) => b.type === "text").map((b) => b.text).join("\n") : "";
|
|
91
|
-
if (!text) continue;
|
|
92
|
-
const matchesPattern = REMEMBER_PATTERNS.some((p) => p.test(text));
|
|
93
|
-
if (matchesPattern) {
|
|
94
|
-
const lines = text.split("\n");
|
|
95
|
-
for (const line of lines) {
|
|
96
|
-
const trimmed = line.trim();
|
|
97
|
-
if (trimmed && REMEMBER_PATTERNS.some((p) => p.test(trimmed))) {
|
|
98
|
-
memories.push(trimmed);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
if (memories.length === 0) return;
|
|
104
|
-
const autoMemoryDir = join(homedir(), CONFIG_BASE_DIR);
|
|
105
|
-
const autoMemoryPath = join(autoMemoryDir, "auto-memory.md");
|
|
106
|
-
if (!existsSync(autoMemoryDir)) {
|
|
107
|
-
mkdirSync(autoMemoryDir, { recursive: true });
|
|
108
|
-
}
|
|
109
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
110
|
-
const entry = `
|
|
111
|
-
## ${timestamp}
|
|
112
|
-
${memories.map((m) => `- ${m}`).join("\n")}
|
|
113
|
-
`;
|
|
114
|
-
appendFileSync(autoMemoryPath, entry, "utf-8");
|
|
115
|
-
} catch {
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
70
|
async function executeAutoCompact(messages, toolUseContext) {
|
|
119
71
|
const compressionMode = getCompressionMode();
|
|
120
72
|
const compressionPrompt = getCompressionPrompt(compressionMode);
|
|
@@ -129,8 +81,8 @@ async function executeAutoCompact(messages, toolUseContext) {
|
|
|
129
81
|
toolUseContext.abortController.signal,
|
|
130
82
|
{
|
|
131
83
|
safeMode: false,
|
|
132
|
-
model: "
|
|
133
|
-
//
|
|
84
|
+
model: "compact",
|
|
85
|
+
// Use compact model pointer for cheaper compression
|
|
134
86
|
prependCLISysprompt: true
|
|
135
87
|
}
|
|
136
88
|
);
|
|
@@ -173,11 +125,76 @@ ${contentWithLines}
|
|
|
173
125
|
emitReminderEvent("compact:file_reference", { filePath: file.path });
|
|
174
126
|
}
|
|
175
127
|
}
|
|
176
|
-
|
|
128
|
+
try {
|
|
129
|
+
const cwd = process.cwd();
|
|
130
|
+
const sessionMemory = createSessionMemory(cwd);
|
|
131
|
+
const decisions = [];
|
|
132
|
+
const focusAreas = [];
|
|
133
|
+
const codeChanges = [];
|
|
134
|
+
const lines = summary.split("\n");
|
|
135
|
+
for (const line of lines) {
|
|
136
|
+
const trimmed = line.trim();
|
|
137
|
+
if (/^[-*]\s*(decided|chose|agreed|will use|switched to)/i.test(trimmed)) {
|
|
138
|
+
decisions.push({
|
|
139
|
+
description: trimmed.replace(/^[-*]\s*/, ""),
|
|
140
|
+
rationale: "",
|
|
141
|
+
messageIndex: 0,
|
|
142
|
+
importance: 0.5
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
if (/^[-*]\s*(modified|created|updated|deleted|edited|refactored)/i.test(
|
|
146
|
+
trimmed
|
|
147
|
+
)) {
|
|
148
|
+
const desc = trimmed.replace(/^[-*]\s*/, "");
|
|
149
|
+
const changeType = /^(created|create)/i.test(desc) ? "create" : /^(deleted|delete|removed)/i.test(desc) ? "delete" : "modify";
|
|
150
|
+
codeChanges.push({
|
|
151
|
+
filePath: "",
|
|
152
|
+
changeType,
|
|
153
|
+
description: desc,
|
|
154
|
+
messageIndex: 0
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (/^[-*]\s*(working on|focusing on|investigating|implementing)/i.test(
|
|
158
|
+
trimmed
|
|
159
|
+
)) {
|
|
160
|
+
focusAreas.push(trimmed.replace(/^[-*]\s*/, ""));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
sessionMemory.saveMemory(
|
|
164
|
+
{
|
|
165
|
+
summary,
|
|
166
|
+
decisions,
|
|
167
|
+
codeChanges,
|
|
168
|
+
toolUsageSummary: {},
|
|
169
|
+
focusAreas,
|
|
170
|
+
preservedContext: []
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
projectPath: cwd,
|
|
174
|
+
messageCount: messages.length,
|
|
175
|
+
compressedAt: Date.now()
|
|
176
|
+
}
|
|
177
|
+
);
|
|
178
|
+
resetSessionMemoryCache();
|
|
179
|
+
} catch {
|
|
180
|
+
}
|
|
177
181
|
getMessagesSetter()([]);
|
|
178
182
|
getContext.cache.clear?.();
|
|
179
183
|
getCodeStyle.cache.clear?.();
|
|
180
184
|
resetFileFreshnessSession();
|
|
185
|
+
clearAgentCache();
|
|
186
|
+
const MAX_FILE_TIMESTAMPS = 200;
|
|
187
|
+
const timestamps = toolUseContext?.readFileTimestamps;
|
|
188
|
+
if (timestamps && typeof timestamps === "object") {
|
|
189
|
+
const entries = Object.entries(timestamps);
|
|
190
|
+
if (entries.length > MAX_FILE_TIMESTAMPS) {
|
|
191
|
+
entries.sort(([, a], [, b]) => b - a);
|
|
192
|
+
const toRemove = entries.slice(MAX_FILE_TIMESTAMPS);
|
|
193
|
+
for (const [key] of toRemove) {
|
|
194
|
+
delete timestamps[key];
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
181
198
|
return compactedMessages;
|
|
182
199
|
}
|
|
183
200
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/autoCompactCore.ts"],
|
|
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": "
|
|
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 { 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'\n\n/**\n * Minimal context interface for auto-compact operations.\n * Subset of ToolUseContext needed for compression.\n * Uses structural typing to accept any object with these fields.\n */\ntype CompactToolUseContext = {\n options: {\n tools?: any[]\n safetyMode?: string\n } & Record<string, unknown>\n abortController: AbortController\n readFileTimestamps?: Record<string, number>\n}\nimport { createSessionMemory } from '@services/sessionMemory'\nimport { resetSessionMemoryCache } from '@services/sessionMemoryInjector'\nimport { clearAgentCache } from './agentLoader'\n\n/**\n * Threshold ratio for triggering automatic context compression.\n * Match Claude Code's ~83.5% threshold. Reserve 33-45K tokens buffer\n * for the compression process itself (summary generation + file recovery).\n */\nconst AUTO_COMPACT_THRESHOLD_RATIO = 0.835\n\n/**\n * Retrieves the context length for the compact model used for compression.\n * Uses the compact model pointer (with fallback chain: compact -> quick -> task -> main).\n */\nasync function getCompressionModelContextLimit(): Promise<number> {\n try {\n const modelManager = getModelManager()\n // Use compact model profile for compression context limit\n const modelProfile =\n modelManager.getModel('compact') ?? 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: CompactToolUseContext,\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 * 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: CompactToolUseContext,\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: 'compact', // Use compact model pointer for cheaper compression\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 // Save session memory for persistence across sessions\n try {\n const cwd = process.cwd()\n const sessionMemory = createSessionMemory(cwd)\n\n // Extract structured data from the summary rather than saving empty arrays\n const decisions: Array<{\n description: string\n rationale: string\n messageIndex: number\n importance: number\n }> = []\n const focusAreas: string[] = []\n const codeChanges: Array<{\n filePath: string\n changeType: 'create' | 'modify' | 'delete' | 'rename'\n description: string\n messageIndex: number\n }> = []\n\n // Parse decisions and focus areas from the summary text\n const lines = summary.split('\\n')\n for (const line of lines) {\n const trimmed = line.trim()\n if (\n /^[-*]\\s*(decided|chose|agreed|will use|switched to)/i.test(trimmed)\n ) {\n decisions.push({\n description: trimmed.replace(/^[-*]\\s*/, ''),\n rationale: '',\n messageIndex: 0,\n importance: 0.5,\n })\n }\n if (\n /^[-*]\\s*(modified|created|updated|deleted|edited|refactored)/i.test(\n trimmed,\n )\n ) {\n const desc = trimmed.replace(/^[-*]\\s*/, '')\n const changeType = /^(created|create)/i.test(desc)\n ? ('create' as const)\n : /^(deleted|delete|removed)/i.test(desc)\n ? ('delete' as const)\n : ('modify' as const)\n codeChanges.push({\n filePath: '',\n changeType,\n description: desc,\n messageIndex: 0,\n })\n }\n if (\n /^[-*]\\s*(working on|focusing on|investigating|implementing)/i.test(\n trimmed,\n )\n ) {\n focusAreas.push(trimmed.replace(/^[-*]\\s*/, ''))\n }\n }\n\n sessionMemory.saveMemory(\n {\n summary,\n decisions,\n codeChanges,\n toolUsageSummary: {},\n focusAreas,\n preservedContext: [],\n },\n {\n projectPath: cwd,\n messageCount: messages.length,\n compressedAt: Date.now(),\n },\n )\n // Reset the injector cache so next session picks up this new memory\n resetSessionMemoryCache()\n } catch {\n // Non-critical: session memory save failure should not block compression\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 clearAgentCache()\n\n // Cap readFileTimestamps to prevent unbounded memory growth\n // Keep the most recent entries so file freshness tracking remains useful\n const MAX_FILE_TIMESTAMPS = 200\n const timestamps = toolUseContext?.readFileTimestamps\n if (timestamps && typeof timestamps === 'object') {\n const entries = Object.entries(timestamps)\n if (entries.length > MAX_FILE_TIMESTAMPS) {\n entries.sort(([, a], [, b]) => (b as number) - (a as number))\n const toRemove = entries.slice(MAX_FILE_TIMESTAMPS)\n for (const [key] of toRemove) {\n delete timestamps[key]\n }\n }\n }\n\n return compactedMessages\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { join } from "path";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync } from "fs";
|
|
4
|
+
import { spawnSync } from "child_process";
|
|
5
|
+
import { CONFIG_BASE_DIR } from "../constants/product.js";
|
|
6
|
+
import { getOriginalCwd } from "./state.js";
|
|
7
|
+
import { getGlobalConfig } from "./config.js";
|
|
8
|
+
function getProjectSlug(projectRoot) {
|
|
9
|
+
return projectRoot.replace(/[^a-zA-Z0-9]/g, "-");
|
|
10
|
+
}
|
|
11
|
+
let _cachedGitRoot;
|
|
12
|
+
function getGitRootSync() {
|
|
13
|
+
if (_cachedGitRoot !== void 0) return _cachedGitRoot;
|
|
14
|
+
try {
|
|
15
|
+
const result = spawnSync("git", ["rev-parse", "--show-toplevel"], {
|
|
16
|
+
encoding: "utf-8",
|
|
17
|
+
timeout: 3e3,
|
|
18
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
19
|
+
});
|
|
20
|
+
_cachedGitRoot = result.status === 0 ? result.stdout.trim() : null;
|
|
21
|
+
} catch {
|
|
22
|
+
_cachedGitRoot = null;
|
|
23
|
+
}
|
|
24
|
+
return _cachedGitRoot;
|
|
25
|
+
}
|
|
26
|
+
function getProjectRoot(cwd) {
|
|
27
|
+
if (cwd) return cwd;
|
|
28
|
+
const gitRoot = getGitRootSync();
|
|
29
|
+
return gitRoot ?? getOriginalCwd();
|
|
30
|
+
}
|
|
31
|
+
function getAutoMemoryDir(cwd) {
|
|
32
|
+
const projectRoot = getProjectRoot(cwd);
|
|
33
|
+
const slug = getProjectSlug(projectRoot);
|
|
34
|
+
return join(homedir(), CONFIG_BASE_DIR, "projects", slug, "memory");
|
|
35
|
+
}
|
|
36
|
+
function ensureAutoMemoryDir(cwd) {
|
|
37
|
+
const dir = getAutoMemoryDir(cwd);
|
|
38
|
+
if (!existsSync(dir)) {
|
|
39
|
+
mkdirSync(dir, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
return dir;
|
|
42
|
+
}
|
|
43
|
+
function isAutoMemoryEnabled() {
|
|
44
|
+
if (process.env.MINTO_DISABLE_AUTO_MEMORY === "1" || process.env.CLAUDE_CODE_DISABLE_AUTO_MEMORY === "1") {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
const config = getGlobalConfig();
|
|
48
|
+
return config.autoMemory !== false;
|
|
49
|
+
}
|
|
50
|
+
function readMemoryMd(cwd) {
|
|
51
|
+
const projectRoot = getProjectRoot(cwd);
|
|
52
|
+
const slug = getProjectSlug(projectRoot);
|
|
53
|
+
const home = homedir();
|
|
54
|
+
const mintoPath = join(
|
|
55
|
+
home,
|
|
56
|
+
CONFIG_BASE_DIR,
|
|
57
|
+
"projects",
|
|
58
|
+
slug,
|
|
59
|
+
"memory",
|
|
60
|
+
"MEMORY.md"
|
|
61
|
+
);
|
|
62
|
+
const claudePath = join(
|
|
63
|
+
home,
|
|
64
|
+
".claude",
|
|
65
|
+
"projects",
|
|
66
|
+
slug,
|
|
67
|
+
"memory",
|
|
68
|
+
"MEMORY.md"
|
|
69
|
+
);
|
|
70
|
+
const filePath = existsSync(mintoPath) ? mintoPath : existsSync(claudePath) ? claudePath : null;
|
|
71
|
+
if (!filePath) return null;
|
|
72
|
+
try {
|
|
73
|
+
const content = readFileSync(filePath, "utf-8");
|
|
74
|
+
const lines = content.split("\n");
|
|
75
|
+
if (lines.length > 200) {
|
|
76
|
+
return lines.slice(0, 200).join("\n");
|
|
77
|
+
}
|
|
78
|
+
return content;
|
|
79
|
+
} catch {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export {
|
|
84
|
+
ensureAutoMemoryDir,
|
|
85
|
+
getAutoMemoryDir,
|
|
86
|
+
isAutoMemoryEnabled,
|
|
87
|
+
readMemoryMd
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=autoMemoryPaths.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/autoMemoryPaths.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Auto Memory path utilities.\n *\n * CC-compatible per-project memory directory:\n * ~/.minto/projects/<project-slug>/memory/\n * (reads also check ~/.claude/projects/<project-slug>/memory/ as fallback)\n *\n * Project slug: project root path with non-alphanumeric chars replaced by '-'\n * Same format as CC's ~/.claude/projects/ directory structure.\n *\n * CC uses the git repository root to determine the project. If not in a git\n * repo, the working directory is used.\n */\n\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { existsSync, mkdirSync, readFileSync } from 'fs'\nimport { spawnSync } from 'child_process'\nimport { CONFIG_BASE_DIR } from '@constants/product'\nimport { getOriginalCwd } from './state'\nimport { getGlobalConfig } from './config'\n\n/**\n * Convert a path to a project slug (CC-compatible).\n * e.g., /Users/lib/Desktop/project \u2192 -Users-lib-Desktop-project\n */\nfunction getProjectSlug(projectRoot: string): string {\n return projectRoot.replace(/[^a-zA-Z0-9]/g, '-')\n}\n\n/**\n * Get the git repository root synchronously.\n * Returns null if not in a git repo.\n */\nlet _cachedGitRoot: string | null | undefined\nfunction getGitRootSync(): string | null {\n if (_cachedGitRoot !== undefined) return _cachedGitRoot\n try {\n const result = spawnSync('git', ['rev-parse', '--show-toplevel'], {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n })\n _cachedGitRoot = result.status === 0 ? result.stdout.trim() : null\n } catch {\n _cachedGitRoot = null\n }\n return _cachedGitRoot\n}\n\n/**\n * Get the project root path for memory directory scoping.\n * Uses git repo root if available, otherwise the original CWD.\n */\nfunction getProjectRoot(cwd?: string): string {\n if (cwd) return cwd\n // CC behavior: use git repo root if in a git repo\n const gitRoot = getGitRootSync()\n return gitRoot ?? getOriginalCwd()\n}\n\n/**\n * Get the per-project memory directory path (Minto primary).\n */\nexport function getAutoMemoryDir(cwd?: string): string {\n const projectRoot = getProjectRoot(cwd)\n const slug = getProjectSlug(projectRoot)\n return join(homedir(), CONFIG_BASE_DIR, 'projects', slug, 'memory')\n}\n\n/**\n * Ensure the auto memory directory exists, creating it if needed.\n */\nexport function ensureAutoMemoryDir(cwd?: string): string {\n const dir = getAutoMemoryDir(cwd)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true })\n }\n return dir\n}\n\n/**\n * Check if auto memory is enabled.\n * Default: true (matches CC behavior).\n * Can be disabled via config `autoMemory: false` or env `MINTO_DISABLE_AUTO_MEMORY=1`.\n */\nexport function isAutoMemoryEnabled(): boolean {\n // Environment variable override (CC uses CLAUDE_CODE_DISABLE_AUTO_MEMORY=1)\n if (\n process.env.MINTO_DISABLE_AUTO_MEMORY === '1' ||\n process.env.CLAUDE_CODE_DISABLE_AUTO_MEMORY === '1'\n ) {\n return false\n }\n\n const config = getGlobalConfig()\n // autoMemory defaults to true when not explicitly set (CC default)\n return config.autoMemory !== false\n}\n\n/**\n * Read MEMORY.md content from the per-project memory directory.\n * Checks Minto path first, then Claude Code fallback path.\n * Returns first 200 lines (CC truncation behavior).\n */\nexport function readMemoryMd(cwd?: string): string | null {\n const projectRoot = getProjectRoot(cwd)\n const slug = getProjectSlug(projectRoot)\n const home = homedir()\n\n // Primary: ~/.minto/projects/<slug>/memory/MEMORY.md\n const mintoPath = join(\n home,\n CONFIG_BASE_DIR,\n 'projects',\n slug,\n 'memory',\n 'MEMORY.md',\n )\n // Fallback: ~/.claude/projects/<slug>/memory/MEMORY.md\n const claudePath = join(\n home,\n '.claude',\n 'projects',\n slug,\n 'memory',\n 'MEMORY.md',\n )\n\n const filePath = existsSync(mintoPath)\n ? mintoPath\n : existsSync(claudePath)\n ? claudePath\n : null\n\n if (!filePath) return null\n\n try {\n const content = readFileSync(filePath, 'utf-8')\n // Truncate to first 200 lines (CC behavior)\n const lines = content.split('\\n')\n if (lines.length > 200) {\n return lines.slice(0, 200).join('\\n')\n }\n return content\n } catch {\n return null\n }\n}\n"],
|
|
5
|
+
"mappings": "AAcA,SAAS,YAAY;AACrB,SAAS,eAAe;AACxB,SAAS,YAAY,WAAW,oBAAoB;AACpD,SAAS,iBAAiB;AAC1B,SAAS,uBAAuB;AAChC,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAMhC,SAAS,eAAe,aAA6B;AACnD,SAAO,YAAY,QAAQ,iBAAiB,GAAG;AACjD;AAMA,IAAI;AACJ,SAAS,iBAAgC;AACvC,MAAI,mBAAmB,OAAW,QAAO;AACzC,MAAI;AACF,UAAM,SAAS,UAAU,OAAO,CAAC,aAAa,iBAAiB,GAAG;AAAA,MAChE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,OAAO,CAAC,QAAQ,QAAQ,MAAM;AAAA,IAChC,CAAC;AACD,qBAAiB,OAAO,WAAW,IAAI,OAAO,OAAO,KAAK,IAAI;AAAA,EAChE,QAAQ;AACN,qBAAiB;AAAA,EACnB;AACA,SAAO;AACT;AAMA,SAAS,eAAe,KAAsB;AAC5C,MAAI,IAAK,QAAO;AAEhB,QAAM,UAAU,eAAe;AAC/B,SAAO,WAAW,eAAe;AACnC;AAKO,SAAS,iBAAiB,KAAsB;AACrD,QAAM,cAAc,eAAe,GAAG;AACtC,QAAM,OAAO,eAAe,WAAW;AACvC,SAAO,KAAK,QAAQ,GAAG,iBAAiB,YAAY,MAAM,QAAQ;AACpE;AAKO,SAAS,oBAAoB,KAAsB;AACxD,QAAM,MAAM,iBAAiB,GAAG;AAChC,MAAI,CAAC,WAAW,GAAG,GAAG;AACpB,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AACA,SAAO;AACT;AAOO,SAAS,sBAA+B;AAE7C,MACE,QAAQ,IAAI,8BAA8B,OAC1C,QAAQ,IAAI,oCAAoC,KAChD;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,gBAAgB;AAE/B,SAAO,OAAO,eAAe;AAC/B;AAOO,SAAS,aAAa,KAA6B;AACxD,QAAM,cAAc,eAAe,GAAG;AACtC,QAAM,OAAO,eAAe,WAAW;AACvC,QAAM,OAAO,QAAQ;AAGrB,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,aAAa;AAAA,IACjB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,WAAW,WAAW,SAAS,IACjC,YACA,WAAW,UAAU,IACnB,aACA;AAEN,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI;AACF,UAAM,UAAU,aAAa,UAAU,OAAO;AAE9C,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAI,MAAM,SAAS,KAAK;AACtB,aAAO,MAAM,MAAM,GAAG,GAAG,EAAE,KAAK,IAAI;AAAA,IACtC;AACA,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/utils/config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, readFileSync,
|
|
2
|
-
import { resolve, join
|
|
1
|
+
import { existsSync, readFileSync, statSync } from "fs";
|
|
2
|
+
import { resolve, join } from "path";
|
|
3
3
|
import { cloneDeep, memoize, pick } from "lodash-es";
|
|
4
4
|
import { homedir } from "os";
|
|
5
5
|
import { GLOBAL_CONFIG_FILE } from "./env.js";
|
|
@@ -41,6 +41,10 @@ function getVerboseLabel(verbose) {
|
|
|
41
41
|
return verbose ? "Verbose: On" : "Verbose: Off";
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
function _assertGlobalConfigAlignment() {
|
|
45
|
+
const _check1 = {};
|
|
46
|
+
const _check2 = {};
|
|
47
|
+
}
|
|
44
48
|
const DEFAULT_GLOBAL_CONFIG = {
|
|
45
49
|
numStartups: 0,
|
|
46
50
|
autoUpdaterStatus: "not_configured",
|
|
@@ -86,12 +90,21 @@ const GLOBAL_CONFIG_KEYS = [
|
|
|
86
90
|
"preferredNotifChannel",
|
|
87
91
|
"shiftEnterKeyBindingInstalled",
|
|
88
92
|
"maxTokens",
|
|
93
|
+
"proxy",
|
|
94
|
+
"stream",
|
|
95
|
+
"thinking",
|
|
96
|
+
"backupEnabled",
|
|
89
97
|
"compressionMode",
|
|
90
98
|
"language",
|
|
91
99
|
"safetyMode",
|
|
92
100
|
"enableMemoryTools",
|
|
93
101
|
"outputStyle",
|
|
94
|
-
"autoMemory"
|
|
102
|
+
"autoMemory",
|
|
103
|
+
"enableAgentTeams",
|
|
104
|
+
"teammateMode",
|
|
105
|
+
"bashOutputSummarization",
|
|
106
|
+
"enableSessionMemory",
|
|
107
|
+
"enableTopicDetection"
|
|
95
108
|
];
|
|
96
109
|
function isGlobalConfigKey(key) {
|
|
97
110
|
return GLOBAL_CONFIG_KEYS.includes(key);
|
|
@@ -136,6 +149,8 @@ function saveGlobalConfig(config) {
|
|
|
136
149
|
}
|
|
137
150
|
return;
|
|
138
151
|
}
|
|
152
|
+
_cachedGlobalConfig = null;
|
|
153
|
+
_cachedMtimeMs = 0;
|
|
139
154
|
saveConfig(
|
|
140
155
|
GLOBAL_CONFIG_FILE,
|
|
141
156
|
{
|
|
@@ -163,13 +178,32 @@ function migrateDisplayModeToVerbose(config) {
|
|
|
163
178
|
verbose: false
|
|
164
179
|
};
|
|
165
180
|
}
|
|
181
|
+
function deepFreeze(obj) {
|
|
182
|
+
Object.freeze(obj);
|
|
183
|
+
for (const value of Object.values(obj)) {
|
|
184
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
185
|
+
deepFreeze(value);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return obj;
|
|
189
|
+
}
|
|
190
|
+
let _cachedGlobalConfig = null;
|
|
191
|
+
let _cachedMtimeMs = 0;
|
|
192
|
+
function getMutableGlobalConfig() {
|
|
193
|
+
return structuredClone(getGlobalConfig());
|
|
194
|
+
}
|
|
166
195
|
function getGlobalConfig() {
|
|
167
196
|
if (process.env.NODE_ENV === "test") {
|
|
168
197
|
return TEST_GLOBAL_CONFIG_FOR_TESTING;
|
|
169
198
|
}
|
|
199
|
+
const stat = statSync(GLOBAL_CONFIG_FILE, { throwIfNoEntry: false });
|
|
200
|
+
const currentMtime = stat?.mtimeMs ?? 0;
|
|
201
|
+
if (_cachedGlobalConfig && currentMtime === _cachedMtimeMs) {
|
|
202
|
+
return _cachedGlobalConfig;
|
|
203
|
+
}
|
|
170
204
|
const config = getConfig(GLOBAL_CONFIG_FILE, DEFAULT_GLOBAL_CONFIG);
|
|
171
|
-
|
|
172
|
-
|
|
205
|
+
let migratedConfig = migrateModelProfilesRemoveId(config);
|
|
206
|
+
let displayMigratedConfig = migrateDisplayModeToVerbose(migratedConfig);
|
|
173
207
|
if (displayMigratedConfig.modelProfiles && displayMigratedConfig.modelProfiles.length > 0) {
|
|
174
208
|
const originalCount = displayMigratedConfig.modelProfiles.length;
|
|
175
209
|
const deduplicatedProfiles = deduplicateModelProfiles(
|
|
@@ -194,14 +228,18 @@ function getGlobalConfig() {
|
|
|
194
228
|
},
|
|
195
229
|
DEFAULT_GLOBAL_CONFIG
|
|
196
230
|
);
|
|
197
|
-
|
|
231
|
+
_cachedGlobalConfig = deepFreeze(configToSave);
|
|
232
|
+
_cachedMtimeMs = statSync(GLOBAL_CONFIG_FILE, { throwIfNoEntry: false })?.mtimeMs ?? 0;
|
|
233
|
+
return _cachedGlobalConfig;
|
|
198
234
|
}
|
|
199
|
-
|
|
235
|
+
displayMigratedConfig = {
|
|
200
236
|
...displayMigratedConfig,
|
|
201
237
|
modelProfiles: deduplicatedProfiles
|
|
202
238
|
};
|
|
203
239
|
}
|
|
204
|
-
|
|
240
|
+
_cachedGlobalConfig = deepFreeze(displayMigratedConfig);
|
|
241
|
+
_cachedMtimeMs = currentMtime;
|
|
242
|
+
return _cachedGlobalConfig;
|
|
205
243
|
}
|
|
206
244
|
function getAnthropicApiKey() {
|
|
207
245
|
return process.env.ANTHROPIC_API_KEY || null;
|
|
@@ -219,23 +257,7 @@ function getCustomApiKeyStatus(truncatedApiKey) {
|
|
|
219
257
|
}
|
|
220
258
|
return "new";
|
|
221
259
|
}
|
|
222
|
-
|
|
223
|
-
const dir = dirname(filePath);
|
|
224
|
-
const tempPath = join(
|
|
225
|
-
dir,
|
|
226
|
-
`.${Date.now()}-${Math.random().toString(36).slice(2)}.tmp`
|
|
227
|
-
);
|
|
228
|
-
try {
|
|
229
|
-
writeFileSync(tempPath, content, "utf-8");
|
|
230
|
-
renameSync(tempPath, filePath);
|
|
231
|
-
} catch (error) {
|
|
232
|
-
try {
|
|
233
|
-
rmSync(tempPath, { force: true });
|
|
234
|
-
} catch {
|
|
235
|
-
}
|
|
236
|
-
throw error;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
260
|
+
import { atomicWriteFileSync } from "./atomicWrite.js";
|
|
239
261
|
function saveConfig(file, config, defaultConfig) {
|
|
240
262
|
const filteredConfig = Object.fromEntries(
|
|
241
263
|
Object.entries(config).filter(
|
|
@@ -292,12 +314,17 @@ function getConfig(file, defaultConfig, throwOnInvalid) {
|
|
|
292
314
|
file,
|
|
293
315
|
parsedKeys: Object.keys(parsedConfig).join(", ")
|
|
294
316
|
});
|
|
317
|
+
let validationWarnings;
|
|
295
318
|
if (file === GLOBAL_CONFIG_FILE) {
|
|
296
319
|
const validation = safeValidateGlobalConfig(parsedConfig);
|
|
297
320
|
if (!validation.success && validation.errors) {
|
|
298
|
-
|
|
321
|
+
const issues = validation.errors.issues.map(
|
|
322
|
+
(i) => `${i.path.join(".")}: ${i.message}`
|
|
323
|
+
);
|
|
324
|
+
validationWarnings = issues;
|
|
325
|
+
debugLogger.error("CONFIG_VALIDATION", {
|
|
299
326
|
file,
|
|
300
|
-
issues:
|
|
327
|
+
issues: issues.join("; ")
|
|
301
328
|
});
|
|
302
329
|
}
|
|
303
330
|
}
|
|
@@ -305,6 +332,10 @@ function getConfig(file, defaultConfig, throwOnInvalid) {
|
|
|
305
332
|
...cloneDeep(defaultConfig),
|
|
306
333
|
...parsedConfig
|
|
307
334
|
};
|
|
335
|
+
if (validationWarnings) {
|
|
336
|
+
;
|
|
337
|
+
finalConfig._validationWarnings = validationWarnings;
|
|
338
|
+
}
|
|
308
339
|
debugLogger.state("CONFIG_LOAD_SUCCESS", {
|
|
309
340
|
file,
|
|
310
341
|
finalConfigKeys: Object.keys(finalConfig).join(", ")
|
|
@@ -416,19 +447,12 @@ const getMcprcConfig = memoize(
|
|
|
416
447
|
}
|
|
417
448
|
return {};
|
|
418
449
|
},
|
|
419
|
-
//
|
|
450
|
+
// Cache key uses mtime instead of reading file content (avoids full I/O on every call)
|
|
420
451
|
() => {
|
|
421
452
|
const cwd = getCwd();
|
|
422
453
|
const mcprcPath = join(cwd, ".mcprc");
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
const stat = readFileSync(mcprcPath, "utf-8");
|
|
426
|
-
return `${cwd}:${stat}`;
|
|
427
|
-
} catch {
|
|
428
|
-
return cwd;
|
|
429
|
-
}
|
|
430
|
-
}
|
|
431
|
-
return cwd;
|
|
454
|
+
const mtime = statSync(mcprcPath, { throwIfNoEntry: false })?.mtimeMs;
|
|
455
|
+
return mtime != null ? `${cwd}:${mtime}` : cwd;
|
|
432
456
|
}
|
|
433
457
|
);
|
|
434
458
|
function getOrCreateUserID() {
|
|
@@ -503,7 +527,7 @@ function deleteConfigForCLI(key, global) {
|
|
|
503
527
|
);
|
|
504
528
|
process.exit(1);
|
|
505
529
|
}
|
|
506
|
-
const currentConfig = getGlobalConfig();
|
|
530
|
+
const currentConfig = structuredClone(getGlobalConfig());
|
|
507
531
|
delete currentConfig[key];
|
|
508
532
|
saveGlobalConfig(currentConfig);
|
|
509
533
|
} else {
|
|
@@ -668,6 +692,7 @@ export {
|
|
|
668
692
|
getGPT5ConfigRecommendations,
|
|
669
693
|
getGlobalConfig,
|
|
670
694
|
getMcprcConfig,
|
|
695
|
+
getMutableGlobalConfig,
|
|
671
696
|
getOpenAIApiKey,
|
|
672
697
|
getOrCreateUserID,
|
|
673
698
|
getVerboseLabel,
|