@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/hookManager.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Hook Manager\n *\n * Central manager for plugin hooks lifecycle.\n * Coordinates hook execution across the application.\n */\n\nimport { HookEvent } from '../types/hooks'\nimport { LoadedPlugin } from '../types/plugin'\nimport {\n executeHooksForEvent,\n processHookDecisions,\n createPreToolUseInput,\n createPostToolUseInput,\n createUserPromptSubmitInput,\n createSessionStartInput,\n createSessionEndInput,\n type HookExecutionOptions,\n type HookExecutionResult,\n} from '../services/hookExecutor'\nimport { logError } from './log'\n\n// Simple logging helpers\nconst logInfo = (msg: string) => {\n // Only log in debug mode to reduce noise\n if (process.env.DEBUG) console.log(`[INFO] ${msg}`)\n}\nconst logDebug = (msg: string, ...args: any[]) => {\n if (process.env.DEBUG) console.log(`[DEBUG] ${msg}`, ...args)\n}\n\n/**\n * Hook manager instance\n */\nexport class HookManager {\n private plugins: LoadedPlugin[] = []\n private sessionId: string\n private transcriptPath: string\n private enabled: boolean = true\n\n constructor(sessionId: string, transcriptPath: string) {\n this.sessionId = sessionId\n this.transcriptPath = transcriptPath\n }\n\n /**\n * Register plugins with hooks\n */\n registerPlugins(plugins: LoadedPlugin[]) {\n this.plugins = plugins\n const totalHooks = plugins.reduce((sum, p) => sum + p.hooks.length, 0)\n logInfo(\n `HookManager: Registered ${plugins.length} plugin(s) with ${totalHooks} hook(s)`,\n )\n }\n\n /**\n * Enable or disable hook execution\n */\n setEnabled(enabled: boolean) {\n this.enabled = enabled\n logDebug(`HookManager: ${enabled ? 'Enabled' : 'Disabled'}`)\n }\n\n /**\n * Execute PreToolUse hooks\n */\n async executePreToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n ): Promise<{\n shouldContinue: boolean\n shouldAskUser: boolean\n reason?: string\n }> {\n if (!this.enabled) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n // Collect all hooks across all plugins\n const allHooks = this.plugins.flatMap(p => p.hooks)\n\n // Filter hooks that match this tool\n const matchingHooks = allHooks.filter(hook => {\n if (hook.event !== HookEvent.PreToolUse) return false\n if (!hook.matcher) return true // No matcher means match all\n if (hook.matcher === '*' || hook.matcher === '') return true\n\n // Check if tool name matches the pattern\n try {\n const regex = new RegExp(hook.matcher)\n return regex.test(toolName)\n } catch {\n // If regex is invalid, try exact match\n return hook.matcher === toolName\n }\n })\n\n if (matchingHooks.length === 0) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n logDebug(\n `PreToolUse: ${matchingHooks.length} hook(s) matched for tool: ${toolName}`,\n )\n\n // Execute hooks\n const input = createPreToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n )\n\n const results: HookExecutionResult[] = []\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n const result = await executeHooksForEvent(\n HookEvent.PreToolUse,\n [hook],\n input,\n options,\n )\n\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n /**\n * Execute PostToolUse hooks\n */\n async executePostToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n toolOutput: Record<string, unknown>,\n ): Promise<void> {\n if (!this.enabled) {\n return\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n\n const matchingHooks = allHooks.filter(hook => {\n if (hook.event !== HookEvent.PostToolUse) return false\n if (!hook.matcher) return true\n if (hook.matcher === '*' || hook.matcher === '') return true\n\n try {\n const regex = new RegExp(hook.matcher)\n return regex.test(toolName)\n } catch {\n return hook.matcher === toolName\n }\n })\n\n if (matchingHooks.length === 0) {\n return\n }\n\n logDebug(\n `PostToolUse: ${matchingHooks.length} hook(s) matched for tool: ${toolName}`,\n )\n\n const input = createPostToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n toolOutput,\n )\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n // PostToolUse hooks don't affect workflow, just execute them\n await executeHooksForEvent(HookEvent.PostToolUse, [hook], input, options)\n }\n }\n\n /**\n * Execute UserPromptSubmit hooks\n */\n async executeUserPromptSubmit(userPrompt: string): Promise<{\n shouldContinue: boolean\n shouldAskUser: boolean\n reason?: string\n }> {\n if (!this.enabled) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n const matchingHooks = allHooks.filter(\n hook => hook.event === HookEvent.UserPromptSubmit,\n )\n\n if (matchingHooks.length === 0) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n logDebug(`UserPromptSubmit: ${matchingHooks.length} hook(s)`)\n\n const input = createUserPromptSubmitInput(\n this.sessionId,\n this.transcriptPath,\n userPrompt,\n )\n\n const results: HookExecutionResult[] = []\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n const result = await executeHooksForEvent(\n HookEvent.UserPromptSubmit,\n [hook],\n input,\n options,\n )\n\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n /**\n * Execute SessionStart hooks\n */\n async executeSessionStart(): Promise<void> {\n if (!this.enabled) {\n return\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n const matchingHooks = allHooks.filter(\n hook => hook.event === HookEvent.SessionStart,\n )\n\n if (matchingHooks.length === 0) {\n return\n }\n\n logInfo(`SessionStart: Executing ${matchingHooks.length} hook(s)`)\n\n const input = createSessionStartInput(this.sessionId, this.transcriptPath)\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n await executeHooksForEvent(HookEvent.SessionStart, [hook], input, options)\n }\n }\n\n /**\n * Execute SessionEnd hooks\n */\n async executeSessionEnd(\n reason: 'clear' | 'logout' | 'prompt_input_exit' | 'other' = 'other',\n ): Promise<void> {\n if (!this.enabled) {\n return\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n const matchingHooks = allHooks.filter(\n hook => hook.event === HookEvent.SessionEnd,\n )\n\n if (matchingHooks.length === 0) {\n return\n }\n\n logInfo(`SessionEnd: Executing ${matchingHooks.length} hook(s)`)\n\n const input = createSessionEndInput(\n this.sessionId,\n this.transcriptPath,\n reason,\n )\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n await executeHooksForEvent(HookEvent.SessionEnd, [hook], input, options)\n }\n }\n}\n\n/**\n * Global hook manager instance\n */\nlet globalHookManager: HookManager | null = null\n\n/**\n * Initialize global hook manager\n */\nexport function initializeHookManager(\n sessionId: string,\n transcriptPath: string,\n plugins: LoadedPlugin[],\n): HookManager {\n globalHookManager = new HookManager(sessionId, transcriptPath)\n globalHookManager.registerPlugins(plugins)\n return globalHookManager\n}\n\n/**\n * Get global hook manager\n */\nexport function getHookManager(): HookManager | null {\n return globalHookManager\n}\n"],
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["/**\n * Hook Manager\n *\n * Central manager for hook lifecycle.\n * Coordinates hook execution across plugins and settings.json configurations.\n * Supports all CC hook events with proper toolInput matching.\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { HookEvent, HookMatcher, HooksConfigSchema } from '../types/hooks'\nimport { LoadedPlugin, LoadedHook } from '../types/plugin'\nimport { emitReminderEvent } from '@services/systemReminder'\nimport {\n executeHooksForEvent,\n processHookDecisions,\n createPreToolUseInput,\n createPostToolUseInput,\n createPostToolUseFailureInput,\n createPermissionRequestInput,\n createUserPromptSubmitInput,\n createSessionStartInput,\n createSessionEndInput,\n createStopInput,\n createSubagentStartInput,\n createSubagentStopInput,\n createNotificationInput,\n createPreCompactInput,\n createPostCompactInput,\n createConfigChangeInput,\n createTaskCompletedInput,\n createTeammateIdleInput,\n resetOnceHooks,\n type HookExecutionOptions,\n type HookExecutionResult,\n} from '../services/hookExecutor'\nimport { logError } from './log'\nimport { safeParseJSON } from './json'\nimport { getCwd } from './state'\n\nconst logInfo = (msg: string) => {\n if (process.env.DEBUG) console.log(`[INFO] ${msg}`)\n}\nconst logDebug = (msg: string, ...args: any[]) => {\n if (process.env.DEBUG) console.log(`[DEBUG] ${msg}`, ...args)\n}\n\n/**\n * Check if a hook matcher matches a tool name and optionally tool input\n */\nfunction matchHook(\n hook: LoadedHook,\n toolName: string,\n toolInput?: Record<string, unknown>,\n): boolean {\n // Check tool name matcher\n if (hook.matcher) {\n if (hook.matcher !== '*' && hook.matcher !== '') {\n try {\n const regex = new RegExp(hook.matcher)\n if (!regex.test(toolName)) return false\n } catch {\n if (hook.matcher !== toolName) return false\n }\n }\n }\n\n // Check toolInput matcher (CC spec: matcher.toolInput field matching)\n const hookConfig = hook.config as any\n if (hookConfig.toolInput && toolInput) {\n for (const [field, pattern] of Object.entries(\n hookConfig.toolInput as Record<string, string>,\n )) {\n const fieldValue = String(toolInput[field] ?? '')\n try {\n const regex = new RegExp(pattern)\n if (!regex.test(fieldValue)) return false\n } catch {\n if (fieldValue !== pattern) return false\n }\n }\n }\n\n return true\n}\n\n/**\n * Standard decision return type for blocking hooks\n */\ninterface HookDecisionResult {\n shouldContinue: boolean\n shouldAskUser: boolean\n reason?: string\n updatedInput?: Record<string, unknown>\n additionalContext?: string\n}\n\nconst ALLOW_RESULT: HookDecisionResult = {\n shouldContinue: true,\n shouldAskUser: false,\n}\n\n/**\n * Hook manager instance\n */\nexport class HookManager {\n private plugins: LoadedPlugin[] = []\n private settingsHooks: LoadedHook[] = []\n private managedHooks: LoadedHook[] = []\n private sessionId: string\n private transcriptPath: string\n private enabled: boolean = true\n private disableAllHooks: boolean = false\n\n constructor(sessionId: string, transcriptPath: string) {\n this.sessionId = sessionId\n this.transcriptPath = transcriptPath\n resetOnceHooks()\n }\n\n /**\n * Register plugins with hooks\n */\n registerPlugins(plugins: LoadedPlugin[]) {\n this.plugins = plugins\n const totalHooks = plugins.reduce((sum, p) => sum + p.hooks.length, 0)\n logInfo(\n `HookManager: Registered ${plugins.length} plugin(s) with ${totalHooks} hook(s)`,\n )\n }\n\n /**\n * Load hooks from settings.json files\n * Priority (high to low): managed > .minto/settings.json > .claude/settings.json >\n * .minto/settings.local.json > ~/.minto/settings.json > ~/.claude/settings.json\n */\n loadSettingsHooks() {\n const cwd = getCwd()\n const home = homedir()\n\n // Load paths in priority order (lowest first, higher overrides)\n const settingsPaths = [\n join(home, '.claude', 'settings.json'),\n join(home, '.minto', 'settings.json'),\n join(cwd, '.minto', 'settings.local.json'),\n join(cwd, '.claude', 'settings.json'),\n join(cwd, '.minto', 'settings.json'),\n ]\n\n const allHooks: LoadedHook[] = []\n\n for (const settingsPath of settingsPaths) {\n try {\n if (!existsSync(settingsPath)) continue\n const content = readFileSync(settingsPath, 'utf-8')\n const settings = safeParseJSON(content)\n if (!settings || typeof settings !== 'object') continue\n\n const hooksConfig = (settings as any).hooks\n if (!hooksConfig || typeof hooksConfig !== 'object') continue\n\n const parsed = HooksConfigSchema.safeParse({ hooks: hooksConfig })\n if (!parsed.success) {\n logDebug(`Invalid hooks in ${settingsPath}: ${parsed.error.message}`)\n continue\n }\n\n const hooks = parsed.data.hooks\n if (!hooks) continue\n\n for (const [eventName, matchers] of Object.entries(hooks)) {\n const event = eventName as HookEvent\n for (const matcher of matchers as HookMatcher[]) {\n for (let i = 0; i < matcher.hooks.length; i++) {\n const hookDef = matcher.hooks[i]!\n allHooks.push({\n name: `settings:${eventName}:${i}`,\n filePath: settingsPath,\n config: {\n event,\n matcher: matcher.matcher,\n type: hookDef.type as any,\n command: hookDef.command,\n timeout: hookDef.timeout,\n once: hookDef.once,\n async: hookDef.async,\n } as any,\n pluginName: 'settings',\n event,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (err) {\n logDebug(`Error loading hooks from ${settingsPath}: ${err}`)\n }\n }\n\n this.settingsHooks = allHooks\n\n // Check for disableAllHooks\n try {\n const localSettings = join(cwd, '.minto', 'settings.json')\n const globalSettings = join(home, '.minto', 'settings.json')\n for (const p of [localSettings, globalSettings]) {\n if (existsSync(p)) {\n const content = safeParseJSON(readFileSync(p, 'utf-8'))\n if (content && (content as any).disableAllHooks) {\n this.disableAllHooks = true\n break\n }\n }\n }\n } catch {\n // ignore\n }\n\n logInfo(`HookManager: Loaded ${allHooks.length} hook(s) from settings`)\n }\n\n /**\n * Dynamically add temporary hooks (e.g., skill-level hooks)\n * Returns a cleanup function to remove them\n */\n addHooks(hooks: LoadedHook[]): () => void {\n this.settingsHooks.push(...hooks)\n logDebug(`HookManager: Added ${hooks.length} temporary hook(s)`)\n return () => {\n this.settingsHooks = this.settingsHooks.filter(h => !hooks.includes(h))\n logDebug(`HookManager: Removed ${hooks.length} temporary hook(s)`)\n }\n }\n\n /**\n * Enable or disable hook execution\n */\n setEnabled(enabled: boolean) {\n this.enabled = enabled\n logDebug(`HookManager: ${enabled ? 'Enabled' : 'Disabled'}`)\n }\n\n /**\n * Get all hooks (plugins + settings), respecting disableAllHooks\n */\n private getAllHooks(): LoadedHook[] {\n // Managed hooks always execute even if disableAllHooks is true\n const managed = this.managedHooks\n\n if (this.disableAllHooks) {\n return managed\n }\n\n const pluginHooks = this.plugins.flatMap(p => p.hooks)\n return [...pluginHooks, ...this.settingsHooks, ...managed]\n }\n\n /**\n * Get matching hooks for a tool-based event\n */\n private getMatchingToolHooks(\n event: HookEvent,\n toolName: string,\n toolInput?: Record<string, unknown>,\n ): { hooks: LoadedHook[]; plugins: LoadedPlugin[] } {\n const allHooks = this.getAllHooks()\n const matching = allHooks.filter(hook => {\n if (hook.event !== event) return false\n return matchHook(hook, toolName, toolInput)\n })\n return { hooks: matching, plugins: this.plugins }\n }\n\n /**\n * Get matching hooks for a non-tool event\n */\n private getMatchingEventHooks(event: HookEvent): LoadedHook[] {\n return this.getAllHooks().filter(hook => hook.event === event)\n }\n\n /**\n * Find plugin root for a hook\n */\n private getPluginRoot(hook: LoadedHook): string {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n return plugin?.location || getCwd()\n }\n\n /**\n * Execute hooks for a tool-based event (PreToolUse, PostToolUse, etc.)\n */\n private async executeToolEvent(\n event: HookEvent,\n toolName: string,\n input: any,\n toolInput?: Record<string, unknown>,\n ): Promise<HookDecisionResult> {\n if (!this.enabled) return ALLOW_RESULT\n\n const { hooks } = this.getMatchingToolHooks(event, toolName, toolInput)\n if (hooks.length === 0) return ALLOW_RESULT\n\n logDebug(`${event}: ${hooks.length} hook(s) matched for tool: ${toolName}`)\n\n const results: HookExecutionResult[] = []\n for (const hook of hooks) {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n const result = await executeHooksForEvent(event, [hook], input, options)\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n /**\n * Execute hooks for a non-tool event (fire-and-forget)\n */\n private async executeFireAndForget(\n event: HookEvent,\n input: any,\n ): Promise<void> {\n if (!this.enabled) return\n\n const hooks = this.getMatchingEventHooks(event)\n if (hooks.length === 0) return\n\n logDebug(`${event}: ${hooks.length} hook(s)`)\n\n // Fire-and-forget: don't await individual results\n await Promise.allSettled(\n hooks.map(hook => {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n return executeHooksForEvent(event, [hook], input, options)\n }),\n )\n }\n\n /**\n * Execute hooks for a blockable non-tool event\n */\n private async executeBlockableEvent(\n event: HookEvent,\n input: any,\n ): Promise<HookDecisionResult> {\n if (!this.enabled) return ALLOW_RESULT\n\n const hooks = this.getMatchingEventHooks(event)\n if (hooks.length === 0) return ALLOW_RESULT\n\n logDebug(`${event}: ${hooks.length} hook(s)`)\n\n const results: HookExecutionResult[] = []\n for (const hook of hooks) {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n const result = await executeHooksForEvent(event, [hook], input, options)\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n // ========================================================================\n // Public event methods\n // ========================================================================\n\n async executePreToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n ): Promise<HookDecisionResult> {\n const input = createPreToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n )\n return this.executeToolEvent(\n HookEvent.PreToolUse,\n toolName,\n input,\n toolInput,\n )\n }\n\n async executePostToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n toolOutput: Record<string, unknown>,\n ): Promise<void> {\n const input = createPostToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n toolOutput,\n )\n await this.executeFireAndForget(HookEvent.PostToolUse, input)\n }\n\n async executePostToolUseFailure(\n toolName: string,\n toolInput: Record<string, unknown>,\n error: string,\n errorType?: string,\n ): Promise<void> {\n const input = createPostToolUseFailureInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n error,\n errorType,\n )\n await this.executeFireAndForget(HookEvent.PostToolUseFailure, input)\n\n // Emit diagnostics:new for tool failures (linter/compiler errors)\n emitReminderEvent('diagnostics:new', {\n source: toolName,\n count: 1,\n })\n }\n\n async executePermissionRequest(\n toolName: string,\n toolInput: Record<string, unknown>,\n permissionType: 'read' | 'write' | 'execute' | 'network' | 'other',\n description?: string,\n ): Promise<HookDecisionResult> {\n const input = createPermissionRequestInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n permissionType,\n description,\n )\n return this.executeBlockableEvent(HookEvent.PermissionRequest, input)\n }\n\n async executeUserPromptSubmit(\n userPrompt: string,\n ): Promise<HookDecisionResult> {\n const input = createUserPromptSubmitInput(\n this.sessionId,\n this.transcriptPath,\n userPrompt,\n )\n return this.executeBlockableEvent(HookEvent.UserPromptSubmit, input)\n }\n\n async executeSessionStart(): Promise<void> {\n const input = createSessionStartInput(this.sessionId, this.transcriptPath)\n await this.executeFireAndForget(HookEvent.SessionStart, input)\n }\n\n async executeSessionEnd(\n reason: 'clear' | 'logout' | 'prompt_input_exit' | 'other' = 'other',\n ): Promise<void> {\n const input = createSessionEndInput(\n this.sessionId,\n this.transcriptPath,\n reason,\n )\n await this.executeFireAndForget(HookEvent.SessionEnd, input)\n }\n\n async executeStop(\n lastAssistantMessage?: string,\n ): Promise<HookDecisionResult> {\n const input = createStopInput(this.sessionId, this.transcriptPath, true)\n if (lastAssistantMessage) {\n ;(input as any).last_assistant_message = lastAssistantMessage\n }\n return this.executeBlockableEvent(HookEvent.Stop, input)\n }\n\n async executeSubagentStart(\n agentType: string,\n agentDescription?: string,\n runInBackground?: boolean,\n ): Promise<void> {\n const input = createSubagentStartInput(\n this.sessionId,\n this.transcriptPath,\n agentType,\n agentDescription,\n runInBackground,\n )\n await this.executeFireAndForget(HookEvent.SubagentStart, input)\n }\n\n async executeSubagentStop(\n agentType: string,\n agentId?: string,\n transcriptPath?: string,\n lastMessage?: string,\n ): Promise<HookDecisionResult> {\n const input = createSubagentStopInput(\n this.sessionId,\n this.transcriptPath,\n agentType,\n agentId,\n )\n if (transcriptPath) {\n ;(input as any).agent_transcript_path = transcriptPath\n }\n if (lastMessage) {\n ;(input as any).last_message = lastMessage\n }\n return this.executeBlockableEvent(HookEvent.SubagentStop, input)\n }\n\n async executeNotification(\n message: string,\n title?: string,\n type?: string,\n ): Promise<{ suppressNotification?: boolean }> {\n if (!this.enabled) return {}\n\n const input = createNotificationInput(\n this.sessionId,\n this.transcriptPath,\n message,\n title,\n type,\n )\n\n const hooks = this.getMatchingEventHooks(HookEvent.Notification)\n if (hooks.length === 0) return {}\n\n const results: HookExecutionResult[] = []\n for (const hook of hooks) {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n const result = await executeHooksForEvent(\n HookEvent.Notification,\n [hook],\n input,\n options,\n )\n results.push(...result)\n }\n\n // Check if any hook suppressed the notification\n const suppress = results.some(\n r => r.success && (r.output as any)?.suppressNotification,\n )\n return { suppressNotification: suppress }\n }\n\n async executePreCompact(\n trigger: 'manual' | 'auto',\n customInstructions?: string,\n ): Promise<void> {\n const input = createPreCompactInput(\n this.sessionId,\n this.transcriptPath,\n trigger,\n customInstructions || '',\n )\n await this.executeFireAndForget(HookEvent.PreCompact, input)\n }\n\n async executePostCompact(\n trigger: 'manual' | 'auto',\n summary: string,\n compressionRatio: number,\n originalTokens: number,\n compressedTokens: number,\n ): Promise<void> {\n const input = createPostCompactInput(\n this.sessionId,\n this.transcriptPath,\n trigger,\n summary,\n compressionRatio,\n originalTokens,\n compressedTokens,\n )\n await this.executeFireAndForget(HookEvent.PostCompact, input)\n }\n\n async executeConfigChange(\n source: 'settings' | 'project' | 'global' | 'env' | 'cli',\n filePath?: string,\n ): Promise<HookDecisionResult> {\n const input = createConfigChangeInput(\n this.sessionId,\n this.transcriptPath,\n source,\n filePath,\n )\n return this.executeBlockableEvent(HookEvent.ConfigChange, input)\n }\n\n async executeTaskCompleted(\n taskId: string,\n subject: string,\n description?: string,\n ): Promise<HookDecisionResult> {\n const input = createTaskCompletedInput(\n this.sessionId,\n this.transcriptPath,\n taskId,\n subject,\n description,\n )\n return this.executeBlockableEvent(HookEvent.TaskCompleted, input)\n }\n\n async executeTeammateIdle(\n teammateName: string,\n teamName: string,\n ): Promise<HookDecisionResult> {\n const input = createTeammateIdleInput(\n this.sessionId,\n this.transcriptPath,\n teammateName,\n teamName,\n )\n return this.executeBlockableEvent(HookEvent.TeammateIdle, input)\n }\n}\n\n// ============================================================================\n// Global Hook Manager\n// ============================================================================\n\nlet globalHookManager: HookManager | null = null\n\nexport function initializeHookManager(\n sessionId: string,\n transcriptPath: string,\n plugins: LoadedPlugin[],\n): HookManager {\n globalHookManager = new HookManager(sessionId, transcriptPath)\n globalHookManager.registerPlugins(plugins)\n globalHookManager.loadSettingsHooks()\n return globalHookManager\n}\n\nexport function getHookManager(): HookManager | null {\n return globalHookManager\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/utils/markdown.js
CHANGED
|
@@ -79,9 +79,56 @@ function format(token, listDepth = 0, orderedListNumber = null, parent = null) {
|
|
|
79
79
|
} else {
|
|
80
80
|
return token.text;
|
|
81
81
|
}
|
|
82
|
+
case "table": {
|
|
83
|
+
const headerTexts = token.header.map(
|
|
84
|
+
(cell) => (cell.tokens ?? []).map((_) => format(_)).join("")
|
|
85
|
+
);
|
|
86
|
+
const rowTexts = token.rows.map(
|
|
87
|
+
(row) => row.map(
|
|
88
|
+
(cell) => (cell.tokens ?? []).map((_) => format(_)).join("")
|
|
89
|
+
)
|
|
90
|
+
);
|
|
91
|
+
const colCount = headerTexts.length;
|
|
92
|
+
const colWidths = [];
|
|
93
|
+
for (let c = 0; c < colCount; c++) {
|
|
94
|
+
let maxWidth = stripAnsi(headerTexts[c] ?? "").length;
|
|
95
|
+
for (const row of rowTexts) {
|
|
96
|
+
maxWidth = Math.max(maxWidth, stripAnsi(row[c] ?? "").length);
|
|
97
|
+
}
|
|
98
|
+
colWidths.push(Math.max(maxWidth, 3));
|
|
99
|
+
}
|
|
100
|
+
const headerRow = headerTexts.map(
|
|
101
|
+
(text, i) => chalk.bold(padCell(text, colWidths[i], token.align[i]))
|
|
102
|
+
).join(" | ");
|
|
103
|
+
const separator = colWidths.map((w, i) => {
|
|
104
|
+
const align = token.align[i];
|
|
105
|
+
if (align === "center") return ":" + "-".repeat(w - 2) + ":";
|
|
106
|
+
if (align === "right") return "-".repeat(w - 1) + ":";
|
|
107
|
+
if (align === "left") return ":" + "-".repeat(w - 1);
|
|
108
|
+
return "-".repeat(w);
|
|
109
|
+
}).join(" | ");
|
|
110
|
+
const dataRows = rowTexts.map(
|
|
111
|
+
(row) => row.map((text, i) => padCell(text, colWidths[i], token.align[i])).join(" | ")
|
|
112
|
+
);
|
|
113
|
+
return [headerRow, separator, ...dataRows].join(EOL) + EOL;
|
|
114
|
+
}
|
|
82
115
|
}
|
|
83
116
|
return "";
|
|
84
117
|
}
|
|
118
|
+
function stripAnsi(str) {
|
|
119
|
+
return str.replace(/\x1B\[[0-9;]*m/g, "");
|
|
120
|
+
}
|
|
121
|
+
function padCell(text, width, align) {
|
|
122
|
+
const visibleLength = stripAnsi(text).length;
|
|
123
|
+
const padding = Math.max(0, width - visibleLength);
|
|
124
|
+
if (align === "right") return " ".repeat(padding) + text;
|
|
125
|
+
if (align === "center") {
|
|
126
|
+
const left = Math.floor(padding / 2);
|
|
127
|
+
const right = padding - left;
|
|
128
|
+
return " ".repeat(left) + text + " ".repeat(right);
|
|
129
|
+
}
|
|
130
|
+
return text + " ".repeat(padding);
|
|
131
|
+
}
|
|
85
132
|
const DEPTH_1_LIST_NUMBERS = [
|
|
86
133
|
"a",
|
|
87
134
|
"b",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/markdown.ts"],
|
|
4
|
-
"sourcesContent": ["import { marked, Token } from 'marked'\nimport { stripSystemMessages } from './messages'\nimport chalk from 'chalk'\nimport { EOL } from 'os'\nimport { highlight, supportsLanguage } from 'cli-highlight'\nimport { logError } from './log'\n\n/**\n * Strip outer markdown code block wrapper if present.\n * AI models sometimes wrap their response in ```markdown ... ``` which\n * causes the content to be parsed as a code block instead of actual markdown.\n */\nfunction stripMarkdownCodeBlockWrapper(content: string): string {\n const trimmed = content.trim()\n // Match ```markdown or ```md at the start and ``` at the end\n const codeBlockRegex = /^```(?:markdown|md)?\\s*\\n([\\s\\S]*?)\\n```$/\n const match = trimmed.match(codeBlockRegex)\n if (match) {\n return match[1] ?? trimmed\n }\n return content\n}\n\nexport function applyMarkdown(content: string): string {\n // Pre-process: remove outer markdown code block wrapper if present\n const preprocessed = stripMarkdownCodeBlockWrapper(\n stripSystemMessages(content),\n )\n return marked\n .lexer(preprocessed)\n .map(_ => format(_))\n .join('')\n .trim()\n}\n\nfunction format(\n token: Token,\n listDepth = 0,\n orderedListNumber: number | null = null,\n parent: Token | null = null,\n): string {\n switch (token.type) {\n case 'blockquote':\n return chalk.dim.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'code':\n if (token.lang && supportsLanguage(token.lang)) {\n return highlight(token.text, { language: token.lang }) + EOL\n } else {\n logError(\n `Language not supported while highlighting code, falling back to markdown: ${token.lang}`,\n )\n return highlight(token.text, { language: 'markdown' }) + EOL\n }\n case 'codespan':\n // inline code\n return chalk.blue(token.text)\n case 'em':\n return chalk.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'strong':\n return chalk.bold((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'heading':\n switch (token.depth) {\n case 1: // h1\n return (\n chalk.bold.italic.underline(\n (token.tokens ?? []).map(_ => format(_)).join(''),\n ) +\n EOL +\n EOL\n )\n case 2: // h2\n return (\n chalk.bold((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n default: // h3+\n return (\n chalk.bold.dim((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n }\n case 'hr':\n return '---'\n case 'image':\n return `[Image: ${token.title}: ${token.href}]`\n case 'link':\n return chalk.blue(token.href)\n case 'list': {\n return token.items\n .map((_: Token, index: number) =>\n format(\n _,\n listDepth,\n token.ordered ? token.start + index : null,\n token,\n ),\n )\n .join('')\n }\n case 'list_item':\n return (token.tokens ?? [])\n .map(\n _ =>\n `${' '.repeat(listDepth)}${format(_, listDepth + 1, orderedListNumber, token)}`,\n )\n .join('')\n case 'paragraph':\n return (token.tokens ?? []).map(_ => format(_)).join('') + EOL\n case 'space':\n return EOL\n case 'text':\n if (parent?.type === 'list_item') {\n return `${orderedListNumber === null ? '-' : getListNumber(listDepth, orderedListNumber) + '.'} ${token.tokens ? token.tokens.map(_ => format(_, listDepth, orderedListNumber, token)).join('') : token.text}${EOL}`\n } else {\n return token.text\n }\n }\n //
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import { marked, Token } from 'marked'\nimport { stripSystemMessages } from './messages'\nimport chalk from 'chalk'\nimport { EOL } from 'os'\nimport { highlight, supportsLanguage } from 'cli-highlight'\nimport { logError } from './log'\n\n/**\n * Strip outer markdown code block wrapper if present.\n * AI models sometimes wrap their response in ```markdown ... ``` which\n * causes the content to be parsed as a code block instead of actual markdown.\n */\nfunction stripMarkdownCodeBlockWrapper(content: string): string {\n const trimmed = content.trim()\n // Match ```markdown or ```md at the start and ``` at the end\n const codeBlockRegex = /^```(?:markdown|md)?\\s*\\n([\\s\\S]*?)\\n```$/\n const match = trimmed.match(codeBlockRegex)\n if (match) {\n return match[1] ?? trimmed\n }\n return content\n}\n\nexport function applyMarkdown(content: string): string {\n // Pre-process: remove outer markdown code block wrapper if present\n const preprocessed = stripMarkdownCodeBlockWrapper(\n stripSystemMessages(content),\n )\n return marked\n .lexer(preprocessed)\n .map(_ => format(_))\n .join('')\n .trim()\n}\n\nfunction format(\n token: Token,\n listDepth = 0,\n orderedListNumber: number | null = null,\n parent: Token | null = null,\n): string {\n switch (token.type) {\n case 'blockquote':\n return chalk.dim.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'code':\n if (token.lang && supportsLanguage(token.lang)) {\n return highlight(token.text, { language: token.lang }) + EOL\n } else {\n logError(\n `Language not supported while highlighting code, falling back to markdown: ${token.lang}`,\n )\n return highlight(token.text, { language: 'markdown' }) + EOL\n }\n case 'codespan':\n // inline code\n return chalk.blue(token.text)\n case 'em':\n return chalk.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'strong':\n return chalk.bold((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'heading':\n switch (token.depth) {\n case 1: // h1\n return (\n chalk.bold.italic.underline(\n (token.tokens ?? []).map(_ => format(_)).join(''),\n ) +\n EOL +\n EOL\n )\n case 2: // h2\n return (\n chalk.bold((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n default: // h3+\n return (\n chalk.bold.dim((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n }\n case 'hr':\n return '---'\n case 'image':\n return `[Image: ${token.title}: ${token.href}]`\n case 'link':\n return chalk.blue(token.href)\n case 'list': {\n return token.items\n .map((_: Token, index: number) =>\n format(\n _,\n listDepth,\n token.ordered ? token.start + index : null,\n token,\n ),\n )\n .join('')\n }\n case 'list_item':\n return (token.tokens ?? [])\n .map(\n _ =>\n `${' '.repeat(listDepth)}${format(_, listDepth + 1, orderedListNumber, token)}`,\n )\n .join('')\n case 'paragraph':\n return (token.tokens ?? []).map(_ => format(_)).join('') + EOL\n case 'space':\n return EOL\n case 'text':\n if (parent?.type === 'list_item') {\n return `${orderedListNumber === null ? '-' : getListNumber(listDepth, orderedListNumber) + '.'} ${token.tokens ? token.tokens.map(_ => format(_, listDepth, orderedListNumber, token)).join('') : token.text}${EOL}`\n } else {\n return token.text\n }\n case 'table': {\n // Render each cell's inline tokens to get display text\n const headerTexts = (token.header as any[]).map((cell: any) =>\n (cell.tokens ?? []).map((_: Token) => format(_)).join(''),\n )\n const rowTexts = (token.rows as any[][]).map((row: any[]) =>\n row.map((cell: any) =>\n (cell.tokens ?? []).map((_: Token) => format(_)).join(''),\n ),\n )\n\n // Calculate column widths (max of header and all rows)\n const colCount = headerTexts.length\n const colWidths: number[] = []\n for (let c = 0; c < colCount; c++) {\n let maxWidth = stripAnsi(headerTexts[c] ?? '').length\n for (const row of rowTexts) {\n maxWidth = Math.max(maxWidth, stripAnsi(row[c] ?? '').length)\n }\n colWidths.push(Math.max(maxWidth, 3)) // minimum 3 chars\n }\n\n // Build header row\n const headerRow = headerTexts\n .map((text, i) =>\n chalk.bold(padCell(text, colWidths[i]!, token.align[i])),\n )\n .join(' | ')\n\n // Build separator\n const separator = colWidths\n .map((w, i) => {\n const align = token.align[i]\n if (align === 'center') return ':' + '-'.repeat(w - 2) + ':'\n if (align === 'right') return '-'.repeat(w - 1) + ':'\n if (align === 'left') return ':' + '-'.repeat(w - 1)\n return '-'.repeat(w)\n })\n .join(' | ')\n\n // Build data rows\n const dataRows = rowTexts.map(row =>\n row\n .map((text, i) => padCell(text, colWidths[i]!, token.align[i]))\n .join(' | '),\n )\n\n return [headerRow, separator, ...dataRows].join(EOL) + EOL\n }\n }\n return ''\n}\n\n/**\n * Strip ANSI escape codes for accurate width calculation\n */\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B\\[[0-9;]*m/g, '')\n}\n\n/**\n * Pad a cell to a target width, respecting alignment and ANSI codes\n */\nfunction padCell(\n text: string,\n width: number,\n align: 'center' | 'left' | 'right' | null,\n): string {\n const visibleLength = stripAnsi(text).length\n const padding = Math.max(0, width - visibleLength)\n if (align === 'right') return ' '.repeat(padding) + text\n if (align === 'center') {\n const left = Math.floor(padding / 2)\n const right = padding - left\n return ' '.repeat(left) + text + ' '.repeat(right)\n }\n // left or null (default left)\n return text + ' '.repeat(padding)\n}\n\nconst DEPTH_1_LIST_NUMBERS = [\n 'a',\n 'b',\n 'c',\n 'd',\n 'e',\n 'f',\n 'g',\n 'h',\n 'i',\n 'j',\n 'k',\n 'l',\n 'm',\n 'n',\n 'o',\n 'p',\n 'q',\n 'r',\n 's',\n 't',\n 'u',\n 'v',\n 'w',\n 'x',\n 'y',\n 'z',\n 'aa',\n 'ab',\n 'ac',\n 'ad',\n 'ae',\n 'af',\n 'ag',\n 'ah',\n 'ai',\n 'aj',\n 'ak',\n 'al',\n 'am',\n 'an',\n 'ao',\n 'ap',\n 'aq',\n 'ar',\n 'as',\n 'at',\n 'au',\n 'av',\n 'aw',\n 'ax',\n 'ay',\n 'az',\n]\nconst DEPTH_2_LIST_NUMBERS = [\n 'i',\n 'ii',\n 'iii',\n 'iv',\n 'v',\n 'vi',\n 'vii',\n 'viii',\n 'ix',\n 'x',\n 'xi',\n 'xii',\n 'xiii',\n 'xiv',\n 'xv',\n 'xvi',\n 'xvii',\n 'xviii',\n 'xix',\n 'xx',\n 'xxi',\n 'xxii',\n 'xxiii',\n 'xxiv',\n 'xxv',\n 'xxvi',\n 'xxvii',\n 'xxviii',\n 'xxix',\n 'xxx',\n 'xxxi',\n 'xxxii',\n 'xxxiii',\n 'xxxiv',\n 'xxxv',\n 'xxxvi',\n 'xxxvii',\n 'xxxviii',\n 'xxxix',\n 'xl',\n]\n\nfunction getListNumber(listDepth: number, orderedListNumber: number): string {\n switch (listDepth) {\n case 0:\n case 1:\n return orderedListNumber.toString()\n case 2:\n return DEPTH_1_LIST_NUMBERS[orderedListNumber - 1]! // TODO: don't hard code the list\n case 3:\n return DEPTH_2_LIST_NUMBERS[orderedListNumber - 1]! // TODO: don't hard code the list\n default:\n return orderedListNumber.toString()\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function memoizeWithTTL(fn, ttlMs = 6e4) {
|
|
2
|
+
let cached = null;
|
|
3
|
+
let inflight = null;
|
|
4
|
+
return async () => {
|
|
5
|
+
if (cached && Date.now() < cached.expiresAt) {
|
|
6
|
+
return cached.value;
|
|
7
|
+
}
|
|
8
|
+
if (inflight) {
|
|
9
|
+
return inflight;
|
|
10
|
+
}
|
|
11
|
+
inflight = fn().then((value) => {
|
|
12
|
+
cached = { value, expiresAt: Date.now() + ttlMs };
|
|
13
|
+
inflight = null;
|
|
14
|
+
return value;
|
|
15
|
+
}).catch((error) => {
|
|
16
|
+
inflight = null;
|
|
17
|
+
throw error;
|
|
18
|
+
});
|
|
19
|
+
return inflight;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export {
|
|
23
|
+
memoizeWithTTL
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=memoizeWithTTL.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/memoizeWithTTL.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Memoize an async function with a TTL (time-to-live) cache.\n *\n * Unlike lodash memoize(), cached values expire after `ttlMs`.\n * This prevents permanent caching of transient failures\n * (e.g., network check returns false once \u2192 cached forever).\n *\n * - Success results are cached for `ttlMs` (default 60s).\n * - Thrown errors are NOT cached (next call retries immediately).\n * - Only supports zero-argument async functions (covers all current use cases).\n */\n\nexport function memoizeWithTTL<T>(\n fn: () => Promise<T>,\n ttlMs: number = 60_000,\n): () => Promise<T> {\n let cached: { value: T; expiresAt: number } | null = null\n let inflight: Promise<T> | null = null\n\n return async (): Promise<T> => {\n // Return cached if still valid\n if (cached && Date.now() < cached.expiresAt) {\n return cached.value\n }\n\n // Deduplicate concurrent calls\n if (inflight) {\n return inflight\n }\n\n inflight = fn()\n .then(value => {\n cached = { value, expiresAt: Date.now() + ttlMs }\n inflight = null\n return value\n })\n .catch(error => {\n // Don't cache errors \u2014 allow immediate retry\n inflight = null\n throw error\n })\n\n return inflight\n }\n}\n"],
|
|
5
|
+
"mappings": "AAYO,SAAS,eACd,IACA,QAAgB,KACE;AAClB,MAAI,SAAiD;AACrD,MAAI,WAA8B;AAElC,SAAO,YAAwB;AAE7B,QAAI,UAAU,KAAK,IAAI,IAAI,OAAO,WAAW;AAC3C,aAAO,OAAO;AAAA,IAChB;AAGA,QAAI,UAAU;AACZ,aAAO;AAAA,IACT;AAEA,eAAW,GAAG,EACX,KAAK,WAAS;AACb,eAAS,EAAE,OAAO,WAAW,KAAK,IAAI,IAAI,MAAM;AAChD,iBAAW;AACX,aAAO;AAAA,IACT,CAAC,EACA,MAAM,WAAS;AAEd,iBAAW;AACX,YAAM;AAAA,IACR,CAAC;AAEH,WAAO;AAAA,EACT;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/utils/model.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { memoize } from "lodash-es";
|
|
2
1
|
import {
|
|
3
2
|
getGlobalConfig,
|
|
4
3
|
saveGlobalConfig
|
|
@@ -13,7 +12,7 @@ const DEFAULT_MODEL_CONFIG = {
|
|
|
13
12
|
async function getModelConfig() {
|
|
14
13
|
return DEFAULT_MODEL_CONFIG;
|
|
15
14
|
}
|
|
16
|
-
const getSlowAndCapableModel =
|
|
15
|
+
const getSlowAndCapableModel = async () => {
|
|
17
16
|
const config = await getGlobalConfig();
|
|
18
17
|
const modelManager = new ModelManager(config);
|
|
19
18
|
const model = modelManager.getMainAgentModel();
|
|
@@ -32,10 +31,10 @@ const getSlowAndCapableModel = memoize(async () => {
|
|
|
32
31
|
throw new Error(
|
|
33
32
|
"No models configured. Please run /model to add and configure your AI models."
|
|
34
33
|
);
|
|
35
|
-
}
|
|
34
|
+
};
|
|
36
35
|
function getModelContextLength(pointerType = "main") {
|
|
37
36
|
const config = getGlobalConfig();
|
|
38
|
-
const modelManager =
|
|
37
|
+
const modelManager = getModelManager();
|
|
39
38
|
let modelName = null;
|
|
40
39
|
switch (pointerType) {
|
|
41
40
|
case "main":
|
|
@@ -73,6 +72,7 @@ function getVertexRegionForModel(model) {
|
|
|
73
72
|
} else if (model?.startsWith("claude-3-7-sonnet")) {
|
|
74
73
|
return process.env.VERTEX_REGION_CLAUDE_3_7_SONNET;
|
|
75
74
|
}
|
|
75
|
+
return void 0;
|
|
76
76
|
}
|
|
77
77
|
class ModelManager {
|
|
78
78
|
config;
|
|
@@ -535,6 +535,26 @@ class ModelManager {
|
|
|
535
535
|
modelPointers: this.config.modelPointers || {}
|
|
536
536
|
};
|
|
537
537
|
}
|
|
538
|
+
/**
|
|
539
|
+
* Update an existing model profile
|
|
540
|
+
* modelName is the primary key and cannot be changed
|
|
541
|
+
*/
|
|
542
|
+
updateModel(modelName, updates) {
|
|
543
|
+
const profile = this.findModelProfile(modelName);
|
|
544
|
+
if (!profile) {
|
|
545
|
+
throw new Error(`Model '${modelName}' not found`);
|
|
546
|
+
}
|
|
547
|
+
if (updates.name && updates.name !== profile.name) {
|
|
548
|
+
const existingByName = this.modelProfiles.find(
|
|
549
|
+
(p) => p.name === updates.name && p.modelName !== modelName
|
|
550
|
+
);
|
|
551
|
+
if (existingByName) {
|
|
552
|
+
throw new Error(`Model with name '${updates.name}' already exists`);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
Object.assign(profile, updates);
|
|
556
|
+
this.saveConfig();
|
|
557
|
+
}
|
|
538
558
|
/**
|
|
539
559
|
* Remove a model profile
|
|
540
560
|
*/
|
|
@@ -692,8 +712,9 @@ class ModelManager {
|
|
|
692
712
|
findModelProfile(modelName) {
|
|
693
713
|
return this.modelProfiles.find((p) => p.modelName === modelName) || null;
|
|
694
714
|
}
|
|
715
|
+
/** @deprecated Use findModelProfile instead - identical implementation */
|
|
695
716
|
findModelProfileByModelName(modelName) {
|
|
696
|
-
return this.
|
|
717
|
+
return this.findModelProfile(modelName);
|
|
697
718
|
}
|
|
698
719
|
findModelProfileByName(name) {
|
|
699
720
|
return this.modelProfiles.find((p) => p.name === name) || null;
|
|
@@ -797,13 +818,17 @@ const reloadModelManager = () => {
|
|
|
797
818
|
};
|
|
798
819
|
const getQuickModel = () => {
|
|
799
820
|
const manager = getModelManager();
|
|
800
|
-
const
|
|
801
|
-
|
|
821
|
+
const quickModelName = manager.getQuickModel();
|
|
822
|
+
if (quickModelName) return quickModelName;
|
|
823
|
+
const mainModel = manager.getMainAgentModel();
|
|
824
|
+
return mainModel || "";
|
|
802
825
|
};
|
|
803
826
|
const getCompactModel = () => {
|
|
804
827
|
const manager = getModelManager();
|
|
805
|
-
const
|
|
806
|
-
|
|
828
|
+
const compactModelName = manager.getCompactModel();
|
|
829
|
+
if (compactModelName) return compactModelName;
|
|
830
|
+
const mainModel = manager.getMainAgentModel();
|
|
831
|
+
return mainModel || "";
|
|
807
832
|
};
|
|
808
833
|
export {
|
|
809
834
|
ModelManager,
|