@within-7/minto 0.3.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Tool.js.map +2 -2
- package/dist/commands/agents/AgentsCommand.js +461 -657
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/types.js +1 -0
- package/dist/commands/agents/types.js.map +2 -2
- package/dist/commands/agents/utils/fileOperations.js +96 -36
- package/dist/commands/agents/utils/fileOperations.js.map +3 -3
- package/dist/commands/agents/utils/index.js +3 -1
- package/dist/commands/agents/utils/index.js.map +2 -2
- package/dist/commands/context.js +54 -23
- package/dist/commands/context.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 +684 -94
- 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/language.js +19 -46
- package/dist/commands/language.js.map +2 -2
- package/dist/commands/mcp-interactive.js +425 -217
- 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 +457 -65
- 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/permissions.js +75 -49
- package/dist/commands/permissions.js.map +2 -2
- package/dist/commands/plugin/utils.js +33 -1
- package/dist/commands/plugin/utils.js.map +2 -2
- package/dist/commands/plugin.js +891 -185
- package/dist/commands/plugin.js.map +3 -3
- package/dist/commands/refreshCommands.js +2 -0
- package/dist/commands/refreshCommands.js.map +2 -2
- package/dist/commands/resume.js +1 -1
- package/dist/commands/resume.js.map +1 -1
- package/dist/commands/review.js +51 -0
- package/dist/commands/review.js.map +7 -0
- package/dist/commands/sandbox.js +168 -70
- package/dist/commands/sandbox.js.map +2 -2
- package/dist/commands/setup.js +593 -107
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/stats.js +188 -131
- package/dist/commands/stats.js.map +2 -2
- package/dist/commands/status.js +75 -13
- package/dist/commands/status.js.map +2 -2
- package/dist/commands/terminalSetup.js +6 -0
- package/dist/commands/terminalSetup.js.map +2 -2
- package/dist/commands/undo.js +146 -174
- 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/Help.js +165 -32
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HighlightedCode.js +1 -0
- package/dist/components/HighlightedCode.js.map +2 -2
- package/dist/components/InfoPanel/InfoPanel.js +123 -0
- package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
- package/dist/components/InfoPanel/index.js +5 -0
- package/dist/components/InfoPanel/index.js.map +7 -0
- package/dist/components/InfoPanel/types.js +1 -0
- package/dist/components/InfoPanel/types.js.map +7 -0
- package/dist/components/ModelSelector/BrandTextInput.js +43 -0
- package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +590 -565
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/ModelSelector/WizardContainer.js +45 -0
- package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
- package/dist/components/ModelSelector/index.js +1 -3
- package/dist/components/ModelSelector/index.js.map +2 -2
- package/dist/components/PromptInput.js +26 -11
- 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/SimpleSelector/SimpleSelector.js +154 -0
- package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
- package/dist/components/SimpleSelector/index.js +5 -0
- package/dist/components/SimpleSelector/index.js.map +7 -0
- package/dist/components/SimpleSelector/types.js +1 -0
- package/dist/components/SimpleSelector/types.js.map +7 -0
- 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/StatusOverlayContent.js +21 -0
- package/dist/components/StatusOverlayContent.js.map +7 -0
- package/dist/components/SubagentBlock.js +43 -6
- package/dist/components/SubagentBlock.js.map +2 -2
- package/dist/components/TabbedListView/ScrollableList.js +31 -5
- package/dist/components/TabbedListView/ScrollableList.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 +123 -48
- 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 +29 -0
- package/dist/core/backupHook.js.map +7 -0
- package/dist/core/config/defaults.js +11 -2
- package/dist/core/config/defaults.js.map +2 -2
- package/dist/core/config/schema.js +21 -3
- package/dist/core/config/schema.js.map +2 -2
- package/dist/core/costTracker.js +18 -16
- 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/cost-tracker.js +0 -16
- package/dist/cost-tracker.js.map +2 -2
- package/dist/entrypoints/bootstrap.js +3 -1
- package/dist/entrypoints/bootstrap.js.map +2 -2
- package/dist/entrypoints/cli.js +81 -68
- 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 +299 -1
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +300 -2
- 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/customCommands.js +30 -8
- package/dist/services/customCommands.js.map +2 -2
- 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/lspServers.js +1 -1
- package/dist/services/plugins/lspServers.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +2 -1
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +10 -3
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/plugins/skillMarketplace.js +20 -9
- 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 +367 -9
- 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 +8 -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 +10 -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 +7 -0
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
- package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
- 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 +84 -11
- 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 +3 -5
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/agentHookExecutor.js +1 -4
- package/dist/utils/agentHookExecutor.js.map +2 -2
- package/dist/utils/agentLoader.js +91 -15
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/agentMemory.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/claudeCodeSync.js +439 -0
- package/dist/utils/claudeCodeSync.js.map +7 -0
- package/dist/utils/config.js +27 -151
- 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/execFileNoThrow.js +2 -1
- package/dist/utils/execFileNoThrow.js.map +2 -2
- 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/marketplaceManager.js +80 -43
- package/dist/utils/marketplaceManager.js.map +2 -2
- package/dist/utils/memoizeWithTTL.js +25 -0
- package/dist/utils/memoizeWithTTL.js.map +7 -0
- package/dist/utils/messages.js +2 -2
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/model.js +34 -9
- package/dist/utils/model.js.map +2 -2
- package/dist/utils/pluginInstaller.js +68 -29
- package/dist/utils/pluginInstaller.js.map +2 -2
- package/dist/utils/pluginLoader.js +249 -57
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/repoFetcher.js +110 -0
- package/dist/utils/repoFetcher.js.map +7 -0
- package/dist/utils/safeFetch.js +45 -0
- package/dist/utils/safeFetch.js.map +7 -0
- package/dist/utils/skillLoader.js +77 -12
- 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/stringSubstitution.js +4 -5
- package/dist/utils/stringSubstitution.js.map +2 -2
- package/dist/utils/style.js +6 -3
- package/dist/utils/style.js.map +2 -2
- package/dist/utils/teamConfig.js +162 -16
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/terminal.js +1 -1
- package/dist/utils/terminal.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/pluginLoader.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Plugin Loader\n *\n * Discovers and loads plugins from Minto plugin directories.\n *\n * Directory Priority (later overrides earlier):\n * 1. ~/.minto/plugins/ (user global)\n * 2. ./.minto/plugins/ (project - highest priority)\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport {\n PluginManifest,\n PluginManifestSchema,\n LoadedPlugin,\n LoadedAgent,\n LoadedCommand,\n LoadedSkill,\n LoadedHook,\n LoadedMCPServer,\n PluginError,\n PluginErrorCode,\n PluginSource,\n} from '../types/plugin'\nimport { getCwd } from './state'\n\n/**\n * Plugin discovery directories in priority order\n */\nfunction getPluginDirectories(): string[] {\n const cwd = getCwd()\n const home = homedir()\n\n return [\n join(home, '.minto', 'plugins'), // User global\n join(cwd, '.minto', 'plugins'), // Project (highest priority)\n ]\n}\n\n/**\n * Find all plugin directories across all sources\n */\nfunction discoverPluginPaths(): Map<string, string> {\n const pluginPaths = new Map<string, string>() // name -> path\n const directories = getPluginDirectories()\n\n for (const dir of directories) {\n if (!existsSync(dir)) continue\n\n try {\n const entries = readdirSync(dir)\n\n for (const entry of entries) {\n const pluginPath = join(dir, entry)\n\n // Must be a directory\n if (!statSync(pluginPath).isDirectory()) continue\n\n // Must have plugin.json in .minto-plugin/ or root\n const mintoManifestPath = join(\n pluginPath,\n '.minto-plugin',\n 'plugin.json',\n )\n const rootManifestPath = join(pluginPath, 'plugin.json')\n if (!existsSync(mintoManifestPath) && !existsSync(rootManifestPath))\n continue\n\n // Later directories override earlier ones\n pluginPaths.set(entry, pluginPath)\n }\n } catch (error) {\n // Silently ignore errors\n }\n }\n\n return pluginPaths\n}\n\n/**\n * Load and validate plugin manifest\n *\n * Manifest locations (priority order):\n * 1. .minto-plugin/plugin.json\n * 2. plugin.json (root fallback)\n */\nfunction loadManifest(pluginPath: string): PluginManifest {\n const mintoPluginManifest = join(pluginPath, '.minto-plugin', 'plugin.json')\n const rootManifest = join(pluginPath, 'plugin.json')\n\n let manifestPath: string | null = null\n\n if (existsSync(mintoPluginManifest)) {\n manifestPath = mintoPluginManifest\n } else if (existsSync(rootManifest)) {\n manifestPath = rootManifest\n }\n\n if (!manifestPath) {\n throw new PluginError(\n `Plugin manifest not found. Tried:\\n - ${mintoPluginManifest}\\n - ${rootManifest}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8')\n const manifestData = JSON.parse(manifestContent)\n\n // Validate with Zod schema\n const manifest = PluginManifestSchema.parse(manifestData)\n\n return manifest\n } catch (error) {\n throw new PluginError(\n `Invalid plugin manifest at ${manifestPath}: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Load agents from plugin\n */\nfunction loadAgents(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedAgent[] {\n const agents: LoadedAgent[] = []\n const agentsDir = join(pluginPath, 'agents')\n\n // Load agents listed in manifest\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Agent file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(agentPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(agentPath, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading agent ${agentPath}:`, error)\n }\n }\n\n // Also scan agents/ directory if it exists\n if (existsSync(agentsDir) && statSync(agentsDir).isDirectory()) {\n const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.md'))\n\n for (const file of agentFiles) {\n const fullPath = join(agentsDir, file)\n\n // Skip if already loaded from manifest\n if (agents.some(a => a.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading agent ${file}:`, error)\n }\n }\n }\n\n return agents\n}\n\n/**\n * Load commands from plugin\n */\nfunction loadCommands(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedCommand[] {\n const commands: LoadedCommand[] = []\n const commandsDir = join(pluginPath, 'commands')\n\n // Load commands listed in manifest\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Command file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(commandPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(commandPath, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading command ${commandPath}:`, error)\n }\n }\n\n // Also scan commands/ directory if it exists\n if (existsSync(commandsDir) && statSync(commandsDir).isDirectory()) {\n const commandFiles = readdirSync(commandsDir).filter(f => f.endsWith('.md'))\n\n for (const file of commandFiles) {\n const fullPath = join(commandsDir, file)\n\n // Skip if already loaded from manifest\n if (commands.some(c => c.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(`Error loading command ${file}:`, error)\n }\n }\n }\n\n return commands\n}\n\n/**\n * Load skills from plugin\n *\n * Supports two patterns:\n * - Subdirectory: skills/skill-name/SKILL.md\n * - Flat: skills/skill-name.md\n */\nfunction loadSkills(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n const skillsDir = join(pluginPath, 'skills')\n\n // Load skills listed in manifest\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n\n if (!existsSync(fullPath)) {\n console.warn(`Skill file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(skillPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(skillPath, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n console.error(`Error loading skill ${skillPath}:`, error)\n }\n }\n\n // Auto-discover skills from skills/ directory if it exists\n if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {\n const entries = readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n // Subdirectory pattern: skill-name/SKILL.md\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsDir, entry.name, 'SKILL.md')\n\n if (existsSync(skillMdPath)) {\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === skillMdPath)) continue\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || entry.name,\n filePath: skillMdPath,\n config: {\n name: data.name || entry.name,\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n console.error(`Error loading skill from ${skillMdPath}:`, error)\n }\n }\n }\n // Flat pattern: .md files directly in skills/\n else if (entry.isFile() && entry.name.endsWith('.md')) {\n const fullPath = join(skillsDir, entry.name)\n\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(entry.name, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(entry.name, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n console.error(`Error loading skill ${entry.name}:`, error)\n }\n }\n }\n }\n\n return skills\n}\n\n/**\n * Load hooks from plugin\n *\n * Uses hooks/hooks.json format\n */\nfunction loadHooks(pluginPath: string, manifest: PluginManifest): LoadedHook[] {\n const hooks: LoadedHook[] = []\n const hooksDir = join(pluginPath, 'hooks')\n const hooksJsonPath = join(hooksDir, 'hooks.json')\n\n // Check if hooks.json exists\n if (!existsSync(hooksJsonPath)) {\n return hooks\n }\n\n try {\n const content = readFileSync(hooksJsonPath, 'utf-8')\n const hooksConfig = JSON.parse(content)\n\n // Validate structure (basic validation, full validation in hook executor)\n if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') {\n console.warn(`Invalid hooks.json in ${pluginPath}: missing \"hooks\" field`)\n return hooks\n }\n\n // Process each hook event\n for (const [eventName, matchers] of Object.entries(\n hooksConfig.hooks as Record<string, any[]>,\n )) {\n if (!Array.isArray(matchers)) continue\n\n for (const matcher of matchers) {\n if (!matcher.hooks || !Array.isArray(matcher.hooks)) continue\n\n for (const hookDef of matcher.hooks) {\n hooks.push({\n name: `${manifest.name}:${eventName}:${hooks.length}`,\n filePath: hooksJsonPath,\n config: {\n event: eventName as any,\n matcher: matcher.matcher,\n type: hookDef.type || 'command',\n command: hookDef.command,\n message: hookDef.prompt, // Claude Code uses \"prompt\", we use \"message\" internally\n blocking: hookDef.type === 'prompt',\n timeout: hookDef.timeout || 60,\n },\n pluginName: manifest.name,\n event: eventName as any,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (error) {\n console.error(`Error loading hooks from ${hooksJsonPath}:`, error)\n }\n\n return hooks\n}\n\n/**\n * Expand environment variables in a string\n * Supports:\n * - ${VAR} - expands to environment variable VAR\n * - ${VAR:-default} - expands to VAR or default if not set\n * - ${MINTO_PLUGIN_ROOT} - expands to plugin directory path\n */\nfunction expandEnvVars(value: string, pluginPath: string): string {\n // Replace ${MINTO_PLUGIN_ROOT} with plugin path\n let expanded = value.replace(/\\$\\{MINTO_PLUGIN_ROOT\\}/g, pluginPath)\n\n // Also support $MINTO_PLUGIN_ROOT without braces\n expanded = expanded.replace(/\\$MINTO_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Replace ${VAR} or ${VAR:-default} for other environment variables\n expanded = expanded.replace(\n /\\$\\{([^}:]+)(?::-([^}]*))?\\}/g,\n (match, varName, defaultValue) => {\n // Skip already processed plugin root variable\n if (varName === 'MINTO_PLUGIN_ROOT') {\n return match\n }\n return process.env[varName] || defaultValue || ''\n },\n )\n\n return expanded\n}\n\n/**\n * Expand environment variables in MCP server configuration\n */\nfunction expandServerConfig(config: any, pluginPath: string): any {\n const expanded: any = { ...config }\n\n // Expand string fields\n if (expanded.command) {\n expanded.command = expandEnvVars(expanded.command, pluginPath)\n }\n\n if (expanded.url) {\n expanded.url = expandEnvVars(expanded.url, pluginPath)\n }\n\n // Expand args array\n if (expanded.args && Array.isArray(expanded.args)) {\n expanded.args = expanded.args.map((arg: string) =>\n expandEnvVars(arg, pluginPath),\n )\n }\n\n // Expand env object\n if (expanded.env && typeof expanded.env === 'object') {\n expanded.env = Object.fromEntries(\n Object.entries(expanded.env).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n // Expand headers object\n if (expanded.headers && typeof expanded.headers === 'object') {\n expanded.headers = Object.fromEntries(\n Object.entries(expanded.headers).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n return expanded\n}\n\n/**\n * Load MCP servers from plugin\n *\n * Two configuration methods:\n * 1. .mcp.json file at plugin root\n * 2. Inline mcpServers in plugin.json manifest\n *\n * Inline configurations override .mcp.json for same server name.\n */\nfunction loadMCPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedMCPServer[] {\n const mcpServers: LoadedMCPServer[] = []\n\n // Step 1: Load .mcp.json if it exists\n const mcpJsonPath = join(pluginPath, '.mcp.json')\n let mcpJsonServers: Record<string, any> = {}\n\n if (existsSync(mcpJsonPath)) {\n try {\n const content = readFileSync(mcpJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.mcpServers && typeof parsed.mcpServers === 'object') {\n mcpJsonServers = parsed.mcpServers\n }\n } catch (error) {\n console.error(`Error loading .mcp.json from ${pluginPath}:`, error)\n }\n }\n\n // Step 2: Get inline MCP servers from manifest\n let inlineServers: Record<string, any> = {}\n\n if (\n manifest.mcpServers &&\n typeof manifest.mcpServers === 'object' &&\n !Array.isArray(manifest.mcpServers)\n ) {\n inlineServers = manifest.mcpServers as Record<string, any>\n }\n\n // Step 3: Merge (inline overrides .mcp.json)\n const allServers = { ...mcpJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedMCPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n // Expand environment variables\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n // Validate required fields based on server type\n const serverType = expandedConfig.type || 'stdio'\n\n if (serverType === 'stdio' && !expandedConfig.command) {\n console.warn(\n `MCP server \"${name}\" in ${manifest.name} is missing required \"command\" field for stdio type`,\n )\n continue\n }\n\n if (\n (serverType === 'http' || serverType === 'sse') &&\n !expandedConfig.url\n ) {\n console.warn(\n `MCP server \"${name}\" in ${manifest.name} is missing required \"url\" field for ${serverType} type`,\n )\n continue\n }\n\n mcpServers.push({\n name,\n filePath: existsSync(mcpJsonPath)\n ? mcpJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command || '',\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n timeout: expandedConfig.timeout,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n console.error(\n `Error loading MCP server \"${name}\" from ${manifest.name}:`,\n error,\n )\n }\n }\n\n return mcpServers\n}\n\n/**\n * Determine plugin source from path\n * Checks for marketplace metadata file to identify marketplace-installed plugins\n */\nfunction determinePluginSource(pluginPath: string): PluginSource {\n const home = homedir()\n const cwd = getCwd()\n\n // Check for marketplace metadata file\n const marketplaceMetaPath = join(pluginPath, '.marketplace-meta.json')\n if (existsSync(marketplaceMetaPath)) {\n try {\n const metaContent = readFileSync(marketplaceMetaPath, 'utf-8')\n const meta = JSON.parse(metaContent)\n if (meta.marketplace && meta.plugin) {\n return {\n type: 'marketplace',\n marketplace: meta.marketplace,\n name: meta.plugin,\n }\n }\n } catch (error) {\n // If metadata file is corrupted, fall through to local detection\n console.warn(\n `Failed to read marketplace metadata from ${marketplaceMetaPath}:`,\n error,\n )\n }\n }\n\n // Determine local source based on path\n if (pluginPath.startsWith(join(home, '.minto', 'plugins'))) {\n return { type: 'local', path: 'user-global' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins'))) {\n return { type: 'local', path: 'project' }\n } else {\n return { type: 'local', path: pluginPath }\n }\n}\n\n/**\n * Load a single plugin from a directory\n */\nexport function loadPlugin(pluginPath: string): LoadedPlugin {\n const manifest = loadManifest(pluginPath)\n const source = determinePluginSource(pluginPath)\n const pluginConfig = loadPluginConfig(pluginPath)\n\n const agents = loadAgents(pluginPath, manifest)\n const commands = loadCommands(pluginPath, manifest)\n const skills = loadSkills(pluginPath, manifest)\n const hooks = loadHooks(pluginPath, manifest)\n const mcpServers = loadMCPServers(pluginPath, manifest)\n\n return {\n manifest,\n name: manifest.name,\n location: pluginPath,\n source,\n agents,\n commands,\n skills,\n hooks,\n mcpServers,\n enabled: pluginConfig.enabled,\n config: pluginConfig.config,\n }\n}\n\n/**\n * Load all plugins from all discovery directories\n */\nexport function loadAllPlugins(): LoadedPlugin[] {\n const pluginPaths = discoverPluginPaths()\n const plugins: LoadedPlugin[] = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const plugin = loadPlugin(path)\n plugins.push(plugin)\n } catch (error) {\n if (error instanceof PluginError) {\n console.error(`Error loading plugin ${name}:`, error.message)\n } else {\n console.error(`Unexpected error loading plugin ${name}:`, error)\n }\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin by name\n */\nexport function getPlugin(name: string): LoadedPlugin | undefined {\n const pluginPaths = discoverPluginPaths()\n const pluginPath = pluginPaths.get(name)\n\n if (!pluginPath) return undefined\n\n try {\n return loadPlugin(pluginPath)\n } catch (error) {\n console.error(`Error loading plugin ${name}:`, error)\n return undefined\n }\n}\n\n/**\n * List all installed plugins\n */\nexport function listPlugins(): Array<{\n name: string\n path: string\n manifest?: PluginManifest\n}> {\n const pluginPaths = discoverPluginPaths()\n const plugins: Array<{\n name: string\n path: string\n manifest?: PluginManifest\n }> = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const manifest = loadManifest(path)\n plugins.push({ name, path, manifest })\n } catch (error) {\n plugins.push({ name, path })\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin config file path\n */\nfunction getPluginConfigPath(pluginPath: string): string {\n return join(pluginPath, '.plugin-config.json')\n}\n\n/**\n * Load plugin configuration\n */\nfunction loadPluginConfig(pluginPath: string): {\n enabled: boolean\n config: Record<string, any>\n} {\n const configPath = getPluginConfigPath(pluginPath)\n\n if (!existsSync(configPath)) {\n return { enabled: true, config: {} }\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n const data = JSON.parse(content)\n return {\n enabled: data.enabled !== false,\n config: data.config || {},\n }\n } catch (error) {\n console.error(`Error loading plugin config from ${configPath}:`, error)\n return { enabled: true, config: {} }\n }\n}\n\n/**\n * Save plugin configuration\n */\nfunction savePluginConfig(\n pluginPath: string,\n enabled: boolean,\n config: Record<string, any>,\n): void {\n const configPath = getPluginConfigPath(pluginPath)\n\n try {\n const data = { enabled, config }\n writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (error) {\n throw new PluginError(\n `Failed to save plugin config: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Enable a plugin\n */\nexport function enablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, true, plugin.config || {})\n}\n\n/**\n * Disable a plugin\n */\nexport function disablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, false, plugin.config || {})\n}\n\n/**\n * Toggle plugin enabled state\n */\nexport function togglePluginEnabled(pluginName: string): boolean {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n const newState = !plugin.enabled\n savePluginConfig(plugin.location, newState, plugin.config || {})\n return newState\n}\n\n/**\n * Update plugin configuration\n */\nexport function updatePluginConfig(\n pluginName: string,\n config: Record<string, any>,\n): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, plugin.enabled, config)\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Plugin Loader\n *\n * Discovers and loads plugins from Minto plugin directories.\n *\n * Directory Priority (later overrides earlier):\n * 1. ~/.minto/plugins/ (user global)\n * 2. ./.minto/plugins/ (project - highest priority)\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n mkdirSync,\n} from 'fs'\nimport { debug as debugLogger } from '@utils/debugLogger'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { validatePluginDirectory } from '@services/plugins/pluginValidation'\nimport {\n PluginManifest,\n PluginManifestSchema,\n LoadedPlugin,\n LoadedAgent,\n LoadedCommand,\n LoadedSkill,\n LoadedHook,\n LoadedMCPServer,\n LoadedLSPServer,\n PluginError,\n PluginErrorCode,\n PluginSource,\n} from '../types/plugin'\nimport { getCwd } from './state'\n\n/**\n * Extra plugin directories added via --plugin-dir CLI flag\n */\nlet extraPluginDirs: string[] = []\n\n/**\n * Add extra plugin directories (from --plugin-dir CLI flag)\n * These are merged with default directories, not replacing them.\n */\nexport function addExtraPluginDir(dir: string): void {\n const resolved = resolve(dir)\n if (!extraPluginDirs.includes(resolved)) {\n extraPluginDirs.push(resolved)\n }\n}\n\n/**\n * Get managed plugins directory (read-only, enterprise)\n */\nfunction getManagedPluginsDir(): string {\n if (process.platform === 'darwin') {\n return '/Library/Application Support/Minto/managed-plugins'\n }\n return '/etc/minto/managed-plugins'\n}\n\n/**\n * Plugin discovery directories in priority order\n */\nfunction getPluginDirectories(): string[] {\n const cwd = getCwd()\n const home = homedir()\n\n return [\n getManagedPluginsDir(), // Managed (enterprise, read-only, lowest)\n join(home, '.claude', 'plugins'), // User global (legacy)\n join(home, '.minto', 'plugins'), // User global\n join(cwd, '.claude', 'plugins'), // Project (legacy)\n join(cwd, '.minto', 'plugins'), // Project\n join(cwd, '.minto', 'plugins.local'), // Project local (gitignored)\n ...extraPluginDirs, // CLI --plugin-dir (highest priority)\n ]\n}\n\n/**\n * Find all plugin directories across all sources\n */\nfunction discoverPluginPaths(): Map<string, string> {\n const pluginPaths = new Map<string, string>() // name -> path\n const directories = getPluginDirectories()\n\n for (const dir of directories) {\n if (!existsSync(dir)) continue\n\n try {\n const entries = readdirSync(dir)\n\n for (const entry of entries) {\n const pluginPath = join(dir, entry)\n\n // Must be a directory\n if (!statSync(pluginPath).isDirectory()) continue\n\n // Must have plugin.json in .minto-plugin/, .claude-plugin/, or root\n const mintoManifestPath = join(\n pluginPath,\n '.minto-plugin',\n 'plugin.json',\n )\n const claudeManifestPath = join(\n pluginPath,\n '.claude-plugin',\n 'plugin.json',\n )\n const rootManifestPath = join(pluginPath, 'plugin.json')\n if (\n !existsSync(mintoManifestPath) &&\n !existsSync(claudeManifestPath) &&\n !existsSync(rootManifestPath)\n )\n continue\n\n // Later directories override earlier ones\n pluginPaths.set(entry, pluginPath)\n }\n } catch (error) {\n // Silently ignore errors\n }\n }\n\n return pluginPaths\n}\n\n/**\n * Load and validate plugin manifest\n *\n * Manifest locations (priority order):\n * 1. .minto-plugin/plugin.json\n * 2. plugin.json (root fallback)\n */\nfunction loadManifest(pluginPath: string): PluginManifest {\n const candidates = [\n join(pluginPath, '.minto-plugin', 'plugin.json'),\n join(pluginPath, '.claude-plugin', 'plugin.json'),\n join(pluginPath, 'plugin.json'),\n ]\n\n const existing = candidates.filter(p => existsSync(p))\n\n if (existing.length === 0) {\n throw new PluginError(\n `Plugin manifest not found. Tried:\\n${candidates.map(p => ` - ${p}`).join('\\n')}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n let lastError: unknown = null\n\n // Try each candidate in priority order; fall through on validation failure\n for (const manifestPath of existing) {\n try {\n const manifestContent = readFileSync(manifestPath, 'utf-8')\n const manifestData = JSON.parse(manifestContent)\n return PluginManifestSchema.parse(manifestData)\n } catch (error) {\n lastError = error\n // Continue to next candidate\n }\n }\n\n // All candidates failed\n throw new PluginError(\n `Invalid plugin manifest at ${existing[0]}: ${lastError instanceof Error ? lastError.message : String(lastError)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n lastError,\n )\n}\n\n/**\n * Load agents from plugin\n */\nfunction loadAgents(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedAgent[] {\n const agents: LoadedAgent[] = []\n const agentsDir = join(pluginPath, 'agents')\n\n // Load agents listed in manifest\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Agent file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(agentPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(agentPath, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading agent ${agentPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Also scan agents/ directory if it exists\n if (existsSync(agentsDir) && statSync(agentsDir).isDirectory()) {\n const agentFiles = readdirSync(agentsDir).filter(f => f.endsWith('.md'))\n\n for (const file of agentFiles) {\n const fullPath = join(agentsDir, file)\n\n // Skip if already loaded from manifest\n if (agents.some(a => a.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: promptContent } = matter(content)\n\n agents.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description || '',\n tools: data.tools,\n model: data.model,\n content: promptContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading agent ${file}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return agents\n}\n\n/**\n * Load commands from plugin\n */\nfunction loadCommands(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedCommand[] {\n const commands: LoadedCommand[] = []\n const commandsDir = join(pluginPath, 'commands')\n\n // Load commands listed in manifest\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Command file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(commandPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(commandPath, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading command ${commandPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Also scan commands/ directory if it exists\n if (existsSync(commandsDir) && statSync(commandsDir).isDirectory()) {\n const commandFiles = readdirSync(commandsDir).filter(f => f.endsWith('.md'))\n\n for (const file of commandFiles) {\n const fullPath = join(commandsDir, file)\n\n // Skip if already loaded from manifest\n if (commands.some(c => c.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: commandContent } = matter(content)\n\n commands.push({\n name: data.name || basename(file, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(file, '.md'),\n description: data.description,\n aliases: data.aliases,\n enabled: data.enabled !== false,\n hidden: data.hidden === true,\n progressMessage: data.progressMessage,\n argNames: data.argNames,\n 'allowed-tools': data['allowed-tools'],\n content: commandContent.trim(),\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading command ${file}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return commands\n}\n\n/**\n * Load skills from plugin\n *\n * Supports two patterns:\n * - Subdirectory: skills/skill-name/SKILL.md\n * - Flat: skills/skill-name.md\n */\nfunction loadSkills(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n const skillsDir = join(pluginPath, 'skills')\n\n // Load skills listed in manifest\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n\n if (!existsSync(fullPath)) {\n debugLogger.warn('PLUGIN_LOADER', `Skill file not found: ${fullPath}`)\n continue\n }\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(skillPath, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(skillPath, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill ${skillPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Auto-discover skills from skills/ directory if it exists\n if (existsSync(skillsDir) && statSync(skillsDir).isDirectory()) {\n const entries = readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n // Subdirectory pattern: skill-name/SKILL.md\n if (entry.isDirectory()) {\n const skillMdPath = join(skillsDir, entry.name, 'SKILL.md')\n\n if (existsSync(skillMdPath)) {\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === skillMdPath)) continue\n\n try {\n const content = readFileSync(skillMdPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || entry.name,\n filePath: skillMdPath,\n config: {\n name: data.name || entry.name,\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill from ${skillMdPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n // Flat pattern: .md files directly in skills/\n else if (entry.isFile() && entry.name.endsWith('.md')) {\n const fullPath = join(skillsDir, entry.name)\n\n // Skip if already loaded from manifest\n if (skills.some(s => s.filePath === fullPath)) continue\n\n try {\n const content = readFileSync(fullPath, 'utf-8')\n const { data, content: skillContent } = matter(content)\n\n skills.push({\n name: data.name || basename(entry.name, '.md'),\n filePath: fullPath,\n config: {\n name: data.name || basename(entry.name, '.md'),\n description: data.description || '',\n content: skillContent.trim(),\n },\n pluginName: manifest.name,\n source: 'plugin',\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading skill ${entry.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n }\n\n return skills\n}\n\n/**\n * Load hooks from plugin\n *\n * Uses hooks/hooks.json format\n */\nfunction loadHooks(pluginPath: string, manifest: PluginManifest): LoadedHook[] {\n const hooks: LoadedHook[] = []\n const hooksDir = join(pluginPath, 'hooks')\n const hooksJsonPath = join(hooksDir, 'hooks.json')\n\n // Check if hooks.json exists\n if (!existsSync(hooksJsonPath)) {\n return hooks\n }\n\n try {\n const content = readFileSync(hooksJsonPath, 'utf-8')\n const hooksConfig = JSON.parse(content)\n\n // Validate structure (basic validation, full validation in hook executor)\n if (!hooksConfig.hooks || typeof hooksConfig.hooks !== 'object') {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Invalid hooks.json in ${pluginPath}: missing \"hooks\" field`,\n )\n return hooks\n }\n\n // Process each hook event\n for (const [eventName, matchers] of Object.entries(\n hooksConfig.hooks as Record<string, any[]>,\n )) {\n if (!Array.isArray(matchers)) continue\n\n for (const matcher of matchers) {\n if (!matcher.hooks || !Array.isArray(matcher.hooks)) continue\n\n for (const hookDef of matcher.hooks) {\n hooks.push({\n name: `${manifest.name}:${eventName}:${hooks.length}`,\n filePath: hooksJsonPath,\n config: {\n event: eventName as any,\n matcher: matcher.matcher,\n type: hookDef.type || 'command',\n command: hookDef.command,\n prompt: hookDef.prompt,\n blocking: hookDef.type === 'prompt',\n timeout: hookDef.timeout || 60,\n },\n pluginName: manifest.name,\n event: eventName as any,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading hooks from ${hooksJsonPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n\n return hooks\n}\n\n/**\n * Expand environment variables in a string\n * Supports:\n * - ${VAR} - expands to environment variable VAR\n * - ${VAR:-default} - expands to VAR or default if not set\n * - ${MINTO_PLUGIN_ROOT} - expands to plugin directory path\n */\nfunction expandEnvVars(value: string, pluginPath: string): string {\n // Replace ${MINTO_PLUGIN_ROOT} with plugin path\n let expanded = value.replace(/\\$\\{MINTO_PLUGIN_ROOT\\}/g, pluginPath)\n\n // Also support $MINTO_PLUGIN_ROOT without braces\n expanded = expanded.replace(/\\$MINTO_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Support ${CLAUDE_PLUGIN_ROOT} for CC-synced plugins\n expanded = expanded.replace(/\\$\\{CLAUDE_PLUGIN_ROOT\\}/g, pluginPath)\n expanded = expanded.replace(/\\$CLAUDE_PLUGIN_ROOT(?![A-Za-z_])/g, pluginPath)\n\n // Replace ${VAR} or ${VAR:-default} for other environment variables\n expanded = expanded.replace(\n /\\$\\{([^}:]+)(?::-([^}]*))?\\}/g,\n (match, varName, defaultValue) => {\n // Skip already processed plugin root variables\n if (varName === 'MINTO_PLUGIN_ROOT' || varName === 'CLAUDE_PLUGIN_ROOT') {\n return match\n }\n return process.env[varName] || defaultValue || ''\n },\n )\n\n return expanded\n}\n\n/**\n * Expand environment variables in MCP server configuration\n */\nfunction expandServerConfig(config: any, pluginPath: string): any {\n const expanded: any = { ...config }\n\n // Expand string fields\n if (expanded.command) {\n expanded.command = expandEnvVars(expanded.command, pluginPath)\n }\n\n if (expanded.url) {\n expanded.url = expandEnvVars(expanded.url, pluginPath)\n }\n\n // Expand args array\n if (expanded.args && Array.isArray(expanded.args)) {\n expanded.args = expanded.args.map((arg: string) =>\n expandEnvVars(arg, pluginPath),\n )\n }\n\n // Expand env object\n if (expanded.env && typeof expanded.env === 'object') {\n expanded.env = Object.fromEntries(\n Object.entries(expanded.env).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n // Expand headers object\n if (expanded.headers && typeof expanded.headers === 'object') {\n expanded.headers = Object.fromEntries(\n Object.entries(expanded.headers).map(([k, v]) => [\n k,\n expandEnvVars(String(v), pluginPath),\n ]),\n )\n }\n\n return expanded\n}\n\n/**\n * Load MCP servers from plugin\n *\n * Two configuration methods:\n * 1. .mcp.json file at plugin root\n * 2. Inline mcpServers in plugin.json manifest\n *\n * Inline configurations override .mcp.json for same server name.\n */\nfunction loadMCPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedMCPServer[] {\n const mcpServers: LoadedMCPServer[] = []\n\n // Step 1: Load .mcp.json if it exists\n const mcpJsonPath = join(pluginPath, '.mcp.json')\n let mcpJsonServers: Record<string, any> = {}\n\n if (existsSync(mcpJsonPath)) {\n try {\n const content = readFileSync(mcpJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.mcpServers && typeof parsed.mcpServers === 'object') {\n mcpJsonServers = parsed.mcpServers\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading .mcp.json from ${pluginPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Step 2: Get inline MCP servers from manifest\n let inlineServers: Record<string, any> = {}\n\n if (\n manifest.mcpServers &&\n typeof manifest.mcpServers === 'object' &&\n !Array.isArray(manifest.mcpServers)\n ) {\n inlineServers = manifest.mcpServers as Record<string, any>\n }\n\n // Step 3: Merge (inline overrides .mcp.json)\n const allServers = { ...mcpJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedMCPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n // Expand environment variables\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n // Validate required fields based on server type\n const serverType = expandedConfig.type || 'stdio'\n\n if (serverType === 'stdio' && !expandedConfig.command) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `MCP server \"${name}\" in ${manifest.name} is missing required \"command\" field for stdio type`,\n )\n continue\n }\n\n if (\n (serverType === 'http' || serverType === 'sse') &&\n !expandedConfig.url\n ) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `MCP server \"${name}\" in ${manifest.name} is missing required \"url\" field for ${serverType} type`,\n )\n continue\n }\n\n mcpServers.push({\n name,\n filePath: existsSync(mcpJsonPath)\n ? mcpJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command || '',\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n timeout: expandedConfig.timeout,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading MCP server \"${name}\" from ${manifest.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return mcpServers\n}\n\n/**\n * Load LSP servers from plugin\n *\n * Two configuration methods:\n * 1. .lsp.json file at plugin root\n * 2. Inline lspServers in plugin.json manifest\n *\n * ${CLAUDE_PLUGIN_ROOT} / ${MINTO_PLUGIN_ROOT} is expanded in config values.\n */\nfunction loadLSPServers(\n pluginPath: string,\n manifest: PluginManifest,\n): LoadedLSPServer[] {\n const lspServers: LoadedLSPServer[] = []\n\n // Step 1: Load .lsp.json if it exists\n const lspJsonPath = join(pluginPath, '.lsp.json')\n let lspJsonServers: Record<string, any> = {}\n\n if (existsSync(lspJsonPath)) {\n try {\n const content = readFileSync(lspJsonPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n if (parsed.lspServers && typeof parsed.lspServers === 'object') {\n lspJsonServers = parsed.lspServers\n } else if (typeof parsed === 'object' && !Array.isArray(parsed)) {\n // Support flat format: { \"server-name\": { command: \"...\" } }\n lspJsonServers = parsed\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading .lsp.json from ${pluginPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Step 2: Get inline LSP servers from manifest (if any)\n const manifestData = manifest as any\n let inlineServers: Record<string, any> = {}\n\n if (\n manifestData.lspServers &&\n typeof manifestData.lspServers === 'object' &&\n !Array.isArray(manifestData.lspServers)\n ) {\n inlineServers = manifestData.lspServers\n }\n\n // Step 3: Merge (inline overrides .lsp.json)\n const allServers = { ...lspJsonServers, ...inlineServers }\n\n // Step 4: Convert to LoadedLSPServer format\n for (const [name, config] of Object.entries(allServers)) {\n try {\n const expandedConfig = expandServerConfig(config, pluginPath)\n\n if (!expandedConfig.command) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `LSP server \"${name}\" in ${manifest.name} is missing required \"command\" field`,\n )\n continue\n }\n\n lspServers.push({\n name,\n filePath: existsSync(lspJsonPath)\n ? lspJsonPath\n : join(pluginPath, 'plugin.json'),\n config: {\n command: expandedConfig.command,\n args: expandedConfig.args || [],\n env: expandedConfig.env || {},\n filePatterns: expandedConfig.filePatterns,\n languages: expandedConfig.languages,\n initializationOptions: expandedConfig.initializationOptions,\n },\n pluginName: manifest.name,\n })\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading LSP server \"${name}\" from ${manifest.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return lspServers\n}\n\n/**\n * Determine plugin source from path\n * Checks for marketplace metadata file to identify marketplace-installed plugins\n */\nfunction determinePluginSource(pluginPath: string): PluginSource {\n const home = homedir()\n const cwd = getCwd()\n\n // Check for CC sync metadata (Claude Code synced plugins)\n const ccSyncPath = join(pluginPath, '.cc-sync.json')\n if (existsSync(ccSyncPath)) {\n try {\n const ccMeta = JSON.parse(readFileSync(ccSyncPath, 'utf-8'))\n return {\n type: 'claude-code',\n marketplace: ccMeta.marketplace || '',\n name: ccMeta.name || basename(pluginPath),\n }\n } catch {\n // Fall through to other detection methods\n }\n }\n\n // Check for marketplace metadata file\n const marketplaceMetaPath = join(pluginPath, '.marketplace-meta.json')\n if (existsSync(marketplaceMetaPath)) {\n try {\n const metaContent = readFileSync(marketplaceMetaPath, 'utf-8')\n const meta = JSON.parse(metaContent)\n if (meta.marketplace && meta.plugin) {\n return {\n type: 'marketplace',\n marketplace: meta.marketplace,\n name: meta.plugin,\n }\n }\n } catch (error) {\n // If metadata file is corrupted, fall through to local detection\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Failed to read marketplace metadata from ${marketplaceMetaPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n // Determine local source based on path\n const managedDir = getManagedPluginsDir()\n if (pluginPath.startsWith(managedDir)) {\n return { type: 'local', path: 'managed' }\n } else if (pluginPath.startsWith(join(home, '.minto', 'plugins'))) {\n return { type: 'local', path: 'user-global' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins.local'))) {\n return { type: 'local', path: 'local' }\n } else if (pluginPath.startsWith(join(cwd, '.minto', 'plugins'))) {\n return { type: 'local', path: 'project' }\n } else {\n return { type: 'local', path: pluginPath }\n }\n}\n\n/**\n * Load plugin settings.json (CC agent settings format)\n *\n * CC format: { \"agent\": { \"defaultAgent\": \"...\", \"maxTurns\": 20 } }\n * Only agent-related settings fields are applied.\n *\n * Priority: plugin settings < user settings < project settings\n */\nexport function loadPluginSettings(\n pluginPath: string,\n): Record<string, any> | null {\n const settingsPaths = [\n join(pluginPath, '.minto-plugin', 'settings.json'),\n join(pluginPath, '.claude-plugin', 'settings.json'),\n join(pluginPath, 'settings.json'),\n ]\n\n for (const settingsPath of settingsPaths) {\n if (!existsSync(settingsPath)) continue\n\n try {\n const content = readFileSync(settingsPath, 'utf-8')\n const parsed = JSON.parse(content)\n\n // Only return agent-related settings (CC format)\n if (parsed.agent && typeof parsed.agent === 'object') {\n return parsed.agent\n }\n\n return parsed\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Failed to parse plugin settings from ${settingsPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n\n return null\n}\n\n/**\n * Load a single plugin from a directory\n */\nexport function loadPlugin(pluginPath: string): LoadedPlugin {\n const manifest = loadManifest(pluginPath)\n\n // Run directory validation for warnings (non-blocking)\n try {\n const validation = validatePluginDirectory(pluginPath)\n if (validation.warnings.length > 0) {\n for (const warning of validation.warnings) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Plugin \"${manifest.name}\": ${warning}`,\n )\n }\n }\n } catch {\n // Validation failed, continue with loading\n }\n\n const source = determinePluginSource(pluginPath)\n const pluginConfig = loadPluginConfig(pluginPath)\n\n const agents = loadAgents(pluginPath, manifest)\n const commands = loadCommands(pluginPath, manifest)\n const skills = loadSkills(pluginPath, manifest)\n const hooks = loadHooks(pluginPath, manifest)\n const mcpServers = loadMCPServers(pluginPath, manifest)\n const lspServers = loadLSPServers(pluginPath, manifest)\n const settings = loadPluginSettings(pluginPath)\n\n return {\n manifest,\n name: manifest.name,\n location: pluginPath,\n source,\n agents,\n commands,\n skills,\n hooks,\n mcpServers,\n lspServers,\n enabled: pluginConfig.enabled,\n config: pluginConfig.config,\n settings,\n }\n}\n\n/**\n * Load all plugins from all discovery directories\n */\nexport function loadAllPlugins(): LoadedPlugin[] {\n const pluginPaths = discoverPluginPaths()\n const plugins: LoadedPlugin[] = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const plugin = loadPlugin(path)\n plugins.push(plugin)\n } catch (error) {\n if (error instanceof PluginError) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin ${name}: ${error.message}`,\n )\n } else {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Unexpected error loading plugin ${name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n }\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin by name\n */\nexport function getPlugin(name: string): LoadedPlugin | undefined {\n const pluginPaths = discoverPluginPaths()\n const pluginPath = pluginPaths.get(name)\n\n if (!pluginPath) return undefined\n\n try {\n return loadPlugin(pluginPath)\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin ${name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return undefined\n }\n}\n\n/**\n * List all installed plugins\n */\nexport function listPlugins(): Array<{\n name: string\n path: string\n manifest?: PluginManifest\n}> {\n const pluginPaths = discoverPluginPaths()\n const plugins: Array<{\n name: string\n path: string\n manifest?: PluginManifest\n }> = []\n\n for (const [name, path] of pluginPaths) {\n try {\n const manifest = loadManifest(path)\n plugins.push({ name, path, manifest })\n } catch (error) {\n plugins.push({ name, path })\n }\n }\n\n return plugins\n}\n\n/**\n * Get plugin config file path\n */\nfunction getPluginConfigPath(pluginPath: string): string {\n return join(pluginPath, '.plugin-config.json')\n}\n\n/**\n * Load plugin configuration\n */\nfunction loadPluginConfig(pluginPath: string): {\n enabled: boolean\n config: Record<string, any>\n} {\n const configPath = getPluginConfigPath(pluginPath)\n\n if (!existsSync(configPath)) {\n return { enabled: true, config: {} }\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8')\n const data = JSON.parse(content)\n return {\n enabled: data.enabled !== false,\n config: data.config || {},\n }\n } catch (error) {\n debugLogger.warn(\n 'PLUGIN_LOADER',\n `Error loading plugin config from ${configPath}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return { enabled: true, config: {} }\n }\n}\n\n/**\n * Save plugin configuration\n */\nfunction savePluginConfig(\n pluginPath: string,\n enabled: boolean,\n config: Record<string, any>,\n): void {\n const configPath = getPluginConfigPath(pluginPath)\n\n try {\n const data = { enabled, config }\n writeFileSync(configPath, JSON.stringify(data, null, 2), 'utf-8')\n } catch (error) {\n throw new PluginError(\n `Failed to save plugin config: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n}\n\n/**\n * Enable a plugin\n */\nexport function enablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, true, plugin.config || {})\n}\n\n/**\n * Disable a plugin\n */\nexport function disablePlugin(pluginName: string): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, false, plugin.config || {})\n}\n\n/**\n * Toggle plugin enabled state\n */\nexport function togglePluginEnabled(pluginName: string): boolean {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n const newState = !plugin.enabled\n savePluginConfig(plugin.location, newState, plugin.config || {})\n return newState\n}\n\n/**\n * Update plugin configuration\n */\nexport function updatePluginConfig(\n pluginName: string,\n config: Record<string, any>,\n): void {\n const plugin = getPlugin(pluginName)\n\n if (!plugin) {\n throw new PluginError(\n `Plugin \"${pluginName}\" not found`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n savePluginConfig(plugin.location, plugin.enabled, config)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "fs";
|
|
2
|
+
import { join, dirname, isAbsolute } from "path";
|
|
3
|
+
import { tmpdir } from "os";
|
|
4
|
+
import { execFileNoThrow } from "./execFileNoThrow.js";
|
|
5
|
+
async function fetchRepo(source, targetDir) {
|
|
6
|
+
if (source.type === "github") {
|
|
7
|
+
return fetchGitHubRepo(source.repo, source.ref, targetDir);
|
|
8
|
+
}
|
|
9
|
+
const ghMatch = source.url.match(/github\.com[/:]([^/]+\/[^/.]+?)(?:\.git)?$/);
|
|
10
|
+
if (ghMatch) {
|
|
11
|
+
return fetchGitHubRepo(ghMatch[1], source.ref, targetDir);
|
|
12
|
+
}
|
|
13
|
+
await gitCloneFallback(source.url, source.ref, targetDir);
|
|
14
|
+
}
|
|
15
|
+
async function fetchGitHubRepo(repo, ref, targetDir) {
|
|
16
|
+
try {
|
|
17
|
+
await fetchGitHubTarball(repo, ref, targetDir);
|
|
18
|
+
} catch {
|
|
19
|
+
const url = `https://github.com/${repo}.git`;
|
|
20
|
+
await gitCloneFallback(url, ref, targetDir);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function fetchGitHubTarball(repo, ref, targetDir) {
|
|
24
|
+
const url = ref ? `https://api.github.com/repos/${repo}/tarball/${ref}` : `https://api.github.com/repos/${repo}/tarball`;
|
|
25
|
+
await downloadAndExtractTarball(url, targetDir);
|
|
26
|
+
}
|
|
27
|
+
async function downloadAndExtractTarball(url, targetDir) {
|
|
28
|
+
if (!existsSync(targetDir)) {
|
|
29
|
+
mkdirSync(targetDir, { recursive: true });
|
|
30
|
+
}
|
|
31
|
+
const tmpFile = join(
|
|
32
|
+
tmpdir(),
|
|
33
|
+
`minto-tarball-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`
|
|
34
|
+
);
|
|
35
|
+
try {
|
|
36
|
+
const response = await fetch(url, {
|
|
37
|
+
redirect: "follow",
|
|
38
|
+
signal: AbortSignal.timeout(6e4)
|
|
39
|
+
});
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error(`HTTP ${response.status} ${response.statusText}`);
|
|
42
|
+
}
|
|
43
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
44
|
+
writeFileSync(tmpFile, buffer);
|
|
45
|
+
const result = await execFileNoThrow("tar", [
|
|
46
|
+
"xzf",
|
|
47
|
+
tmpFile,
|
|
48
|
+
"-C",
|
|
49
|
+
targetDir,
|
|
50
|
+
"--strip-components=1"
|
|
51
|
+
]);
|
|
52
|
+
if (result.code !== 0) {
|
|
53
|
+
throw new Error(
|
|
54
|
+
`tar extraction failed: ${result.stderr || result.stdout}`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
} finally {
|
|
58
|
+
try {
|
|
59
|
+
if (existsSync(tmpFile)) {
|
|
60
|
+
rmSync(tmpFile, { force: true });
|
|
61
|
+
}
|
|
62
|
+
} catch {
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async function gitCloneFallback(url, ref, targetDir) {
|
|
67
|
+
await ensureGitEnv();
|
|
68
|
+
if (existsSync(targetDir)) {
|
|
69
|
+
rmSync(targetDir, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
const args = ["clone", "--depth", "1"];
|
|
72
|
+
if (ref) {
|
|
73
|
+
args.push("--branch", ref);
|
|
74
|
+
}
|
|
75
|
+
args.push(url, targetDir);
|
|
76
|
+
const result = await execFileNoThrow("git", args);
|
|
77
|
+
if (result.code !== 0) {
|
|
78
|
+
throw new Error(`Git clone failed: ${result.stderr || result.stdout}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
let gitEnvFixed = false;
|
|
82
|
+
async function ensureGitEnv() {
|
|
83
|
+
if (gitEnvFixed) return;
|
|
84
|
+
gitEnvFixed = true;
|
|
85
|
+
if (process.env.GIT_EXEC_PATH) return;
|
|
86
|
+
try {
|
|
87
|
+
const result = await execFileNoThrow("git", ["--exec-path"]);
|
|
88
|
+
const execPath = result.stdout.trim();
|
|
89
|
+
if (execPath && (execPath.startsWith("//") || !isAbsolute(execPath))) {
|
|
90
|
+
const whichResult = await execFileNoThrow("which", ["git"]);
|
|
91
|
+
const gitBin = whichResult.stdout.trim();
|
|
92
|
+
if (gitBin) {
|
|
93
|
+
const prefix = dirname(dirname(gitBin));
|
|
94
|
+
const fixedExecPath = join(prefix, "libexec", "git-core");
|
|
95
|
+
if (existsSync(fixedExecPath)) {
|
|
96
|
+
process.env.GIT_EXEC_PATH = fixedExecPath;
|
|
97
|
+
const templateDir = join(prefix, "share", "git-core", "templates");
|
|
98
|
+
if (existsSync(templateDir) && !process.env.GIT_TEMPLATE_DIR) {
|
|
99
|
+
process.env.GIT_TEMPLATE_DIR = templateDir;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
export {
|
|
108
|
+
fetchRepo
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=repoFetcher.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/repoFetcher.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Repo Fetcher\n *\n * Unified repository fetching utility that replaces git clone with HTTP tarball\n * downloads for GitHub sources (zero git dependency). Falls back to git clone\n * for non-GitHub URLs.\n *\n * GitHub tarball URL pattern: https://github.com/{owner}/{repo}/archive/{ref}.tar.gz\n * macOS/Linux systems have /usr/bin/tar built-in, so no extra dependencies needed.\n */\n\nimport { existsSync, mkdirSync, rmSync, writeFileSync } from 'fs'\nimport { join, dirname, isAbsolute } from 'path'\nimport { tmpdir } from 'os'\nimport { execFileNoThrow } from './execFileNoThrow'\n\n/**\n * Source descriptor for fetchRepo\n */\nexport type RepoSource =\n | { type: 'github'; repo: string; ref?: string }\n | { type: 'url'; url: string; ref?: string }\n\n/**\n * Fetch a repository into targetDir.\n *\n * - GitHub sources use HTTP tarball download (no git required)\n * - Non-GitHub URL sources fall back to git clone\n * - On GitHub tarball failure, falls back to git clone\n */\nexport async function fetchRepo(\n source: RepoSource,\n targetDir: string,\n): Promise<void> {\n if (source.type === 'github') {\n return fetchGitHubRepo(source.repo, source.ref, targetDir)\n }\n\n // URL source: check if it's a github.com URL\n const ghMatch = source.url.match(/github\\.com[/:]([^/]+\\/[^/.]+?)(?:\\.git)?$/)\n if (ghMatch) {\n return fetchGitHubRepo(ghMatch[1], source.ref, targetDir)\n }\n\n // Non-GitHub URL: git clone only\n await gitCloneFallback(source.url, source.ref, targetDir)\n}\n\n/**\n * Fetch a GitHub repo: try tarball first, fall back to git clone\n */\nasync function fetchGitHubRepo(\n repo: string,\n ref: string | undefined,\n targetDir: string,\n): Promise<void> {\n try {\n await fetchGitHubTarball(repo, ref, targetDir)\n } catch {\n // Tarball failed \u2014 fall back to git clone\n const url = `https://github.com/${repo}.git`\n await gitCloneFallback(url, ref, targetDir)\n }\n}\n\n/**\n * Download and extract a GitHub tarball into targetDir.\n *\n * GitHub tarballs contain a single top-level directory like `{repo}-{ref}/`.\n * We use `--strip-components=1` to remove that prefix.\n */\nasync function fetchGitHubTarball(\n repo: string,\n ref: string | undefined,\n targetDir: string,\n): Promise<void> {\n // Use GitHub API tarball endpoint \u2014 it auto-resolves the default branch\n // when no ref is given (unlike /archive/ which requires an explicit ref).\n const url = ref\n ? `https://api.github.com/repos/${repo}/tarball/${ref}`\n : `https://api.github.com/repos/${repo}/tarball`\n await downloadAndExtractTarball(url, targetDir)\n}\n\n/**\n * Download a .tar.gz URL to a temp file, then extract into targetDir\n * using the system `tar` command.\n */\nasync function downloadAndExtractTarball(\n url: string,\n targetDir: string,\n): Promise<void> {\n // Ensure target directory exists\n if (!existsSync(targetDir)) {\n mkdirSync(targetDir, { recursive: true })\n }\n\n const tmpFile = join(\n tmpdir(),\n `minto-tarball-${Date.now()}-${Math.random().toString(36).slice(2)}.tar.gz`,\n )\n\n try {\n // Download with fetch (built-in in Node 18+ / Bun)\n const response = await fetch(url, {\n redirect: 'follow',\n signal: AbortSignal.timeout(60_000),\n })\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`)\n }\n\n const buffer = Buffer.from(await response.arrayBuffer())\n writeFileSync(tmpFile, buffer)\n\n // Extract with system tar\n const result = await execFileNoThrow('tar', [\n 'xzf',\n tmpFile,\n '-C',\n targetDir,\n '--strip-components=1',\n ])\n\n if (result.code !== 0) {\n throw new Error(\n `tar extraction failed: ${result.stderr || result.stdout}`,\n )\n }\n } finally {\n // Clean up temp file\n try {\n if (existsSync(tmpFile)) {\n rmSync(tmpFile, { force: true })\n }\n } catch {\n // Ignore cleanup errors\n }\n }\n}\n\n/**\n * Git clone fallback for non-GitHub URLs.\n * Includes ensureGitEnv() to fix broken bundled git installations.\n */\nasync function gitCloneFallback(\n url: string,\n ref: string | undefined,\n targetDir: string,\n): Promise<void> {\n await ensureGitEnv()\n\n // git clone requires the target to not exist or be empty.\n // Remove it first (may contain partial tarball extraction artifacts).\n if (existsSync(targetDir)) {\n rmSync(targetDir, { recursive: true, force: true })\n }\n\n const args = ['clone', '--depth', '1']\n if (ref) {\n args.push('--branch', ref)\n }\n args.push(url, targetDir)\n\n const result = await execFileNoThrow('git', args)\n\n if (result.code !== 0) {\n throw new Error(`Git clone failed: ${result.stderr || result.stdout}`)\n }\n}\n\n/**\n * Ensure GIT_EXEC_PATH is correctly set in the environment.\n *\n * Some bundled git binaries (e.g., dugite inside Electron apps) have a broken\n * compiled-in exec-path that resolves to `//libexec/git-core` instead of an\n * absolute path. We detect this and derive the correct path from the git\n * binary's location.\n */\nlet gitEnvFixed = false\nasync function ensureGitEnv(): Promise<void> {\n if (gitEnvFixed) return\n gitEnvFixed = true\n\n // Skip if user already set GIT_EXEC_PATH\n if (process.env.GIT_EXEC_PATH) return\n\n try {\n const result = await execFileNoThrow('git', ['--exec-path'])\n const execPath = result.stdout.trim()\n\n // Detect broken path: starts with // or is not absolute\n if (execPath && (execPath.startsWith('//') || !isAbsolute(execPath))) {\n const whichResult = await execFileNoThrow('which', ['git'])\n const gitBin = whichResult.stdout.trim()\n\n if (gitBin) {\n const prefix = dirname(dirname(gitBin))\n const fixedExecPath = join(prefix, 'libexec', 'git-core')\n\n if (existsSync(fixedExecPath)) {\n process.env.GIT_EXEC_PATH = fixedExecPath\n\n const templateDir = join(prefix, 'share', 'git-core', 'templates')\n if (existsSync(templateDir) && !process.env.GIT_TEMPLATE_DIR) {\n process.env.GIT_TEMPLATE_DIR = templateDir\n }\n }\n }\n }\n } catch {\n // Best-effort; if detection fails, proceed without fixing\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const DEFAULT_TIMEOUT_MS = 3e4;
|
|
2
|
+
async function safeFetch(input, init, options) {
|
|
3
|
+
const {
|
|
4
|
+
timeout = DEFAULT_TIMEOUT_MS,
|
|
5
|
+
retries = 0,
|
|
6
|
+
retryBaseDelay = 2e3
|
|
7
|
+
} = options ?? {};
|
|
8
|
+
let lastError;
|
|
9
|
+
for (let attempt = 0; attempt <= retries; attempt++) {
|
|
10
|
+
try {
|
|
11
|
+
const fetchInit = applyTimeout(init, timeout);
|
|
12
|
+
return await fetch(input, fetchInit);
|
|
13
|
+
} catch (error) {
|
|
14
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
15
|
+
if (attempt < retries && isRetryable(lastError, init?.signal)) {
|
|
16
|
+
const delay = retryBaseDelay * Math.pow(2, attempt);
|
|
17
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
throw lastError;
|
|
23
|
+
}
|
|
24
|
+
function applyTimeout(init, timeout) {
|
|
25
|
+
if (timeout <= 0) {
|
|
26
|
+
return init ?? {};
|
|
27
|
+
}
|
|
28
|
+
const timeoutSignal = AbortSignal.timeout(timeout);
|
|
29
|
+
if (!init?.signal) {
|
|
30
|
+
return { ...init, signal: timeoutSignal };
|
|
31
|
+
}
|
|
32
|
+
const combined = AbortSignal.any([init.signal, timeoutSignal]);
|
|
33
|
+
return { ...init, signal: combined };
|
|
34
|
+
}
|
|
35
|
+
function isRetryable(error, callerSignal) {
|
|
36
|
+
if (callerSignal?.aborted) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
const msg = error.message.toLowerCase();
|
|
40
|
+
return error.name === "TimeoutError" || error.name === "AbortError" || msg.includes("timeout") || msg.includes("econnrefused") || msg.includes("econnreset") || msg.includes("enotfound") || msg.includes("fetch failed") || msg.includes("network");
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
safeFetch
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=safeFetch.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/safeFetch.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Lightweight fetch wrapper with timeout and optional retry.\n *\n * Usage:\n * await safeFetch(url, { timeout: 15000 })\n * await safeFetch(url, init, { timeout: 30000, retries: 2 })\n */\n\nconst DEFAULT_TIMEOUT_MS = 30_000\n\nexport interface SafeFetchOptions {\n /** Timeout in ms (default 30000). Set 0 to disable. */\n timeout?: number\n /** Number of retries on network/timeout error (default 0 = no retry). */\n retries?: number\n /** Base delay between retries in ms (default 2000). Doubles each attempt. */\n retryBaseDelay?: number\n}\n\n/**\n * Fetch with timeout and optional retry.\n * Timeout is implemented via AbortSignal.timeout() merged with any caller signal.\n */\nexport async function safeFetch(\n input: string | URL | Request,\n init?: RequestInit,\n options?: SafeFetchOptions,\n): Promise<Response> {\n const {\n timeout = DEFAULT_TIMEOUT_MS,\n retries = 0,\n retryBaseDelay = 2000,\n } = options ?? {}\n\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n const fetchInit = applyTimeout(init, timeout)\n return await fetch(input, fetchInit)\n } catch (error) {\n lastError = error instanceof Error ? error : new Error(String(error))\n\n // Only retry on network/timeout errors, not on abort by caller\n if (attempt < retries && isRetryable(lastError, init?.signal)) {\n const delay = retryBaseDelay * Math.pow(2, attempt)\n await new Promise(r => setTimeout(r, delay))\n continue\n }\n }\n }\n\n throw lastError!\n}\n\n/**\n * Merge a timeout AbortSignal with any existing signal from init.\n */\nfunction applyTimeout(\n init: RequestInit | undefined,\n timeout: number,\n): RequestInit {\n if (timeout <= 0) {\n return init ?? {}\n }\n\n const timeoutSignal = AbortSignal.timeout(timeout)\n\n if (!init?.signal) {\n return { ...init, signal: timeoutSignal }\n }\n\n // Combine caller signal + timeout signal\n const combined = AbortSignal.any([init.signal, timeoutSignal])\n return { ...init, signal: combined }\n}\n\n/**\n * Check if error is retryable (network/timeout, not user abort).\n */\nfunction isRetryable(\n error: Error,\n callerSignal: AbortSignal | null | undefined,\n): boolean {\n // If the caller's own signal aborted, don't retry\n if (callerSignal?.aborted) {\n return false\n }\n\n // Retry on timeout and network errors\n const msg = error.message.toLowerCase()\n return (\n error.name === 'TimeoutError' ||\n error.name === 'AbortError' ||\n msg.includes('timeout') ||\n msg.includes('econnrefused') ||\n msg.includes('econnreset') ||\n msg.includes('enotfound') ||\n msg.includes('fetch failed') ||\n msg.includes('network')\n )\n}\n"],
|
|
5
|
+
"mappings": "AAQA,MAAM,qBAAqB;AAe3B,eAAsB,UACpB,OACA,MACA,SACmB;AACnB,QAAM;AAAA,IACJ,UAAU;AAAA,IACV,UAAU;AAAA,IACV,iBAAiB;AAAA,EACnB,IAAI,WAAW,CAAC;AAEhB,MAAI;AAEJ,WAAS,UAAU,GAAG,WAAW,SAAS,WAAW;AACnD,QAAI;AACF,YAAM,YAAY,aAAa,MAAM,OAAO;AAC5C,aAAO,MAAM,MAAM,OAAO,SAAS;AAAA,IACrC,SAAS,OAAO;AACd,kBAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAGpE,UAAI,UAAU,WAAW,YAAY,WAAW,MAAM,MAAM,GAAG;AAC7D,cAAM,QAAQ,iBAAiB,KAAK,IAAI,GAAG,OAAO;AAClD,cAAM,IAAI,QAAQ,OAAK,WAAW,GAAG,KAAK,CAAC;AAC3C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM;AACR;AAKA,SAAS,aACP,MACA,SACa;AACb,MAAI,WAAW,GAAG;AAChB,WAAO,QAAQ,CAAC;AAAA,EAClB;AAEA,QAAM,gBAAgB,YAAY,QAAQ,OAAO;AAEjD,MAAI,CAAC,MAAM,QAAQ;AACjB,WAAO,EAAE,GAAG,MAAM,QAAQ,cAAc;AAAA,EAC1C;AAGA,QAAM,WAAW,YAAY,IAAI,CAAC,KAAK,QAAQ,aAAa,CAAC;AAC7D,SAAO,EAAE,GAAG,MAAM,QAAQ,SAAS;AACrC;AAKA,SAAS,YACP,OACA,cACS;AAET,MAAI,cAAc,SAAS;AACzB,WAAO;AAAA,EACT;AAGA,QAAM,MAAM,MAAM,QAAQ,YAAY;AACtC,SACE,MAAM,SAAS,kBACf,MAAM,SAAS,gBACf,IAAI,SAAS,SAAS,KACtB,IAAI,SAAS,cAAc,KAC3B,IAAI,SAAS,YAAY,KACzB,IAAI,SAAS,WAAW,KACxB,IAAI,SAAS,cAAc,KAC3B,IAAI,SAAS,SAAS;AAE1B;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -13,6 +13,7 @@ function parseSkillFile(filePath, source) {
|
|
|
13
13
|
const { data: frontmatter, content } = matter(fileContent);
|
|
14
14
|
const fileName = basename(filePath, ".md");
|
|
15
15
|
const name = frontmatter.name || (fileName === "SKILL" ? basename(dirname(filePath)) : fileName);
|
|
16
|
+
const hooks = parseSkillHooks(frontmatter.hooks);
|
|
16
17
|
const config = {
|
|
17
18
|
name,
|
|
18
19
|
description: frontmatter.description || "",
|
|
@@ -25,6 +26,12 @@ function parseSkillFile(filePath, source) {
|
|
|
25
26
|
model: frontmatter.model,
|
|
26
27
|
context: frontmatter.context,
|
|
27
28
|
agent: frontmatter.agent,
|
|
29
|
+
...hooks?.length && { hooks },
|
|
30
|
+
...frontmatter.license && { license: frontmatter.license },
|
|
31
|
+
...frontmatter.compatibility && {
|
|
32
|
+
compatibility: frontmatter.compatibility
|
|
33
|
+
},
|
|
34
|
+
...frontmatter.metadata && { metadata: frontmatter.metadata },
|
|
28
35
|
content: content.trim()
|
|
29
36
|
};
|
|
30
37
|
return {
|
|
@@ -39,6 +46,24 @@ function parseSkillFile(filePath, source) {
|
|
|
39
46
|
return null;
|
|
40
47
|
}
|
|
41
48
|
}
|
|
49
|
+
function parseSkillHooks(hooks) {
|
|
50
|
+
if (!hooks) return void 0;
|
|
51
|
+
if (!Array.isArray(hooks)) return void 0;
|
|
52
|
+
const parsed = [];
|
|
53
|
+
for (const h of hooks) {
|
|
54
|
+
if (!h || typeof h !== "object") continue;
|
|
55
|
+
if (!h.event) continue;
|
|
56
|
+
parsed.push({
|
|
57
|
+
event: h.event,
|
|
58
|
+
...h.matcher && { matcher: h.matcher },
|
|
59
|
+
...h.type && { type: h.type },
|
|
60
|
+
...h.command && { command: h.command },
|
|
61
|
+
...h.prompt && { prompt: h.prompt },
|
|
62
|
+
...h.timeout && { timeout: Number(h.timeout) }
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return parsed.length > 0 ? parsed : void 0;
|
|
66
|
+
}
|
|
42
67
|
function parseStringOrArray(value) {
|
|
43
68
|
if (!value) return void 0;
|
|
44
69
|
if (Array.isArray(value)) return value.map(String);
|
|
@@ -73,14 +98,26 @@ function scanStandaloneSkillsDirectory(dirPath, source) {
|
|
|
73
98
|
function loadStandaloneSkills() {
|
|
74
99
|
const home = homedir();
|
|
75
100
|
const cwd = getCwd();
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
|
|
101
|
+
const userClaudeDir = join(home, ".claude", "skills");
|
|
102
|
+
const userMintoDir = join(home, ".minto", "skills");
|
|
103
|
+
const projectClaudeDir = join(cwd, ".claude", "skills");
|
|
104
|
+
const projectMintoDir = join(cwd, ".minto", "skills");
|
|
105
|
+
const userClaudeSkills = scanStandaloneSkillsDirectory(userClaudeDir, "user");
|
|
106
|
+
const userMintoSkills = scanStandaloneSkillsDirectory(userMintoDir, "user");
|
|
107
|
+
const projectClaudeSkills = scanStandaloneSkillsDirectory(
|
|
108
|
+
projectClaudeDir,
|
|
109
|
+
"project"
|
|
110
|
+
);
|
|
111
|
+
const projectMintoSkills = scanStandaloneSkillsDirectory(
|
|
112
|
+
projectMintoDir,
|
|
81
113
|
"project"
|
|
82
114
|
);
|
|
83
|
-
return [
|
|
115
|
+
return [
|
|
116
|
+
...userClaudeSkills,
|
|
117
|
+
...userMintoSkills,
|
|
118
|
+
...projectClaudeSkills,
|
|
119
|
+
...projectMintoSkills
|
|
120
|
+
];
|
|
84
121
|
}
|
|
85
122
|
function loadAllSkills() {
|
|
86
123
|
if (skillsCache !== null) {
|
|
@@ -100,7 +137,12 @@ function loadAllSkills() {
|
|
|
100
137
|
const standaloneSkills = loadStandaloneSkills();
|
|
101
138
|
skillsCache = /* @__PURE__ */ new Map();
|
|
102
139
|
for (const skill of pluginSkills) {
|
|
103
|
-
|
|
140
|
+
if (skill.pluginName && skill.pluginName !== "standalone") {
|
|
141
|
+
const namespacedKey = `${skill.pluginName}:${skill.name}`;
|
|
142
|
+
skillsCache.set(namespacedKey, skill);
|
|
143
|
+
} else {
|
|
144
|
+
skillsCache.set(skill.name, skill);
|
|
145
|
+
}
|
|
104
146
|
}
|
|
105
147
|
for (const skill of standaloneSkills) {
|
|
106
148
|
skillsCache.set(skill.name, skill);
|
|
@@ -111,21 +153,37 @@ function getSkill(name) {
|
|
|
111
153
|
if (skillsCache === null) {
|
|
112
154
|
loadAllSkills();
|
|
113
155
|
}
|
|
114
|
-
|
|
156
|
+
const direct = skillsCache?.get(name);
|
|
157
|
+
if (direct) return direct;
|
|
158
|
+
if (!name.includes(":")) {
|
|
159
|
+
for (const [key, skill] of skillsCache ?? []) {
|
|
160
|
+
if (key.includes(":") && key.split(":").pop() === name) {
|
|
161
|
+
return skill;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return void 0;
|
|
166
|
+
}
|
|
167
|
+
function getSkillCacheKey(skill) {
|
|
168
|
+
if (skill.pluginName && skill.pluginName !== "standalone") {
|
|
169
|
+
return `${skill.pluginName}:${skill.name}`;
|
|
170
|
+
}
|
|
171
|
+
return skill.name;
|
|
115
172
|
}
|
|
116
173
|
async function loadSkillContent(skill) {
|
|
117
|
-
|
|
118
|
-
|
|
174
|
+
const cacheKey = getSkillCacheKey(skill);
|
|
175
|
+
if (contentCache.has(cacheKey)) {
|
|
176
|
+
return contentCache.get(cacheKey);
|
|
119
177
|
}
|
|
120
178
|
if (skill.config.content) {
|
|
121
|
-
contentCache.set(
|
|
179
|
+
contentCache.set(cacheKey, skill.config.content);
|
|
122
180
|
return skill.config.content;
|
|
123
181
|
}
|
|
124
182
|
try {
|
|
125
183
|
const fileContent = readFileSync(skill.filePath, "utf-8");
|
|
126
184
|
const { content } = matter(fileContent);
|
|
127
185
|
const trimmedContent = content.trim();
|
|
128
|
-
contentCache.set(
|
|
186
|
+
contentCache.set(cacheKey, trimmedContent);
|
|
129
187
|
skill.config.content = trimmedContent;
|
|
130
188
|
return trimmedContent;
|
|
131
189
|
} catch (error) {
|
|
@@ -134,6 +192,12 @@ async function loadSkillContent(skill) {
|
|
|
134
192
|
);
|
|
135
193
|
}
|
|
136
194
|
}
|
|
195
|
+
function getAllSkillEntries() {
|
|
196
|
+
if (skillsCache === null) {
|
|
197
|
+
loadAllSkills();
|
|
198
|
+
}
|
|
199
|
+
return Array.from(skillsCache?.entries() ?? []);
|
|
200
|
+
}
|
|
137
201
|
function searchSkills(query) {
|
|
138
202
|
const allSkills = loadAllSkills();
|
|
139
203
|
const lowerQuery = query.toLowerCase();
|
|
@@ -155,6 +219,7 @@ function getSkillCount() {
|
|
|
155
219
|
}
|
|
156
220
|
export {
|
|
157
221
|
clearSkillsCache,
|
|
222
|
+
getAllSkillEntries,
|
|
158
223
|
getSkill,
|
|
159
224
|
getSkillCount,
|
|
160
225
|
getSkillsByPlugin,
|