@within-7/minto 0.3.10 → 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.
Files changed (306) hide show
  1. package/dist/Tool.js.map +2 -2
  2. package/dist/commands/agents/AgentsCommand.js +2 -2
  3. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  4. package/dist/commands/ctx_viz.js +1 -1
  5. package/dist/commands/effort.js +87 -0
  6. package/dist/commands/effort.js.map +7 -0
  7. package/dist/commands/export.js +19 -9
  8. package/dist/commands/export.js.map +2 -2
  9. package/dist/commands/ide.js +18 -0
  10. package/dist/commands/ide.js.map +7 -0
  11. package/dist/commands/mcp-interactive.js +14 -8
  12. package/dist/commands/mcp-interactive.js.map +2 -2
  13. package/dist/commands/memory.js +168 -0
  14. package/dist/commands/memory.js.map +7 -0
  15. package/dist/commands/model.js +45 -2
  16. package/dist/commands/model.js.map +2 -2
  17. package/dist/commands/outputStyle.js +64 -0
  18. package/dist/commands/outputStyle.js.map +7 -0
  19. package/dist/commands/plugin/utils.js +33 -1
  20. package/dist/commands/plugin/utils.js.map +2 -2
  21. package/dist/commands/plugin.js +10 -1
  22. package/dist/commands/plugin.js.map +2 -2
  23. package/dist/commands/refreshCommands.js +2 -0
  24. package/dist/commands/refreshCommands.js.map +2 -2
  25. package/dist/commands/review.js +51 -0
  26. package/dist/commands/review.js.map +7 -0
  27. package/dist/commands/terminalSetup.js +6 -0
  28. package/dist/commands/terminalSetup.js.map +2 -2
  29. package/dist/commands/undo.js +8 -0
  30. package/dist/commands/undo.js.map +2 -2
  31. package/dist/commands/vim.js +22 -0
  32. package/dist/commands/vim.js.map +7 -0
  33. package/dist/commands.js +12 -0
  34. package/dist/commands.js.map +2 -2
  35. package/dist/components/HighlightedCode.js +1 -0
  36. package/dist/components/HighlightedCode.js.map +2 -2
  37. package/dist/components/ModelSelector/ModelSelector.js +250 -143
  38. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  39. package/dist/components/PromptInput.js +21 -6
  40. package/dist/components/PromptInput.js.map +2 -2
  41. package/dist/components/PulseLabel.js +44 -0
  42. package/dist/components/PulseLabel.js.map +7 -0
  43. package/dist/components/RequestStatusIndicator.js +1 -1
  44. package/dist/components/RequestStatusIndicator.js.map +1 -1
  45. package/dist/components/Spinner.js +12 -42
  46. package/dist/components/Spinner.js.map +3 -3
  47. package/dist/components/StartupStatus.js +57 -0
  48. package/dist/components/StartupStatus.js.map +7 -0
  49. package/dist/components/SubagentBlock.js +43 -6
  50. package/dist/components/SubagentBlock.js.map +2 -2
  51. package/dist/components/TabbedListView/TabBar.js +13 -8
  52. package/dist/components/TabbedListView/TabBar.js.map +2 -2
  53. package/dist/components/TabbedListView/TabbedListView.js +1 -1
  54. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  55. package/dist/components/TodoPanel.js +1 -1
  56. package/dist/components/TodoPanel.js.map +1 -1
  57. package/dist/components/ToolUseLoader.js +5 -0
  58. package/dist/components/ToolUseLoader.js.map +2 -2
  59. package/dist/components/TrustDialog.js +0 -2
  60. package/dist/components/TrustDialog.js.map +2 -2
  61. package/dist/components/messages/TaskInModuleView.js +1 -1
  62. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  63. package/dist/components/messages/TaskToolMessage.js +1 -1
  64. package/dist/components/messages/TaskToolMessage.js.map +2 -2
  65. package/dist/components/messages/UserPromptMessage.js +6 -1
  66. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  67. package/dist/constants/modelCapabilities.js +103 -18
  68. package/dist/constants/modelCapabilities.js.map +2 -2
  69. package/dist/constants/product.js +2 -0
  70. package/dist/constants/product.js.map +2 -2
  71. package/dist/constants/prompts/agentPrompt.js +30 -0
  72. package/dist/constants/prompts/agentPrompt.js.map +7 -0
  73. package/dist/constants/prompts/codeConventions.js +27 -0
  74. package/dist/constants/prompts/codeConventions.js.map +7 -0
  75. package/dist/constants/prompts/doingTasks.js +15 -0
  76. package/dist/constants/prompts/doingTasks.js.map +7 -0
  77. package/dist/constants/prompts/envInfo.js +17 -0
  78. package/dist/constants/prompts/envInfo.js.map +7 -0
  79. package/dist/constants/prompts/executingWithCare.js +17 -0
  80. package/dist/constants/prompts/executingWithCare.js.map +7 -0
  81. package/dist/constants/prompts/identity.js +10 -0
  82. package/dist/constants/prompts/identity.js.map +7 -0
  83. package/dist/constants/prompts/index.js +78 -0
  84. package/dist/constants/prompts/index.js.map +7 -0
  85. package/dist/constants/prompts/taskManagement.js +60 -0
  86. package/dist/constants/prompts/taskManagement.js.map +7 -0
  87. package/dist/constants/prompts/toneAndStyle.js +62 -0
  88. package/dist/constants/prompts/toneAndStyle.js.map +7 -0
  89. package/dist/constants/prompts/toolUsagePolicy.js +38 -0
  90. package/dist/constants/prompts/toolUsagePolicy.js.map +7 -0
  91. package/dist/constants/prompts.js +5 -176
  92. package/dist/constants/prompts.js.map +2 -2
  93. package/dist/constants/providerRegistry.js +235 -0
  94. package/dist/constants/providerRegistry.js.map +7 -0
  95. package/dist/constants/providers.js +35 -0
  96. package/dist/constants/providers.js.map +7 -0
  97. package/dist/context/PermissionContext.js +0 -1
  98. package/dist/context/PermissionContext.js.map +2 -2
  99. package/dist/context.js +87 -31
  100. package/dist/context.js.map +2 -2
  101. package/dist/core/backupHook.js +2 -2
  102. package/dist/core/backupHook.js.map +2 -2
  103. package/dist/core/config/defaults.js +4 -1
  104. package/dist/core/config/defaults.js.map +2 -2
  105. package/dist/core/config/schema.js +7 -1
  106. package/dist/core/config/schema.js.map +2 -2
  107. package/dist/core/costTracker.js +18 -0
  108. package/dist/core/costTracker.js.map +2 -2
  109. package/dist/core/index.js +0 -1
  110. package/dist/core/index.js.map +2 -2
  111. package/dist/core/tokenStatsManager.js +22 -4
  112. package/dist/core/tokenStatsManager.js.map +2 -2
  113. package/dist/entrypoints/cli.js +65 -84
  114. package/dist/entrypoints/cli.js.map +2 -2
  115. package/dist/hooks/useAgentTokenStats.js +1 -1
  116. package/dist/hooks/useAgentTokenStats.js.map +2 -2
  117. package/dist/hooks/useAgentTranscripts.js +2 -1
  118. package/dist/hooks/useAgentTranscripts.js.map +2 -2
  119. package/dist/hooks/useBackgroundShells.js +29 -0
  120. package/dist/hooks/useBackgroundShells.js.map +7 -0
  121. package/dist/hooks/useCanUseTool.js +1 -1
  122. package/dist/hooks/useCanUseTool.js.map +2 -2
  123. package/dist/hooks/useDeferredLoading.js +64 -0
  124. package/dist/hooks/useDeferredLoading.js.map +7 -0
  125. package/dist/hooks/useHookStatus.js +1 -1
  126. package/dist/hooks/useHookStatus.js.map +2 -2
  127. package/dist/hooks/useSessionTracking.js +55 -0
  128. package/dist/hooks/useSessionTracking.js.map +7 -0
  129. package/dist/hooks/useTerminalSize.js +21 -0
  130. package/dist/hooks/useTerminalSize.js.map +2 -2
  131. package/dist/hooks/useTextInput.js +1 -0
  132. package/dist/hooks/useTextInput.js.map +2 -2
  133. package/dist/hooks/useUnifiedCompletion.js +3 -2
  134. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  135. package/dist/i18n/locales/en.js +8 -9
  136. package/dist/i18n/locales/en.js.map +2 -2
  137. package/dist/i18n/locales/zh-CN.js +8 -9
  138. package/dist/i18n/locales/zh-CN.js.map +2 -2
  139. package/dist/i18n/types.js.map +1 -1
  140. package/dist/messages.js +41 -17
  141. package/dist/messages.js.map +2 -2
  142. package/dist/permissions.js +94 -1
  143. package/dist/permissions.js.map +2 -2
  144. package/dist/query.js +27 -19
  145. package/dist/query.js.map +2 -2
  146. package/dist/screens/REPL.js +83 -74
  147. package/dist/screens/REPL.js.map +2 -2
  148. package/dist/services/adapters/responsesAPI.js +6 -0
  149. package/dist/services/adapters/responsesAPI.js.map +2 -2
  150. package/dist/services/agentTeams/index.js +35 -0
  151. package/dist/services/agentTeams/index.js.map +7 -0
  152. package/dist/services/agentTeams/mailbox.js +114 -0
  153. package/dist/services/agentTeams/mailbox.js.map +7 -0
  154. package/dist/services/agentTeams/teamManager.js +149 -0
  155. package/dist/services/agentTeams/teamManager.js.map +7 -0
  156. package/dist/services/agentTeams/teamTaskStore.js +114 -0
  157. package/dist/services/agentTeams/teamTaskStore.js.map +7 -0
  158. package/dist/services/agentTeams/teammateSpawner.js +80 -0
  159. package/dist/services/agentTeams/teammateSpawner.js.map +7 -0
  160. package/dist/services/checkpointManager.js +16 -3
  161. package/dist/services/checkpointManager.js.map +2 -2
  162. package/dist/services/claude.js +19 -1728
  163. package/dist/services/claude.js.map +3 -3
  164. package/dist/services/gpt5ConnectionTest.js +4 -2
  165. package/dist/services/gpt5ConnectionTest.js.map +2 -2
  166. package/dist/services/hookExecutor.js +411 -127
  167. package/dist/services/hookExecutor.js.map +2 -2
  168. package/dist/services/llm/anthropicProvider.js +807 -0
  169. package/dist/services/llm/anthropicProvider.js.map +7 -0
  170. package/dist/services/llm/dispatch.js +218 -0
  171. package/dist/services/llm/dispatch.js.map +7 -0
  172. package/dist/services/llm/index.js +44 -0
  173. package/dist/services/llm/index.js.map +7 -0
  174. package/dist/services/llm/mintoContext.js +69 -0
  175. package/dist/services/llm/mintoContext.js.map +7 -0
  176. package/dist/services/llm/openaiProvider.js +622 -0
  177. package/dist/services/llm/openaiProvider.js.map +7 -0
  178. package/dist/services/llm/types.js +157 -0
  179. package/dist/services/llm/types.js.map +7 -0
  180. package/dist/services/mcpClient.js +183 -33
  181. package/dist/services/mcpClient.js.map +2 -2
  182. package/dist/services/notifier.js +14 -0
  183. package/dist/services/notifier.js.map +2 -2
  184. package/dist/services/oauth.js +4 -2
  185. package/dist/services/oauth.js.map +2 -2
  186. package/dist/services/openai.js +66 -56
  187. package/dist/services/openai.js.map +3 -3
  188. package/dist/services/outputStyles.js +102 -21
  189. package/dist/services/outputStyles.js.map +2 -2
  190. package/dist/services/plugins/skillMarketplace.js +4 -1
  191. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  192. package/dist/services/sentry.js +1 -1
  193. package/dist/services/sentry.js.map +2 -2
  194. package/dist/services/sessionMemory.js +16 -3
  195. package/dist/services/sessionMemory.js.map +2 -2
  196. package/dist/services/systemReminder.js +350 -3
  197. package/dist/services/systemReminder.js.map +2 -2
  198. package/dist/services/taskStore.js +19 -0
  199. package/dist/services/taskStore.js.map +2 -2
  200. package/dist/tools/ArchitectTool/ArchitectTool.js.map +1 -1
  201. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +1 -1
  202. package/dist/tools/BashOutputTool/BashOutputTool.js.map +1 -1
  203. package/dist/tools/BashTool/BashTool.js +28 -0
  204. package/dist/tools/BashTool/BashTool.js.map +2 -2
  205. package/dist/tools/FileEditTool/FileEditTool.js +1 -1
  206. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  207. package/dist/tools/FileReadTool/FileReadTool.js +14 -0
  208. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  209. package/dist/tools/FileWriteTool/FileWriteTool.js +3 -1
  210. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  211. package/dist/tools/GlobTool/GlobTool.js.map +1 -1
  212. package/dist/tools/GrepTool/GrepTool.js.map +1 -1
  213. package/dist/tools/KillShellTool/KillShellTool.js.map +1 -1
  214. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
  215. package/dist/tools/LspTool/LspTool.js +11 -2
  216. package/dist/tools/LspTool/LspTool.js.map +2 -2
  217. package/dist/tools/MCPTool/MCPTool.js.map +1 -1
  218. package/dist/tools/MemoryReadTool/MemoryReadTool.js +2 -1
  219. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  220. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +2 -1
  221. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  222. package/dist/tools/MultiEditTool/MultiEditTool.js.map +1 -1
  223. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +1 -1
  224. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +1 -1
  225. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +8 -2
  226. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  227. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +2 -0
  228. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  229. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +1 -1
  230. package/dist/tools/SlashCommandTool/SlashCommandTool.js +174 -18
  231. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +3 -3
  232. package/dist/tools/TaskCreateTool/TaskCreateTool.js.map +1 -1
  233. package/dist/tools/TaskGetTool/TaskGetTool.js.map +1 -1
  234. package/dist/tools/TaskListTool/TaskListTool.js.map +1 -1
  235. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +1 -1
  236. package/dist/tools/TaskStopTool/TaskStopTool.js.map +1 -1
  237. package/dist/tools/TaskTool/TaskTool.js +75 -5
  238. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  239. package/dist/tools/TaskTool/prompt.js +12 -6
  240. package/dist/tools/TaskTool/prompt.js.map +2 -2
  241. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +1 -1
  242. package/dist/tools/ThinkTool/ThinkTool.js.map +1 -1
  243. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +1 -1
  244. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +1 -1
  245. package/dist/tools/WebSearchTool/WebSearchTool.js.map +1 -1
  246. package/dist/tools/WebSearchTool/searchProviders.js +2 -1
  247. package/dist/tools/WebSearchTool/searchProviders.js.map +2 -2
  248. package/dist/tools/lsTool/lsTool.js.map +2 -2
  249. package/dist/tools/lsTool/prompt.js.map +1 -1
  250. package/dist/tools.js +14 -3
  251. package/dist/tools.js.map +2 -2
  252. package/dist/types/PermissionMode.js +21 -1
  253. package/dist/types/PermissionMode.js.map +2 -2
  254. package/dist/types/agentTeams.js +1 -0
  255. package/dist/types/agentTeams.js.map +7 -0
  256. package/dist/types/hooks.js +8 -2
  257. package/dist/types/hooks.js.map +2 -2
  258. package/dist/types/plugin.js +1 -1
  259. package/dist/types/plugin.js.map +2 -2
  260. package/dist/utils/agentLoader.js +25 -3
  261. package/dist/utils/agentLoader.js.map +2 -2
  262. package/dist/utils/animationManager.js +1 -1
  263. package/dist/utils/animationManager.js.map +2 -2
  264. package/dist/utils/ask.js +1 -1
  265. package/dist/utils/async.js +5 -1
  266. package/dist/utils/async.js.map +2 -2
  267. package/dist/utils/autoCompactCore.js +60 -0
  268. package/dist/utils/autoCompactCore.js.map +2 -2
  269. package/dist/utils/config.js +26 -128
  270. package/dist/utils/config.js.map +2 -2
  271. package/dist/utils/configSchema.js +227 -0
  272. package/dist/utils/configSchema.js.map +7 -0
  273. package/dist/utils/debugLogger.js.map +2 -2
  274. package/dist/utils/env.js +4 -3
  275. package/dist/utils/env.js.map +2 -2
  276. package/dist/utils/envConfig.js +34 -0
  277. package/dist/utils/envConfig.js.map +3 -3
  278. package/dist/utils/gpt5.js +146 -0
  279. package/dist/utils/gpt5.js.map +7 -0
  280. package/dist/utils/hookManager.js +374 -140
  281. package/dist/utils/hookManager.js.map +2 -2
  282. package/dist/utils/markdown.js +47 -0
  283. package/dist/utils/markdown.js.map +2 -2
  284. package/dist/utils/memoizeWithTTL.js +25 -0
  285. package/dist/utils/memoizeWithTTL.js.map +7 -0
  286. package/dist/utils/model.js +34 -9
  287. package/dist/utils/model.js.map +2 -2
  288. package/dist/utils/pluginInstaller.js +34 -5
  289. package/dist/utils/pluginInstaller.js.map +2 -2
  290. package/dist/utils/pluginLoader.js +201 -32
  291. package/dist/utils/pluginLoader.js.map +2 -2
  292. package/dist/utils/safeFetch.js +45 -0
  293. package/dist/utils/safeFetch.js.map +7 -0
  294. package/dist/utils/skillLoader.js +59 -6
  295. package/dist/utils/skillLoader.js.map +2 -2
  296. package/dist/utils/streamingState.js +52 -0
  297. package/dist/utils/streamingState.js.map +7 -0
  298. package/dist/utils/style.js +6 -3
  299. package/dist/utils/style.js.map +2 -2
  300. package/dist/utils/teamConfig.js +9 -3
  301. package/dist/utils/teamConfig.js.map +2 -2
  302. package/dist/utils/toolRiskClassification.js +0 -6
  303. package/dist/utils/toolRiskClassification.js.map +2 -2
  304. package/dist/version.js +2 -2
  305. package/dist/version.js.map +1 -1
  306. package/package.json +2 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/model.ts"],
4
- "sourcesContent": ["import { memoize } from 'lodash-es'\n\nimport { logError } from './log'\nimport {\n getGlobalConfig,\n ModelProfile,\n ModelPointerType,\n saveGlobalConfig,\n} from './config'\n\nexport const USE_BEDROCK = !!process.env.CLAUDE_CODE_USE_BEDROCK\nexport const USE_VERTEX = !!process.env.CLAUDE_CODE_USE_VERTEX\n\nexport interface ModelConfig {\n bedrock: string\n vertex: string\n firstParty: string\n}\n\nconst DEFAULT_MODEL_CONFIG: ModelConfig = {\n bedrock: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',\n vertex: 'claude-3-7-sonnet@20250219',\n firstParty: 'claude-sonnet-4-20250514',\n}\n\n/**\n * Helper to get the model config from defaults.\n */\nasync function getModelConfig(): Promise<ModelConfig> {\n return DEFAULT_MODEL_CONFIG\n}\n\nexport const getSlowAndCapableModel = memoize(async (): Promise<string> => {\n const config = await getGlobalConfig()\n\n // Use ModelManager for proper model resolution\n const modelManager = new ModelManager(config)\n const model = modelManager.getMainAgentModel()\n\n if (model) {\n return model\n }\n\n // Check if user has configured any models - if so, don't fallback to hardcoded defaults\n // This prevents the system from trying to use Claude models when user only has other providers\n const hasConfiguredModels = modelManager.hasConfiguredModels()\n if (hasConfiguredModels) {\n // User has models but none is set as main - this shouldn't happen normally\n // Return empty string to trigger proper error handling upstream\n throw new Error(\n 'No main model configured. Please use /model to set your default model.',\n )\n }\n\n // Only use hardcoded defaults for Bedrock/Vertex enterprise deployments\n // These are Anthropic-specific cloud deployments where Claude models are guaranteed\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n\n // For first-party (direct API) usage without any configured models,\n // throw an error to guide user to configure models\n throw new Error(\n 'No models configured. Please run /model to add and configure your AI models.',\n )\n})\n\n/**\n * Get context length for a model pointer type\n */\nexport function getModelContextLength(\n pointerType: ModelPointerType = 'main',\n): number {\n const config = getGlobalConfig()\n const modelManager = new ModelManager(config)\n\n // Get the model name based on pointer type\n let modelName: string | null = null\n switch (pointerType) {\n case 'main':\n modelName = modelManager.getMainAgentModel()\n break\n case 'task':\n modelName = modelManager.getTaskToolModel()\n break\n default:\n modelName = modelManager.getMainAgentModel()\n }\n\n // Find the profile for this model\n if (modelName) {\n const profile = config.modelProfiles?.find(\n (p: ModelProfile) => p.modelName === modelName && p.isActive,\n )\n if (profile && profile.contextLength) {\n return profile.contextLength\n }\n }\n\n // Default fallback (Claude Sonnet context length)\n return 200000\n}\n\nexport async function isDefaultSlowAndCapableModel(): Promise<boolean> {\n try {\n const configuredModel = await getSlowAndCapableModel()\n return (\n !process.env.ANTHROPIC_MODEL ||\n process.env.ANTHROPIC_MODEL === configuredModel\n )\n } catch {\n // If no model is configured, we're using \"default\" (which means none)\n return !process.env.ANTHROPIC_MODEL\n }\n}\n\n/**\n * Get the region for a specific Vertex model\n * Checks for hardcoded model-specific environment variables first,\n * then falls back to CLOUD_ML_REGION env var or default region\n */\nexport function getVertexRegionForModel(\n model: string | undefined,\n): string | undefined {\n if (model?.startsWith('claude-3-5-haiku')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_HAIKU\n } else if (model?.startsWith('claude-3-5-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_SONNET\n } else if (model?.startsWith('claude-3-7-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_7_SONNET\n }\n}\n\n/**\n * Comprehensive ModelManager class for centralized model selection and management.\n * Provides a clean interface for model selection across the application.\n */\nexport class ModelManager {\n private config: any // Using any to handle legacy properties\n private modelProfiles: ModelProfile[]\n\n constructor(config: any) {\n this.config = config\n this.modelProfiles = config.modelProfiles || []\n }\n\n /**\n * Get the current terminal model (for interactive CLI sessions)\n */\n getCurrentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Get the main agent default model (for non-terminal mode and MCP calls)\n */\n getMainAgentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to first active profile\n const activeProfile = this.modelProfiles.find(p => p.isActive)\n if (activeProfile) {\n return activeProfile.modelName\n }\n\n return null\n }\n\n /**\n * Get the task tool default model (for Task tool sub-agents)\n */\n getTaskToolModel(): string | null {\n // Use task pointer from new ModelProfile system\n const taskModelName = this.config.modelPointers?.task\n if (taskModelName) {\n const profile = this.findModelProfile(taskModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Switch to the next available model with enhanced context overflow handling\n * If target model can't handle current context, shows warning and reverts after delay\n *\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Object with detailed model name and context status information\n */\n switchToNextModelWithContextCheck(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n previousModelName: string | null\n contextOverflow: boolean\n usagePercentage: number\n // Enhanced feedback fields\n currentContextTokens: number\n targetContextLimit: number\n skippedModels: Array<{ name: string; reason: string }>\n totalAvailableModels: number\n } {\n // Use ALL configured models, not just active ones\n const allProfiles = this.getAllConfiguredModels()\n if (allProfiles.length === 0) {\n return {\n success: false,\n modelName: null,\n previousModelName: null,\n contextOverflow: false,\n usagePercentage: 0,\n currentContextTokens,\n targetContextLimit: 0,\n skippedModels: [],\n totalAvailableModels: 0,\n }\n }\n\n // Sort by createdAt for consistent cycling order (don't use lastUsed)\n // Using lastUsed causes the order to change each time, preventing proper cycling\n allProfiles.sort((a, b) => {\n return a.createdAt - b.createdAt // Oldest first for consistent order\n })\n\n const currentMainModelName = this.config.modelPointers?.main\n const currentModel = currentMainModelName\n ? this.findModelProfile(currentMainModelName)\n : null\n const previousModelName = currentModel?.name || null\n\n if (!currentMainModelName) {\n // No current main model, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName: null,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n currentContextTokens,\n targetContextLimit: firstModel.contextLength,\n skippedModels: [],\n totalAvailableModels: allProfiles.length,\n }\n }\n\n // Find current model index in ALL models\n const currentIndex = allProfiles.findIndex(\n p => p.modelName === currentMainModelName,\n )\n if (currentIndex === -1) {\n // Current model not found, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n currentContextTokens,\n targetContextLimit: firstModel.contextLength,\n skippedModels: [],\n totalAvailableModels: allProfiles.length,\n }\n }\n\n // Check if only one model is available\n if (allProfiles.length === 1) {\n const currentModel = allProfiles[0]\n return {\n success: false,\n modelName: null,\n previousModelName,\n contextOverflow: false,\n usagePercentage: 0,\n currentContextTokens,\n targetContextLimit: currentModel?.contextLength || 0,\n skippedModels: [],\n totalAvailableModels: 1,\n }\n }\n\n // Get next model in cycle (from ALL models)\n const nextIndex = (currentIndex + 1) % allProfiles.length\n const nextModel = allProfiles[nextIndex]\n\n // Activate the model if it's not already active\n const wasInactive = !nextModel.isActive\n if (!nextModel.isActive) {\n nextModel.isActive = true\n }\n\n // Analyze context compatibility for next model\n const analysis = this.analyzeContextCompatibility(\n nextModel,\n currentContextTokens,\n )\n\n // Always switch to next model, but return context status\n this.setPointer('main', nextModel.modelName)\n this.updateLastUsed(nextModel.modelName)\n\n // Save configuration if we activated a new model\n if (wasInactive) {\n this.saveConfig()\n }\n\n return {\n success: true,\n modelName: nextModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n currentContextTokens,\n targetContextLimit: nextModel.contextLength,\n skippedModels: [], // In simple round-robin, no models are skipped\n totalAvailableModels: allProfiles.length,\n }\n }\n\n /**\n * Simple model switching for UI components (compatible interface)\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Compatible interface for PromptInput component\n */\n switchToNextModel(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n blocked?: boolean\n message?: string\n } {\n // Use the enhanced context check method for consistency\n const result = this.switchToNextModelWithContextCheck(currentContextTokens)\n\n if (!result.success) {\n const allModels = this.getAllConfiguredModels()\n if (allModels.length === 0) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: '\u274C No models configured. Use /model to add models.',\n }\n } else if (allModels.length === 1) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: `\u26A0\uFE0F Only one model configured (${allModels[0].modelName}). Use /model to add more models for switching.`,\n }\n }\n }\n\n // Convert the detailed result to the simple interface\n const currentModel = this.findModelProfile(this.config.modelPointers?.main)\n const allModels = this.getAllConfiguredModels()\n const currentIndex = allModels.findIndex(\n m => m.modelName === currentModel?.modelName,\n )\n const totalModels = allModels.length\n\n return {\n success: result.success,\n modelName: result.modelName,\n blocked: result.contextOverflow,\n message: result.success\n ? result.contextOverflow\n ? `\u26A0\uFE0F Context usage: ${result.usagePercentage.toFixed(1)}% - ${result.modelName}`\n : `\u2705 Switched to ${result.modelName} (${currentIndex + 1}/${totalModels})${currentModel?.provider ? ` [${currentModel.provider}]` : ''}`\n : `\u274C Failed to switch models`,\n }\n }\n\n /**\n * Revert to previous model (used when context overflow requires rollback)\n */\n revertToPreviousModel(previousModelName: string): boolean {\n const previousModel = this.modelProfiles.find(\n p => p.name === previousModelName && p.isActive,\n )\n if (!previousModel) {\n return false\n }\n\n this.setPointer('main', previousModel.modelName)\n this.updateLastUsed(previousModel.modelName)\n return true\n }\n\n /**\n * Enhanced context validation with different severity levels\n */\n analyzeContextCompatibility(\n model: ModelProfile,\n contextTokens: number,\n ): {\n compatible: boolean\n severity: 'safe' | 'warning' | 'critical'\n usagePercentage: number\n recommendation: string\n } {\n const usableContext = Math.floor(model.contextLength * 0.8) // Reserve 20% for output\n const usagePercentage = (contextTokens / usableContext) * 100\n\n if (usagePercentage <= 70) {\n return {\n compatible: true,\n severity: 'safe',\n usagePercentage,\n recommendation: 'Full context preserved',\n }\n } else if (usagePercentage <= 90) {\n return {\n compatible: true,\n severity: 'warning',\n usagePercentage,\n recommendation: 'Context usage high, consider compression',\n }\n } else {\n return {\n compatible: false,\n severity: 'critical',\n usagePercentage,\n recommendation: 'Auto-compression or message truncation required',\n }\n }\n }\n\n /**\n * Switch to next model with enhanced context analysis\n */\n switchToNextModelWithAnalysis(currentContextTokens: number = 0): {\n modelName: string | null\n contextAnalysis: ReturnType<typeof this.analyzeContextCompatibility> | null\n requiresCompression: boolean\n estimatedTokensAfterSwitch: number\n } {\n const result = this.switchToNextModel(currentContextTokens)\n\n if (!result.success || !result.modelName) {\n return {\n modelName: null,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: 0,\n }\n }\n\n const newModel = this.getModel('main')\n if (!newModel) {\n return {\n modelName: result.modelName,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n const analysis = this.analyzeContextCompatibility(\n newModel,\n currentContextTokens,\n )\n\n return {\n modelName: result.modelName,\n contextAnalysis: analysis,\n requiresCompression: analysis.severity === 'critical',\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n /**\n * Check if a model can handle the given context size (legacy method)\n */\n canModelHandleContext(model: ModelProfile, contextTokens: number): boolean {\n const analysis = this.analyzeContextCompatibility(model, contextTokens)\n return analysis.compatible\n }\n\n /**\n * Find the first model that can handle the given context size\n */\n findModelWithSufficientContext(\n models: ModelProfile[],\n contextTokens: number,\n ): ModelProfile | null {\n return (\n models.find(model => this.canModelHandleContext(model, contextTokens)) ||\n null\n )\n }\n\n /**\n * Unified model getter for different contexts\n */\n getModelForContext(\n contextType: 'terminal' | 'main-agent' | 'task-tool',\n ): string | null {\n switch (contextType) {\n case 'terminal':\n return this.getCurrentModel()\n case 'main-agent':\n return this.getMainAgentModel()\n case 'task-tool':\n return this.getTaskToolModel()\n default:\n return this.getMainAgentModel()\n }\n }\n\n /**\n * Get all active model profiles\n */\n getActiveModelProfiles(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Check if any models are configured\n */\n hasConfiguredModels(): boolean {\n return this.getActiveModelProfiles().length > 0\n }\n\n // New model pointer system methods\n\n /**\n * Get model by pointer type (main, task, reasoning, quick)\n */\n getModel(pointer: ModelPointerType): ModelProfile | null {\n const pointerId = this.config.modelPointers?.[pointer]\n if (!pointerId) {\n return this.getDefaultModel()\n }\n\n const profile = this.findModelProfile(pointerId)\n return profile && profile.isActive ? profile : this.getDefaultModel()\n }\n\n /**\n * Get model name by pointer type\n */\n getModelName(pointer: ModelPointerType): string | null {\n const profile = this.getModel(pointer)\n return profile ? profile.modelName : null\n }\n\n /**\n * Get reasoning model (with fallback)\n */\n getReasoningModel(): string | null {\n return this.getModelName('reasoning') || this.getModelName('main')\n }\n\n /**\n * Get quick model (with fallback)\n */\n getQuickModel(): string | null {\n return (\n this.getModelName('quick') ||\n this.getModelName('task') ||\n this.getModelName('main')\n )\n }\n\n /**\n * Get compact model for context compression/summarization (with fallback)\n * Fallback chain: compact -> quick -> task -> main\n */\n getCompactModel(): string | null {\n return (\n this.getModelName('compact') ||\n this.getModelName('quick') ||\n this.getModelName('task') ||\n this.getModelName('main')\n )\n }\n\n /**\n * Add a new model profile with duplicate validation\n */\n async addModel(\n config: Omit<ModelProfile, 'createdAt' | 'isActive'>,\n ): Promise<string> {\n // Check for duplicate modelName (actual model identifier)\n const existingByModelName = this.modelProfiles.find(\n p => p.modelName === config.modelName,\n )\n if (existingByModelName) {\n throw new Error(\n `Model with modelName '${config.modelName}' already exists: ${existingByModelName.name}`,\n )\n }\n\n // Check for duplicate friendly name\n const existingByName = this.modelProfiles.find(p => p.name === config.name)\n if (existingByName) {\n throw new Error(`Model with name '${config.name}' already exists`)\n }\n\n const newModel: ModelProfile = {\n ...config,\n createdAt: Date.now(),\n isActive: true,\n }\n\n this.modelProfiles.push(newModel)\n\n // If this is the first model, set all pointers to it\n if (this.modelProfiles.length === 1) {\n this.config.modelPointers = {\n main: config.modelName,\n task: config.modelName,\n reasoning: config.modelName,\n quick: config.modelName,\n compact: config.modelName,\n }\n this.config.defaultModelName = config.modelName\n }\n\n this.saveConfig()\n return config.modelName\n }\n\n /**\n * Set model pointer assignment\n */\n setPointer(pointer: ModelPointerType, modelName: string): void {\n if (!this.findModelProfile(modelName)) {\n throw new Error(`Model '${modelName}' not found`)\n }\n\n if (!this.config.modelPointers) {\n this.config.modelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }\n }\n\n this.config.modelPointers[pointer] = modelName\n this.saveConfig()\n }\n\n /**\n * Get all active models for pointer assignment\n */\n getAvailableModels(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Get all configured models (both active and inactive) for switching\n */\n getAllConfiguredModels(): ModelProfile[] {\n return this.modelProfiles\n }\n\n /**\n * Get all available model names (modelName field) - active only\n */\n getAllAvailableModelNames(): string[] {\n return this.getAvailableModels().map(p => p.modelName)\n }\n\n /**\n * Get all configured model names (both active and inactive)\n */\n getAllConfiguredModelNames(): string[] {\n return this.getAllConfiguredModels().map(p => p.modelName)\n }\n\n /**\n * Debug method to get detailed model switching information\n */\n getModelSwitchingDebugInfo(): {\n totalModels: number\n activeModels: number\n inactiveModels: number\n currentMainModel: string | null\n availableModels: Array<{\n name: string\n modelName: string\n provider: string\n isActive: boolean\n lastUsed?: number\n }>\n modelPointers: Record<string, string | undefined>\n } {\n const availableModels = this.getAvailableModels()\n const currentMainModelName = this.config.modelPointers?.main\n\n return {\n totalModels: this.modelProfiles.length,\n activeModels: availableModels.length,\n inactiveModels: this.modelProfiles.length - availableModels.length,\n currentMainModel: currentMainModelName || null,\n availableModels: this.modelProfiles.map(p => ({\n name: p.name,\n modelName: p.modelName,\n provider: p.provider,\n isActive: p.isActive,\n lastUsed: p.lastUsed,\n })),\n modelPointers: this.config.modelPointers || {},\n }\n }\n\n /**\n * Remove a model profile\n */\n removeModel(modelName: string): void {\n this.modelProfiles = this.modelProfiles.filter(\n p => p.modelName !== modelName,\n )\n\n // Clean up pointers that reference deleted model\n if (this.config.modelPointers) {\n Object.keys(this.config.modelPointers).forEach(pointer => {\n if (\n this.config.modelPointers[pointer as ModelPointerType] === modelName\n ) {\n this.config.modelPointers[pointer as ModelPointerType] =\n this.config.defaultModelName || ''\n }\n })\n }\n\n this.saveConfig()\n }\n\n /**\n * Get default model profile\n */\n private getDefaultModel(): ModelProfile | null {\n if (this.config.defaultModelId) {\n const profile = this.findModelProfile(this.config.defaultModelId)\n if (profile && profile.isActive) {\n return profile\n }\n }\n return this.modelProfiles.find(p => p.isActive) || null\n }\n\n /**\n * Save configuration changes\n * Note: This updates the global config file. The singleton instance\n * is automatically refreshed to avoid stale data issues.\n */\n private saveConfig(): void {\n const updatedConfig = {\n ...this.config,\n modelProfiles: this.modelProfiles,\n }\n saveGlobalConfig(updatedConfig)\n\n // Refresh the global singleton to avoid stale data race conditions\n // This ensures any subsequent getModelManager() calls get fresh data\n refreshGlobalModelManagerInstance(this)\n }\n\n /**\n * Get a fallback model when no specific model is configured\n */\n async getFallbackModel(): Promise<string> {\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n return modelConfig.firstParty\n }\n\n /**\n * \u7EDF\u4E00\u7684\u6A21\u578B\u89E3\u6790\u65B9\u6CD5\uFF1A\u652F\u6301\u6307\u9488\u3001model ID \u548C\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n * @param modelParam - \u53EF\u4EE5\u662F\u6A21\u578B\u6307\u9488 ('main', 'task', etc.)\u3001\u5185\u90E8model ID \u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0 ('gpt-4o', 'claude-3-5-sonnet')\n * @returns ModelProfile \u6216 null\n */\n resolveModel(modelParam: string | ModelPointerType): ModelProfile | null {\n // \u9996\u5148\u68C0\u67E5\u662F\u5426\u662F\u6A21\u578B\u6307\u9488\n if (\n ['main', 'task', 'reasoning', 'quick', 'compact'].includes(modelParam)\n ) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (pointerId) {\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u4E24\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(pointerId) // \u6309\u5185\u90E8ID\u67E5\u627E\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId) // \u6309\u771F\u5B9E\u6A21\u578B\u540D\u67E5\u627E\n }\n if (profile && profile.isActive) {\n return profile\n }\n }\n // \u6307\u9488\u65E0\u6548\u65F6\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n // \u4E0D\u662F\u6307\u9488\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n // 1. \u5C1D\u8BD5\u6309\u5185\u90E8 model ID \u67E5\u627E\n let profile = this.findModelProfile(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 2. \u5C1D\u8BD5\u6309\u771F\u5B9E\u6A21\u578B\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByModelName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 3. \u5C1D\u8BD5\u6309\u53CB\u597D\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // \u6240\u6709\u67E5\u627E\u65B9\u5F0F\u90FD\u5931\u8D25\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n /**\n * \u89E3\u6790\u6A21\u578B\u53C2\u6570\u5E76\u8FD4\u56DE\u5B8C\u6574\u4FE1\u606F\n */\n resolveModelWithInfo(modelParam: string | ModelPointerType): {\n success: boolean\n profile: ModelProfile | null\n error?: string\n } {\n const isPointer = [\n 'main',\n 'task',\n 'reasoning',\n 'quick',\n 'compact',\n ].includes(modelParam)\n\n if (isPointer) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (!pointerId) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' is not configured. Use /model to set up models.`,\n }\n }\n\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n let profile = this.findModelProfile(pointerId)\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' points to invalid model '${pointerId}'. Use /model to reconfigure.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' (pointed by '${modelParam}') is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n } else {\n // \u76F4\u63A5\u7684 model ID \u6216\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(modelParam)\n if (!profile) {\n profile = this.findModelProfileByModelName(modelParam)\n }\n if (!profile) {\n profile = this.findModelProfileByName(modelParam)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model '${modelParam}' not found. Use /model to add models.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n }\n }\n\n // Private helper methods\n private findModelProfile(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n private findModelProfileByModelName(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n private findModelProfileByName(name: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.name === name) || null\n }\n\n private updateLastUsed(modelName: string): void {\n const profile = this.findModelProfile(modelName)\n if (profile) {\n profile.lastUsed = Date.now()\n }\n }\n\n /**\n * Find model profile by provider-qualified name (e.g., \"openai:gpt-4o\", \"anthropic:claude-3-5-sonnet\")\n * @param qualifiedName - Format: \"provider:modelName\" or just \"modelName\"\n * @returns ModelProfile or null\n */\n findModelByProviderQualified(qualifiedName: string): ModelProfile | null {\n // Check if it's a provider-qualified name\n if (qualifiedName.includes(':')) {\n const [provider, modelName] = qualifiedName.split(':', 2)\n // Find model matching both provider and modelName\n return (\n this.modelProfiles.find(\n p =>\n p.provider.toLowerCase() === provider.toLowerCase() &&\n (p.modelName === modelName ||\n p.modelName.toLowerCase() === modelName.toLowerCase() ||\n p.name.toLowerCase() === modelName.toLowerCase()),\n ) || null\n )\n }\n\n // Not provider-qualified, fall back to regular lookup\n return (\n this.findModelProfile(qualifiedName) ||\n this.findModelProfileByName(qualifiedName)\n )\n }\n\n /**\n * Enhanced model resolution supporting provider:model format\n * @param modelParam - Can be pointer, provider:model, modelName, or friendly name\n * @returns ModelProfile or null\n */\n resolveProviderQualifiedModel(modelParam: string): {\n profile: ModelProfile | null\n provider?: string\n modelId?: string\n } {\n // Check for provider:model format first\n if (\n modelParam.includes(':') &&\n !['main', 'task', 'reasoning', 'quick', 'compact'].includes(\n modelParam.split(':')[0],\n )\n ) {\n const [provider, modelId] = modelParam.split(':', 2)\n const profile = this.findModelByProviderQualified(modelParam)\n return { profile, provider, modelId }\n }\n\n // Fall back to regular resolve\n const profile = this.resolveModel(modelParam)\n return { profile }\n }\n\n /**\n * Get all models from a specific provider\n */\n getModelsByProvider(provider: string): ModelProfile[] {\n return this.modelProfiles.filter(\n p => p.provider.toLowerCase() === provider.toLowerCase(),\n )\n }\n\n /**\n * Get list of unique providers\n */\n getUniqueProviders(): string[] {\n const providers = new Set(this.modelProfiles.map(p => p.provider))\n return Array.from(providers)\n }\n}\n\n// Global ModelManager instance to avoid config read/write race conditions\nlet globalModelManager: ModelManager | null = null\n\n/**\n * Internal function to refresh the global singleton with an updated instance\n * This is called by ModelManager.saveConfig() to avoid stale data\n */\nfunction refreshGlobalModelManagerInstance(instance: ModelManager): void {\n globalModelManager = instance\n}\n\n/**\n * Get the global ModelManager instance (singleton pattern to fix race conditions)\n */\nexport const getModelManager = (): ModelManager => {\n try {\n if (!globalModelManager) {\n const config = getGlobalConfig()\n if (!config) {\n console.warn(\n 'No global config available, creating ModelManager with empty config',\n )\n globalModelManager = new ModelManager({\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n })\n } else {\n globalModelManager = new ModelManager(config)\n }\n }\n return globalModelManager\n } catch (error) {\n console.error('Error creating ModelManager:', error)\n // Return a fallback ModelManager with empty configuration\n return new ModelManager({\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n })\n }\n}\n\n/**\n * Force reload of the global ModelManager instance\n * Used when configuration changes to ensure fresh data\n */\nexport const reloadModelManager = (): void => {\n globalModelManager = null\n // Force creation of new instance with fresh config\n getModelManager()\n}\n\n/**\n * Get the quick model for fast operations\n */\nexport const getQuickModel = (): string => {\n const manager = getModelManager()\n const quickModel = manager.getModel('quick')\n return quickModel?.modelName || 'quick' // Return pointer if model not resolved\n}\n\n/**\n * Get the compact model for context compression/summarization\n */\nexport const getCompactModel = (): string => {\n const manager = getModelManager()\n const compactModel = manager.getCompactModel()\n return compactModel || 'compact' // Return pointer if model not resolved\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { logError } from './log'\nimport {\n getGlobalConfig,\n ModelProfile,\n ModelPointerType,\n saveGlobalConfig,\n} from './config'\n\nexport const USE_BEDROCK = !!process.env.CLAUDE_CODE_USE_BEDROCK\nexport const USE_VERTEX = !!process.env.CLAUDE_CODE_USE_VERTEX\n\nexport interface ModelConfig {\n bedrock: string\n vertex: string\n firstParty: string\n}\n\nconst DEFAULT_MODEL_CONFIG: ModelConfig = {\n bedrock: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0',\n vertex: 'claude-3-7-sonnet@20250219',\n firstParty: 'claude-sonnet-4-20250514',\n}\n\n/**\n * Helper to get the model config from defaults.\n */\nasync function getModelConfig(): Promise<ModelConfig> {\n return DEFAULT_MODEL_CONFIG\n}\n\nexport const getSlowAndCapableModel = async (): Promise<string> => {\n const config = await getGlobalConfig()\n\n // Use ModelManager for proper model resolution\n const modelManager = new ModelManager(config)\n const model = modelManager.getMainAgentModel()\n\n if (model) {\n return model\n }\n\n // Check if user has configured any models - if so, don't fallback to hardcoded defaults\n // This prevents the system from trying to use Claude models when user only has other providers\n const hasConfiguredModels = modelManager.hasConfiguredModels()\n if (hasConfiguredModels) {\n // User has models but none is set as main - this shouldn't happen normally\n // Return empty string to trigger proper error handling upstream\n throw new Error(\n 'No main model configured. Please use /model to set your default model.',\n )\n }\n\n // Only use hardcoded defaults for Bedrock/Vertex enterprise deployments\n // These are Anthropic-specific cloud deployments where Claude models are guaranteed\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n\n // For first-party (direct API) usage without any configured models,\n // throw an error to guide user to configure models\n throw new Error(\n 'No models configured. Please run /model to add and configure your AI models.',\n )\n}\n\n/**\n * Get context length for a model pointer type\n */\nexport function getModelContextLength(\n pointerType: ModelPointerType = 'main',\n): number {\n const config = getGlobalConfig()\n const modelManager = getModelManager()\n\n // Get the model name based on pointer type\n let modelName: string | null = null\n switch (pointerType) {\n case 'main':\n modelName = modelManager.getMainAgentModel()\n break\n case 'task':\n modelName = modelManager.getTaskToolModel()\n break\n default:\n modelName = modelManager.getMainAgentModel()\n }\n\n // Find the profile for this model\n if (modelName) {\n const profile = config.modelProfiles?.find(\n (p: ModelProfile) => p.modelName === modelName && p.isActive,\n )\n if (profile && profile.contextLength) {\n return profile.contextLength\n }\n }\n\n // Default fallback (Claude Sonnet context length)\n return 200000\n}\n\nexport async function isDefaultSlowAndCapableModel(): Promise<boolean> {\n try {\n const configuredModel = await getSlowAndCapableModel()\n return (\n !process.env.ANTHROPIC_MODEL ||\n process.env.ANTHROPIC_MODEL === configuredModel\n )\n } catch {\n // If no model is configured, we're using \"default\" (which means none)\n return !process.env.ANTHROPIC_MODEL\n }\n}\n\n/**\n * Get the region for a specific Vertex model\n * Checks for hardcoded model-specific environment variables first,\n * then falls back to CLOUD_ML_REGION env var or default region\n */\nexport function getVertexRegionForModel(\n model: string | undefined,\n): string | undefined {\n if (model?.startsWith('claude-3-5-haiku')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_HAIKU\n } else if (model?.startsWith('claude-3-5-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_5_SONNET\n } else if (model?.startsWith('claude-3-7-sonnet')) {\n return process.env.VERTEX_REGION_CLAUDE_3_7_SONNET\n }\n return undefined\n}\n\n/**\n * Comprehensive ModelManager class for centralized model selection and management.\n * Provides a clean interface for model selection across the application.\n */\nexport class ModelManager {\n private config: any // Using any to handle legacy properties\n private modelProfiles: ModelProfile[]\n\n constructor(config: any) {\n this.config = config\n this.modelProfiles = config.modelProfiles || []\n }\n\n /**\n * Get the current terminal model (for interactive CLI sessions)\n */\n getCurrentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Get the main agent default model (for non-terminal mode and MCP calls)\n */\n getMainAgentModel(): string | null {\n // Use main pointer from new ModelProfile system\n const mainModelName = this.config.modelPointers?.main\n if (mainModelName) {\n const profile = this.findModelProfile(mainModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to first active profile\n const activeProfile = this.modelProfiles.find(p => p.isActive)\n if (activeProfile) {\n return activeProfile.modelName\n }\n\n return null\n }\n\n /**\n * Get the task tool default model (for Task tool sub-agents)\n */\n getTaskToolModel(): string | null {\n // Use task pointer from new ModelProfile system\n const taskModelName = this.config.modelPointers?.task\n if (taskModelName) {\n const profile = this.findModelProfile(taskModelName)\n if (profile && profile.isActive) {\n return profile.modelName\n }\n }\n\n // Fallback to main agent model\n return this.getMainAgentModel()\n }\n\n /**\n * Switch to the next available model with enhanced context overflow handling\n * If target model can't handle current context, shows warning and reverts after delay\n *\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Object with detailed model name and context status information\n */\n switchToNextModelWithContextCheck(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n previousModelName: string | null\n contextOverflow: boolean\n usagePercentage: number\n // Enhanced feedback fields\n currentContextTokens: number\n targetContextLimit: number\n skippedModels: Array<{ name: string; reason: string }>\n totalAvailableModels: number\n } {\n // Use ALL configured models, not just active ones\n const allProfiles = this.getAllConfiguredModels()\n if (allProfiles.length === 0) {\n return {\n success: false,\n modelName: null,\n previousModelName: null,\n contextOverflow: false,\n usagePercentage: 0,\n currentContextTokens,\n targetContextLimit: 0,\n skippedModels: [],\n totalAvailableModels: 0,\n }\n }\n\n // Sort by createdAt for consistent cycling order (don't use lastUsed)\n // Using lastUsed causes the order to change each time, preventing proper cycling\n allProfiles.sort((a, b) => {\n return a.createdAt - b.createdAt // Oldest first for consistent order\n })\n\n const currentMainModelName = this.config.modelPointers?.main\n const currentModel = currentMainModelName\n ? this.findModelProfile(currentMainModelName)\n : null\n const previousModelName = currentModel?.name || null\n\n if (!currentMainModelName) {\n // No current main model, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName: null,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n currentContextTokens,\n targetContextLimit: firstModel.contextLength,\n skippedModels: [],\n totalAvailableModels: allProfiles.length,\n }\n }\n\n // Find current model index in ALL models\n const currentIndex = allProfiles.findIndex(\n p => p.modelName === currentMainModelName,\n )\n if (currentIndex === -1) {\n // Current model not found, select first available (activate if needed)\n const firstModel = allProfiles[0]\n if (!firstModel.isActive) {\n firstModel.isActive = true\n }\n this.setPointer('main', firstModel.modelName)\n this.updateLastUsed(firstModel.modelName)\n\n const analysis = this.analyzeContextCompatibility(\n firstModel,\n currentContextTokens,\n )\n return {\n success: true,\n modelName: firstModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n currentContextTokens,\n targetContextLimit: firstModel.contextLength,\n skippedModels: [],\n totalAvailableModels: allProfiles.length,\n }\n }\n\n // Check if only one model is available\n if (allProfiles.length === 1) {\n const currentModel = allProfiles[0]\n return {\n success: false,\n modelName: null,\n previousModelName,\n contextOverflow: false,\n usagePercentage: 0,\n currentContextTokens,\n targetContextLimit: currentModel?.contextLength || 0,\n skippedModels: [],\n totalAvailableModels: 1,\n }\n }\n\n // Get next model in cycle (from ALL models)\n const nextIndex = (currentIndex + 1) % allProfiles.length\n const nextModel = allProfiles[nextIndex]\n\n // Activate the model if it's not already active\n const wasInactive = !nextModel.isActive\n if (!nextModel.isActive) {\n nextModel.isActive = true\n }\n\n // Analyze context compatibility for next model\n const analysis = this.analyzeContextCompatibility(\n nextModel,\n currentContextTokens,\n )\n\n // Always switch to next model, but return context status\n this.setPointer('main', nextModel.modelName)\n this.updateLastUsed(nextModel.modelName)\n\n // Save configuration if we activated a new model\n if (wasInactive) {\n this.saveConfig()\n }\n\n return {\n success: true,\n modelName: nextModel.name,\n previousModelName,\n contextOverflow: !analysis.compatible,\n usagePercentage: analysis.usagePercentage,\n currentContextTokens,\n targetContextLimit: nextModel.contextLength,\n skippedModels: [], // In simple round-robin, no models are skipped\n totalAvailableModels: allProfiles.length,\n }\n }\n\n /**\n * Simple model switching for UI components (compatible interface)\n * @param currentContextTokens - Current conversation token count for validation\n * @returns Compatible interface for PromptInput component\n */\n switchToNextModel(currentContextTokens: number = 0): {\n success: boolean\n modelName: string | null\n blocked?: boolean\n message?: string\n } {\n // Use the enhanced context check method for consistency\n const result = this.switchToNextModelWithContextCheck(currentContextTokens)\n\n if (!result.success) {\n const allModels = this.getAllConfiguredModels()\n if (allModels.length === 0) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: '\u274C No models configured. Use /model to add models.',\n }\n } else if (allModels.length === 1) {\n return {\n success: false,\n modelName: null,\n blocked: false,\n message: `\u26A0\uFE0F Only one model configured (${allModels[0].modelName}). Use /model to add more models for switching.`,\n }\n }\n }\n\n // Convert the detailed result to the simple interface\n const currentModel = this.findModelProfile(this.config.modelPointers?.main)\n const allModels = this.getAllConfiguredModels()\n const currentIndex = allModels.findIndex(\n m => m.modelName === currentModel?.modelName,\n )\n const totalModels = allModels.length\n\n return {\n success: result.success,\n modelName: result.modelName,\n blocked: result.contextOverflow,\n message: result.success\n ? result.contextOverflow\n ? `\u26A0\uFE0F Context usage: ${result.usagePercentage.toFixed(1)}% - ${result.modelName}`\n : `\u2705 Switched to ${result.modelName} (${currentIndex + 1}/${totalModels})${currentModel?.provider ? ` [${currentModel.provider}]` : ''}`\n : `\u274C Failed to switch models`,\n }\n }\n\n /**\n * Revert to previous model (used when context overflow requires rollback)\n */\n revertToPreviousModel(previousModelName: string): boolean {\n const previousModel = this.modelProfiles.find(\n p => p.name === previousModelName && p.isActive,\n )\n if (!previousModel) {\n return false\n }\n\n this.setPointer('main', previousModel.modelName)\n this.updateLastUsed(previousModel.modelName)\n return true\n }\n\n /**\n * Enhanced context validation with different severity levels\n */\n analyzeContextCompatibility(\n model: ModelProfile,\n contextTokens: number,\n ): {\n compatible: boolean\n severity: 'safe' | 'warning' | 'critical'\n usagePercentage: number\n recommendation: string\n } {\n const usableContext = Math.floor(model.contextLength * 0.8) // Reserve 20% for output\n const usagePercentage = (contextTokens / usableContext) * 100\n\n if (usagePercentage <= 70) {\n return {\n compatible: true,\n severity: 'safe',\n usagePercentage,\n recommendation: 'Full context preserved',\n }\n } else if (usagePercentage <= 90) {\n return {\n compatible: true,\n severity: 'warning',\n usagePercentage,\n recommendation: 'Context usage high, consider compression',\n }\n } else {\n return {\n compatible: false,\n severity: 'critical',\n usagePercentage,\n recommendation: 'Auto-compression or message truncation required',\n }\n }\n }\n\n /**\n * Switch to next model with enhanced context analysis\n */\n switchToNextModelWithAnalysis(currentContextTokens: number = 0): {\n modelName: string | null\n contextAnalysis: ReturnType<typeof this.analyzeContextCompatibility> | null\n requiresCompression: boolean\n estimatedTokensAfterSwitch: number\n } {\n const result = this.switchToNextModel(currentContextTokens)\n\n if (!result.success || !result.modelName) {\n return {\n modelName: null,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: 0,\n }\n }\n\n const newModel = this.getModel('main')\n if (!newModel) {\n return {\n modelName: result.modelName,\n contextAnalysis: null,\n requiresCompression: false,\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n const analysis = this.analyzeContextCompatibility(\n newModel,\n currentContextTokens,\n )\n\n return {\n modelName: result.modelName,\n contextAnalysis: analysis,\n requiresCompression: analysis.severity === 'critical',\n estimatedTokensAfterSwitch: currentContextTokens,\n }\n }\n\n /**\n * Check if a model can handle the given context size (legacy method)\n */\n canModelHandleContext(model: ModelProfile, contextTokens: number): boolean {\n const analysis = this.analyzeContextCompatibility(model, contextTokens)\n return analysis.compatible\n }\n\n /**\n * Find the first model that can handle the given context size\n */\n findModelWithSufficientContext(\n models: ModelProfile[],\n contextTokens: number,\n ): ModelProfile | null {\n return (\n models.find(model => this.canModelHandleContext(model, contextTokens)) ||\n null\n )\n }\n\n /**\n * Unified model getter for different contexts\n */\n getModelForContext(\n contextType: 'terminal' | 'main-agent' | 'task-tool',\n ): string | null {\n switch (contextType) {\n case 'terminal':\n return this.getCurrentModel()\n case 'main-agent':\n return this.getMainAgentModel()\n case 'task-tool':\n return this.getTaskToolModel()\n default:\n return this.getMainAgentModel()\n }\n }\n\n /**\n * Get all active model profiles\n */\n getActiveModelProfiles(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Check if any models are configured\n */\n hasConfiguredModels(): boolean {\n return this.getActiveModelProfiles().length > 0\n }\n\n // New model pointer system methods\n\n /**\n * Get model by pointer type (main, task, reasoning, quick)\n */\n getModel(pointer: ModelPointerType): ModelProfile | null {\n const pointerId = this.config.modelPointers?.[pointer]\n if (!pointerId) {\n return this.getDefaultModel()\n }\n\n const profile = this.findModelProfile(pointerId)\n return profile && profile.isActive ? profile : this.getDefaultModel()\n }\n\n /**\n * Get model name by pointer type\n */\n getModelName(pointer: ModelPointerType): string | null {\n const profile = this.getModel(pointer)\n return profile ? profile.modelName : null\n }\n\n /**\n * Get reasoning model (with fallback)\n */\n getReasoningModel(): string | null {\n return this.getModelName('reasoning') || this.getModelName('main')\n }\n\n /**\n * Get quick model (with fallback)\n */\n getQuickModel(): string | null {\n return (\n this.getModelName('quick') ||\n this.getModelName('task') ||\n this.getModelName('main')\n )\n }\n\n /**\n * Get compact model for context compression/summarization (with fallback)\n * Fallback chain: compact -> quick -> task -> main\n */\n getCompactModel(): string | null {\n return (\n this.getModelName('compact') ||\n this.getModelName('quick') ||\n this.getModelName('task') ||\n this.getModelName('main')\n )\n }\n\n /**\n * Add a new model profile with duplicate validation\n */\n async addModel(\n config: Omit<ModelProfile, 'createdAt' | 'isActive'>,\n ): Promise<string> {\n // Check for duplicate modelName (actual model identifier)\n const existingByModelName = this.modelProfiles.find(\n p => p.modelName === config.modelName,\n )\n if (existingByModelName) {\n throw new Error(\n `Model with modelName '${config.modelName}' already exists: ${existingByModelName.name}`,\n )\n }\n\n // Check for duplicate friendly name\n const existingByName = this.modelProfiles.find(p => p.name === config.name)\n if (existingByName) {\n throw new Error(`Model with name '${config.name}' already exists`)\n }\n\n const newModel: ModelProfile = {\n ...config,\n createdAt: Date.now(),\n isActive: true,\n }\n\n this.modelProfiles.push(newModel)\n\n // If this is the first model, set all pointers to it\n if (this.modelProfiles.length === 1) {\n this.config.modelPointers = {\n main: config.modelName,\n task: config.modelName,\n reasoning: config.modelName,\n quick: config.modelName,\n compact: config.modelName,\n }\n this.config.defaultModelName = config.modelName\n }\n\n this.saveConfig()\n return config.modelName\n }\n\n /**\n * Set model pointer assignment\n */\n setPointer(pointer: ModelPointerType, modelName: string): void {\n if (!this.findModelProfile(modelName)) {\n throw new Error(`Model '${modelName}' not found`)\n }\n\n if (!this.config.modelPointers) {\n this.config.modelPointers = {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }\n }\n\n this.config.modelPointers[pointer] = modelName\n this.saveConfig()\n }\n\n /**\n * Get all active models for pointer assignment\n */\n getAvailableModels(): ModelProfile[] {\n return this.modelProfiles.filter(p => p.isActive)\n }\n\n /**\n * Get all configured models (both active and inactive) for switching\n */\n getAllConfiguredModels(): ModelProfile[] {\n return this.modelProfiles\n }\n\n /**\n * Get all available model names (modelName field) - active only\n */\n getAllAvailableModelNames(): string[] {\n return this.getAvailableModels().map(p => p.modelName)\n }\n\n /**\n * Get all configured model names (both active and inactive)\n */\n getAllConfiguredModelNames(): string[] {\n return this.getAllConfiguredModels().map(p => p.modelName)\n }\n\n /**\n * Debug method to get detailed model switching information\n */\n getModelSwitchingDebugInfo(): {\n totalModels: number\n activeModels: number\n inactiveModels: number\n currentMainModel: string | null\n availableModels: Array<{\n name: string\n modelName: string\n provider: string\n isActive: boolean\n lastUsed?: number\n }>\n modelPointers: Record<string, string | undefined>\n } {\n const availableModels = this.getAvailableModels()\n const currentMainModelName = this.config.modelPointers?.main\n\n return {\n totalModels: this.modelProfiles.length,\n activeModels: availableModels.length,\n inactiveModels: this.modelProfiles.length - availableModels.length,\n currentMainModel: currentMainModelName || null,\n availableModels: this.modelProfiles.map(p => ({\n name: p.name,\n modelName: p.modelName,\n provider: p.provider,\n isActive: p.isActive,\n lastUsed: p.lastUsed,\n })),\n modelPointers: this.config.modelPointers || {},\n }\n }\n\n /**\n * Update an existing model profile\n * modelName is the primary key and cannot be changed\n */\n updateModel(\n modelName: string,\n updates: Partial<\n Pick<\n ModelProfile,\n | 'name'\n | 'baseURL'\n | 'apiKey'\n | 'maxTokens'\n | 'contextLength'\n | 'reasoningEffort'\n >\n >,\n ): void {\n const profile = this.findModelProfile(modelName)\n if (!profile) {\n throw new Error(`Model '${modelName}' not found`)\n }\n\n // Check for duplicate friendly name if name is being updated\n if (updates.name && updates.name !== profile.name) {\n const existingByName = this.modelProfiles.find(\n p => p.name === updates.name && p.modelName !== modelName,\n )\n if (existingByName) {\n throw new Error(`Model with name '${updates.name}' already exists`)\n }\n }\n\n Object.assign(profile, updates)\n this.saveConfig()\n }\n\n /**\n * Remove a model profile\n */\n removeModel(modelName: string): void {\n this.modelProfiles = this.modelProfiles.filter(\n p => p.modelName !== modelName,\n )\n\n // Clean up pointers that reference deleted model\n if (this.config.modelPointers) {\n Object.keys(this.config.modelPointers).forEach(pointer => {\n if (\n this.config.modelPointers[pointer as ModelPointerType] === modelName\n ) {\n this.config.modelPointers[pointer as ModelPointerType] =\n this.config.defaultModelName || ''\n }\n })\n }\n\n this.saveConfig()\n }\n\n /**\n * Get default model profile\n */\n private getDefaultModel(): ModelProfile | null {\n if (this.config.defaultModelId) {\n const profile = this.findModelProfile(this.config.defaultModelId)\n if (profile && profile.isActive) {\n return profile\n }\n }\n return this.modelProfiles.find(p => p.isActive) || null\n }\n\n /**\n * Save configuration changes\n * Note: This updates the global config file. The singleton instance\n * is automatically refreshed to avoid stale data issues.\n */\n private saveConfig(): void {\n const updatedConfig = {\n ...this.config,\n modelProfiles: this.modelProfiles,\n }\n saveGlobalConfig(updatedConfig)\n\n // Refresh the global singleton to avoid stale data race conditions\n // This ensures any subsequent getModelManager() calls get fresh data\n refreshGlobalModelManagerInstance(this)\n }\n\n /**\n * Get a fallback model when no specific model is configured\n */\n async getFallbackModel(): Promise<string> {\n const modelConfig = await getModelConfig()\n if (USE_BEDROCK) return modelConfig.bedrock\n if (USE_VERTEX) return modelConfig.vertex\n return modelConfig.firstParty\n }\n\n /**\n * \u7EDF\u4E00\u7684\u6A21\u578B\u89E3\u6790\u65B9\u6CD5\uFF1A\u652F\u6301\u6307\u9488\u3001model ID \u548C\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n * @param modelParam - \u53EF\u4EE5\u662F\u6A21\u578B\u6307\u9488 ('main', 'task', etc.)\u3001\u5185\u90E8model ID \u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0 ('gpt-4o', 'claude-3-5-sonnet')\n * @returns ModelProfile \u6216 null\n */\n resolveModel(modelParam: string | ModelPointerType): ModelProfile | null {\n // \u9996\u5148\u68C0\u67E5\u662F\u5426\u662F\u6A21\u578B\u6307\u9488\n if (\n ['main', 'task', 'reasoning', 'quick', 'compact'].includes(modelParam)\n ) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (pointerId) {\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u4E24\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(pointerId) // \u6309\u5185\u90E8ID\u67E5\u627E\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId) // \u6309\u771F\u5B9E\u6A21\u578B\u540D\u67E5\u627E\n }\n if (profile && profile.isActive) {\n return profile\n }\n }\n // \u6307\u9488\u65E0\u6548\u65F6\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n // \u4E0D\u662F\u6307\u9488\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n // 1. \u5C1D\u8BD5\u6309\u5185\u90E8 model ID \u67E5\u627E\n let profile = this.findModelProfile(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 2. \u5C1D\u8BD5\u6309\u771F\u5B9E\u6A21\u578B\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByModelName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // 3. \u5C1D\u8BD5\u6309\u53CB\u597D\u540D\u79F0\u67E5\u627E\n profile = this.findModelProfileByName(modelParam)\n if (profile && profile.isActive) {\n return profile\n }\n\n // \u6240\u6709\u67E5\u627E\u65B9\u5F0F\u90FD\u5931\u8D25\uFF0C\u5C1D\u8BD5 fallback \u5230\u9ED8\u8BA4\u6A21\u578B\n return this.getDefaultModel()\n }\n\n /**\n * \u89E3\u6790\u6A21\u578B\u53C2\u6570\u5E76\u8FD4\u56DE\u5B8C\u6574\u4FE1\u606F\n */\n resolveModelWithInfo(modelParam: string | ModelPointerType): {\n success: boolean\n profile: ModelProfile | null\n error?: string\n } {\n const isPointer = [\n 'main',\n 'task',\n 'reasoning',\n 'quick',\n 'compact',\n ].includes(modelParam)\n\n if (isPointer) {\n const pointerId =\n this.config.modelPointers?.[modelParam as ModelPointerType]\n if (!pointerId) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' is not configured. Use /model to set up models.`,\n }\n }\n\n // pointerId \u53EF\u80FD\u662F\u5185\u90E8ID\u6216\u771F\u5B9E\u6A21\u578B\u540D\u79F0\n let profile = this.findModelProfile(pointerId)\n if (!profile) {\n profile = this.findModelProfileByModelName(pointerId)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model pointer '${modelParam}' points to invalid model '${pointerId}'. Use /model to reconfigure.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' (pointed by '${modelParam}') is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n } else {\n // \u76F4\u63A5\u7684 model ID \u6216\u6A21\u578B\u540D\u79F0\uFF0C\u5C1D\u8BD5\u591A\u79CD\u67E5\u627E\u65B9\u5F0F\n let profile = this.findModelProfile(modelParam)\n if (!profile) {\n profile = this.findModelProfileByModelName(modelParam)\n }\n if (!profile) {\n profile = this.findModelProfileByName(modelParam)\n }\n\n if (!profile) {\n return {\n success: false,\n profile: null,\n error: `Model '${modelParam}' not found. Use /model to add models.`,\n }\n }\n\n if (!profile.isActive) {\n return {\n success: false,\n profile: null,\n error: `Model '${profile.name}' is inactive. Use /model to activate it.`,\n }\n }\n\n return {\n success: true,\n profile,\n }\n }\n }\n\n // Private helper methods\n private findModelProfile(modelName: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.modelName === modelName) || null\n }\n\n /** @deprecated Use findModelProfile instead - identical implementation */\n private findModelProfileByModelName(modelName: string): ModelProfile | null {\n return this.findModelProfile(modelName)\n }\n\n private findModelProfileByName(name: string): ModelProfile | null {\n return this.modelProfiles.find(p => p.name === name) || null\n }\n\n private updateLastUsed(modelName: string): void {\n const profile = this.findModelProfile(modelName)\n if (profile) {\n profile.lastUsed = Date.now()\n }\n }\n\n /**\n * Find model profile by provider-qualified name (e.g., \"openai:gpt-4o\", \"anthropic:claude-3-5-sonnet\")\n * @param qualifiedName - Format: \"provider:modelName\" or just \"modelName\"\n * @returns ModelProfile or null\n */\n findModelByProviderQualified(qualifiedName: string): ModelProfile | null {\n // Check if it's a provider-qualified name\n if (qualifiedName.includes(':')) {\n const [provider, modelName] = qualifiedName.split(':', 2)\n // Find model matching both provider and modelName\n return (\n this.modelProfiles.find(\n p =>\n p.provider.toLowerCase() === provider.toLowerCase() &&\n (p.modelName === modelName ||\n p.modelName.toLowerCase() === modelName.toLowerCase() ||\n p.name.toLowerCase() === modelName.toLowerCase()),\n ) || null\n )\n }\n\n // Not provider-qualified, fall back to regular lookup\n return (\n this.findModelProfile(qualifiedName) ||\n this.findModelProfileByName(qualifiedName)\n )\n }\n\n /**\n * Enhanced model resolution supporting provider:model format\n * @param modelParam - Can be pointer, provider:model, modelName, or friendly name\n * @returns ModelProfile or null\n */\n resolveProviderQualifiedModel(modelParam: string): {\n profile: ModelProfile | null\n provider?: string\n modelId?: string\n } {\n // Check for provider:model format first\n if (\n modelParam.includes(':') &&\n !['main', 'task', 'reasoning', 'quick', 'compact'].includes(\n modelParam.split(':')[0],\n )\n ) {\n const [provider, modelId] = modelParam.split(':', 2)\n const profile = this.findModelByProviderQualified(modelParam)\n return { profile, provider, modelId }\n }\n\n // Fall back to regular resolve\n const profile = this.resolveModel(modelParam)\n return { profile }\n }\n\n /**\n * Get all models from a specific provider\n */\n getModelsByProvider(provider: string): ModelProfile[] {\n return this.modelProfiles.filter(\n p => p.provider.toLowerCase() === provider.toLowerCase(),\n )\n }\n\n /**\n * Get list of unique providers\n */\n getUniqueProviders(): string[] {\n const providers = new Set(this.modelProfiles.map(p => p.provider))\n return Array.from(providers)\n }\n}\n\n// Global ModelManager instance to avoid config read/write race conditions\nlet globalModelManager: ModelManager | null = null\n\n/**\n * Internal function to refresh the global singleton with an updated instance\n * This is called by ModelManager.saveConfig() to avoid stale data\n */\nfunction refreshGlobalModelManagerInstance(instance: ModelManager): void {\n globalModelManager = instance\n}\n\n/**\n * Get the global ModelManager instance (singleton pattern to fix race conditions)\n */\nexport const getModelManager = (): ModelManager => {\n try {\n if (!globalModelManager) {\n const config = getGlobalConfig()\n if (!config) {\n console.warn(\n 'No global config available, creating ModelManager with empty config',\n )\n globalModelManager = new ModelManager({\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n })\n } else {\n globalModelManager = new ModelManager(config)\n }\n }\n return globalModelManager\n } catch (error) {\n console.error('Error creating ModelManager:', error)\n // Return a fallback ModelManager with empty configuration\n return new ModelManager({\n modelProfiles: [],\n modelPointers: {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n },\n })\n }\n}\n\n/**\n * Force reload of the global ModelManager instance\n * Used when configuration changes to ensure fresh data\n */\nexport const reloadModelManager = (): void => {\n globalModelManager = null\n // Force creation of new instance with fresh config\n getModelManager()\n}\n\n/**\n * Get the quick model for fast operations\n */\nexport const getQuickModel = (): string => {\n const manager = getModelManager()\n // Use QuickModel with full fallback chain: quick -> task -> main\n const quickModelName = manager.getQuickModel()\n if (quickModelName) return quickModelName\n // Last resort: return main model name or empty string\n const mainModel = manager.getMainAgentModel()\n return mainModel || ''\n}\n\n/**\n * Get the compact model for context compression/summarization\n */\nexport const getCompactModel = (): string => {\n const manager = getModelManager()\n // Use CompactModel with full fallback chain: compact -> quick -> task -> main\n const compactModelName = manager.getCompactModel()\n if (compactModelName) return compactModelName\n // Last resort: return main model name or empty string\n const mainModel = manager.getMainAgentModel()\n return mainModel || ''\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["analysis", "currentModel", "allModels", "profile"]
7
7
  }
@@ -18,6 +18,7 @@ import {
18
18
  PluginErrorCode
19
19
  } from "../types/plugin.js";
20
20
  import { findPlugin } from "./marketplaceManager.js";
21
+ import { validatePluginDirectory } from "../services/plugins/pluginValidation.js";
21
22
  var InstallPhase = /* @__PURE__ */ ((InstallPhase2) => {
22
23
  InstallPhase2["VALIDATING_SOURCE"] = "validating_source";
23
24
  InstallPhase2["CLONING"] = "cloning";
@@ -44,12 +45,23 @@ class PluginInstaller extends EventEmitter {
44
45
  });
45
46
  }
46
47
  /**
47
- * Get plugin installation directory
48
+ * Get plugin installation directory based on scope
48
49
  */
49
50
  getInstallDir(pluginName, options) {
50
51
  if (options?.targetDir) {
51
52
  return resolve(options.targetDir);
52
53
  }
54
+ const scope = options?.scope;
55
+ if (scope) {
56
+ switch (scope) {
57
+ case "user":
58
+ return join(homedir(), ".minto", "plugins", pluginName);
59
+ case "project":
60
+ return join(getCwd(), ".minto", "plugins", pluginName);
61
+ case "local":
62
+ return join(getCwd(), ".minto", "plugins.local", pluginName);
63
+ }
64
+ }
53
65
  const baseDir = options?.global ? homedir() : getCwd();
54
66
  return join(baseDir, ".minto", "plugins", pluginName);
55
67
  }
@@ -140,17 +152,34 @@ class PluginInstaller extends EventEmitter {
140
152
  * Validate plugin manifest exists and is valid
141
153
  */
142
154
  validateManifest(pluginPath) {
143
- const manifestPath = join(pluginPath, "plugin.json");
144
- if (!existsSync(manifestPath)) {
155
+ const candidates = [
156
+ join(pluginPath, ".minto-plugin", "plugin.json"),
157
+ join(pluginPath, ".claude-plugin", "plugin.json"),
158
+ join(pluginPath, "plugin.json")
159
+ ];
160
+ const manifestPath = candidates.find((p) => existsSync(p));
161
+ if (!manifestPath) {
145
162
  throw new PluginError(
146
- `Plugin manifest (plugin.json) not found in ${pluginPath}`,
163
+ `Plugin manifest not found. Tried:
164
+ ${candidates.map((p) => ` - ${p}`).join("\n")}`,
147
165
  PluginErrorCode.MANIFEST_NOT_FOUND
148
166
  );
149
167
  }
150
168
  try {
151
169
  const content = readFileSync(manifestPath, "utf-8");
152
170
  const data = JSON.parse(content);
153
- return PluginManifestSchema.parse(data);
171
+ const manifest = PluginManifestSchema.parse(data);
172
+ const dirValidation = validatePluginDirectory(pluginPath);
173
+ if (dirValidation.warnings.length > 0) {
174
+ for (const warning of dirValidation.warnings) {
175
+ this.emitProgress(
176
+ "validating_manifest" /* VALIDATING_MANIFEST */,
177
+ `Warning: ${warning}`,
178
+ 35
179
+ );
180
+ }
181
+ }
182
+ return manifest;
154
183
  } catch (error) {
155
184
  throw new PluginError(
156
185
  `Invalid plugin manifest: ${error instanceof Error ? error.message : String(error)}`,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/pluginInstaller.ts"],
4
- "sourcesContent": ["/**\n * Plugin Installer\n *\n * Comprehensive plugin installation utility with proper error handling,\n * progress tracking, and cleanup on failure.\n *\n * Supports installation from:\n * - Git repositories (GitHub shorthand, full URLs)\n * - Local directories (copy or symlink)\n * - NPM packages (future)\n * - Marketplaces (via marketplaceManager)\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n rmSync,\n cpSync,\n symlinkSync,\n statSync,\n readdirSync,\n} from 'fs'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport { EventEmitter } from 'events'\nimport { fetchRepo, RepoSource } from './repoFetcher'\nimport { getCwd } from './state'\nimport {\n PluginManifest,\n PluginManifestSchema,\n PluginSource,\n PluginError,\n PluginErrorCode,\n} from '../types/plugin'\nimport { findPlugin } from './marketplaceManager'\n\n/**\n * Installation options\n */\nexport interface InstallOptions {\n /** Target directory (default: ~/.minto/plugins/<name> or ./.minto/plugins/<name>) */\n targetDir?: string\n\n /** Overwrite existing installation */\n force?: boolean\n\n /** Create symlink instead of copy (for local development) */\n dev?: boolean\n\n /** Install globally (~/minto/plugins/) vs project-level (./.minto/plugins/) */\n global?: boolean\n\n /** Silent mode (no progress events) */\n silent?: boolean\n\n /** Validation mode: strict (require all components) or loose */\n validation?: 'strict' | 'loose'\n}\n\n/**\n * Installation progress phases\n */\nexport enum InstallPhase {\n VALIDATING_SOURCE = 'validating_source',\n CLONING = 'cloning',\n COPYING = 'copying',\n VALIDATING_MANIFEST = 'validating_manifest',\n CHECKING_DEPENDENCIES = 'checking_dependencies',\n INSTALLING = 'installing',\n REGISTERING = 'registering',\n CLEANUP = 'cleanup',\n COMPLETE = 'complete',\n}\n\n/**\n * Installation progress event\n */\nexport interface InstallProgress {\n phase: InstallPhase\n message: string\n percentage: number\n pluginName?: string\n}\n\n/**\n * Plugin registry entry\n */\ninterface PluginRegistryEntry {\n name: string\n version: string\n source: PluginSource\n installedAt: string\n location: string\n}\n\n/**\n * Plugin installer with event-based progress tracking\n */\nexport class PluginInstaller extends EventEmitter {\n private tempDirs: string[] = []\n\n /**\n * Emit progress event\n */\n private emitProgress(\n phase: InstallPhase,\n message: string,\n percentage: number,\n pluginName?: string,\n ): void {\n this.emit('progress', {\n phase,\n message,\n percentage,\n pluginName,\n } as InstallProgress)\n }\n\n /**\n * Get plugin installation directory\n */\n private getInstallDir(pluginName: string, options?: InstallOptions): string {\n if (options?.targetDir) {\n return resolve(options.targetDir)\n }\n\n const baseDir = options?.global ? homedir() : getCwd()\n return join(baseDir, '.minto', 'plugins', pluginName)\n }\n\n /**\n * Get plugin registry path\n */\n private getRegistryPath(global: boolean): string {\n const baseDir = global ? homedir() : getCwd()\n return join(baseDir, '.minto', 'plugins', 'registry.json')\n }\n\n /**\n * Load plugin registry\n */\n private loadRegistry(global: boolean): PluginRegistryEntry[] {\n const registryPath = this.getRegistryPath(global)\n\n if (!existsSync(registryPath)) {\n return []\n }\n\n try {\n const content = readFileSync(registryPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.error('Error loading plugin registry:', error)\n return []\n }\n }\n\n /**\n * Save plugin registry\n */\n private saveRegistry(entries: PluginRegistryEntry[], global: boolean): void {\n const registryPath = this.getRegistryPath(global)\n const registryDir = join(registryPath, '..')\n\n // Ensure directory exists\n if (!existsSync(registryDir)) {\n mkdirSync(registryDir, { recursive: true })\n }\n\n writeFileSync(registryPath, JSON.stringify(entries, null, 2), 'utf-8')\n }\n\n /**\n * Register plugin in registry\n */\n private registerPlugin(\n manifest: PluginManifest,\n source: PluginSource,\n location: string,\n global: boolean,\n ): void {\n const registry = this.loadRegistry(global)\n\n // Remove existing entry if present\n const filtered = registry.filter(e => e.name !== manifest.name)\n\n // Add new entry\n filtered.push({\n name: manifest.name,\n version: manifest.version,\n source,\n installedAt: new Date().toISOString(),\n location,\n })\n\n this.saveRegistry(filtered, global)\n }\n\n /**\n * Unregister plugin from registry\n */\n private unregisterPlugin(pluginName: string, global: boolean): void {\n const registry = this.loadRegistry(global)\n const filtered = registry.filter(e => e.name !== pluginName)\n this.saveRegistry(filtered, global)\n }\n\n /**\n * Fetch a git repository to a temporary directory using repoFetcher\n */\n private async fetchToTempDir(source: RepoSource): Promise<string> {\n const tempDir = join(\n homedir(),\n '.minto',\n 'temp',\n 'plugins',\n Date.now().toString(),\n )\n\n this.tempDirs.push(tempDir)\n mkdirSync(tempDir, { recursive: true })\n\n this.emitProgress(InstallPhase.CLONING, `Fetching repository...`, 20)\n\n try {\n await fetchRepo(source, tempDir)\n return tempDir\n } catch (error) {\n throw new PluginError(\n `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n }\n\n /**\n * Validate plugin manifest exists and is valid\n */\n private validateManifest(pluginPath: string): PluginManifest {\n const manifestPath = join(pluginPath, 'plugin.json')\n\n if (!existsSync(manifestPath)) {\n throw new PluginError(\n `Plugin manifest (plugin.json) not found in ${pluginPath}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Validate with Zod schema\n return PluginManifestSchema.parse(data)\n } catch (error) {\n throw new PluginError(\n `Invalid plugin manifest: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n error,\n )\n }\n }\n\n /**\n * Check if plugin is already installed\n */\n private isPluginInstalled(pluginName: string, global: boolean): boolean {\n const registry = this.loadRegistry(global)\n return registry.some(e => e.name === pluginName)\n }\n\n /**\n * Validate plugin components exist\n */\n private validateComponents(\n pluginPath: string,\n manifest: PluginManifest,\n strict: boolean,\n ): void {\n const missing: string[] = []\n\n // Check agents\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n if (!existsSync(fullPath)) {\n missing.push(`Agent: ${agentPath}`)\n }\n }\n\n // Check commands\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n if (!existsSync(fullPath)) {\n missing.push(`Command: ${commandPath}`)\n }\n }\n\n // Check skills\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n if (!existsSync(fullPath)) {\n missing.push(`Skill: ${skillPath}`)\n }\n }\n\n if (missing.length > 0 && strict) {\n throw new PluginError(\n `Missing plugin components:\\n${missing.join('\\n')}`,\n PluginErrorCode.COMPONENT_NOT_FOUND,\n manifest.name,\n )\n } else if (missing.length > 0) {\n console.warn(`Warning: Missing plugin components:\\n${missing.join('\\n')}`)\n }\n }\n\n /**\n * Check disk space availability\n */\n private checkDiskSpace(targetDir: string): void {\n try {\n // Create parent directory if it doesn't exist\n const parentDir = join(targetDir, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n } catch (error) {\n throw new PluginError(\n `Insufficient permissions or disk space: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n }\n\n /**\n * Install plugin from source directory to target directory\n */\n private installToTarget(\n sourceDir: string,\n targetDir: string,\n options?: InstallOptions,\n ): void {\n this.emitProgress(InstallPhase.INSTALLING, `Installing to ${targetDir}`, 60)\n\n // Check if target exists\n if (existsSync(targetDir)) {\n if (options?.force) {\n rmSync(targetDir, { recursive: true, force: true })\n } else {\n throw new PluginError(\n `Plugin directory already exists: ${targetDir}. Use --force to overwrite.`,\n PluginErrorCode.ALREADY_INSTALLED,\n )\n }\n }\n\n // Create parent directory\n const parentDir = join(targetDir, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n\n // Install: symlink for dev mode, copy otherwise\n if (options?.dev) {\n symlinkSync(sourceDir, targetDir, 'dir')\n } else {\n cpSync(sourceDir, targetDir, { recursive: true })\n }\n }\n\n /**\n * Cleanup temporary directories\n */\n private cleanup(): void {\n for (const tempDir of this.tempDirs) {\n try {\n if (existsSync(tempDir)) {\n rmSync(tempDir, { recursive: true, force: true })\n }\n } catch (error) {\n console.error(`Error cleaning up temp directory ${tempDir}:`, error)\n }\n }\n\n this.tempDirs = []\n }\n\n /**\n * Install plugin from any source\n */\n async installPlugin(\n source: PluginSource,\n options?: InstallOptions,\n ): Promise<string> {\n let sourceDir: string | undefined\n let manifest: PluginManifest | undefined\n\n try {\n // Phase 1: Validate and fetch source\n this.emitProgress(\n InstallPhase.VALIDATING_SOURCE,\n 'Validating plugin source',\n 0,\n )\n\n switch (source.type) {\n case 'git': {\n // Detect GitHub URLs and use tarball; otherwise use URL source\n const ghMatch = source.repo.match(\n /github\\.com[/:]([^/]+\\/[^/.]+?)(?:\\.git)?$/,\n )\n if (ghMatch) {\n sourceDir = await this.fetchToTempDir({\n type: 'github',\n repo: ghMatch[1],\n ref: source.ref,\n })\n } else {\n sourceDir = await this.fetchToTempDir({\n type: 'url',\n url: source.repo,\n ref: source.ref,\n })\n }\n break\n }\n\n case 'local':\n sourceDir = resolve(source.path)\n if (!existsSync(sourceDir)) {\n throw new PluginError(\n `Local plugin path does not exist: ${sourceDir}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n break\n\n case 'npm':\n throw new PluginError(\n 'NPM package installation not yet supported',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n\n case 'marketplace':\n // Find plugin in marketplace\n const found = findPlugin(source.name, source.marketplace)\n\n if (!found) {\n throw new PluginError(\n source.marketplace\n ? `Plugin \"${source.name}\" not found in marketplace \"${source.marketplace}\"`\n : `Plugin \"${source.name}\" not found in any marketplace`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n const { plugin } = found\n\n // Recursively install from plugin's source\n if (typeof plugin.source === 'string') {\n throw new PluginError(\n 'Relative path plugins not yet supported',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n } else if (plugin.source.source === 'github') {\n sourceDir = await this.fetchToTempDir({\n type: 'github',\n repo: plugin.source.repo,\n ref: plugin.source.ref,\n })\n } else if (plugin.source.source === 'url') {\n sourceDir = await this.fetchToTempDir({\n type: 'url',\n url: plugin.source.url,\n ref: plugin.source.ref,\n })\n } else {\n throw new PluginError(\n 'Unsupported marketplace plugin source type',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n break\n\n default:\n throw new PluginError(\n 'Unknown plugin source type',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n // Phase 2: Validate manifest\n this.emitProgress(\n InstallPhase.VALIDATING_MANIFEST,\n 'Validating plugin manifest',\n 30,\n )\n\n manifest = this.validateManifest(sourceDir)\n\n // Check if already installed\n const global = options?.global ?? false\n if (this.isPluginInstalled(manifest.name, global) && !options?.force) {\n throw new PluginError(\n `Plugin \"${manifest.name}\" is already installed. Use --force to overwrite.`,\n PluginErrorCode.ALREADY_INSTALLED,\n manifest.name,\n )\n }\n\n // Phase 3: Validate components\n this.emitProgress(\n InstallPhase.VALIDATING_MANIFEST,\n 'Validating plugin components',\n 40,\n )\n\n const strict = options?.validation === 'strict'\n this.validateComponents(sourceDir, manifest, strict)\n\n // Phase 4: Check dependencies (placeholder)\n this.emitProgress(\n InstallPhase.CHECKING_DEPENDENCIES,\n 'Checking dependencies',\n 50,\n )\n\n // TODO: Check engine versions, dependencies, etc.\n\n // Phase 5: Determine target directory\n const targetDir = this.getInstallDir(manifest.name, options)\n\n // Check disk space and permissions\n this.checkDiskSpace(targetDir)\n\n // Phase 6: Install to target\n this.installToTarget(sourceDir, targetDir, options)\n\n // Phase 7: Register plugin\n this.emitProgress(InstallPhase.REGISTERING, 'Registering plugin', 80)\n\n this.registerPlugin(manifest, source, targetDir, global)\n\n // Phase 8: Complete\n this.emitProgress(\n InstallPhase.COMPLETE,\n `Successfully installed ${manifest.name}`,\n 100,\n manifest.name,\n )\n\n return targetDir\n } catch (error) {\n // Cleanup on error\n this.emitProgress(\n InstallPhase.CLEANUP,\n 'Installation failed, cleaning up',\n 0,\n )\n\n throw error\n } finally {\n // Always cleanup temp directories\n this.cleanup()\n }\n }\n\n /**\n * Uninstall a plugin by name\n */\n async uninstallPlugin(\n pluginName: string,\n options?: { global?: boolean },\n ): Promise<void> {\n const global = options?.global ?? false\n const registry = this.loadRegistry(global)\n\n // Find plugin in registry\n const entry = registry.find(e => e.name === pluginName)\n\n if (!entry) {\n throw new PluginError(\n `Plugin \"${pluginName}\" is not installed`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n // Remove plugin directory\n if (existsSync(entry.location)) {\n try {\n rmSync(entry.location, { recursive: true, force: true })\n } catch (error) {\n throw new PluginError(\n `Failed to remove plugin directory: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n pluginName,\n error,\n )\n }\n }\n\n // Unregister from registry\n this.unregisterPlugin(pluginName, global)\n }\n\n /**\n * Update a plugin (re-install from source)\n */\n async updatePlugin(\n pluginName: string,\n options?: { global?: boolean },\n ): Promise<void> {\n const global = options?.global ?? false\n const registry = this.loadRegistry(global)\n\n // Find plugin in registry\n const entry = registry.find(e => e.name === pluginName)\n\n if (!entry) {\n throw new PluginError(\n `Plugin \"${pluginName}\" is not installed`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n // Uninstall and reinstall\n await this.uninstallPlugin(pluginName, { global })\n await this.installPlugin(entry.source, { global, force: true })\n }\n}\n\n/**\n * Convenience function: Install plugin from source\n */\nexport async function installPlugin(\n source: PluginSource,\n options?: InstallOptions,\n): Promise<string> {\n const installer = new PluginInstaller()\n\n // Setup progress listener if not silent\n if (!options?.silent) {\n installer.on('progress', (progress: InstallProgress) => {\n console.log(\n `[${progress.percentage}%] ${progress.phase}: ${progress.message}`,\n )\n })\n }\n\n return installer.installPlugin(source, options)\n}\n\n/**\n * Convenience function: Uninstall plugin by name\n */\nexport async function uninstallPlugin(\n name: string,\n options?: { global?: boolean },\n): Promise<void> {\n const installer = new PluginInstaller()\n return installer.uninstallPlugin(name, options)\n}\n\n/**\n * Convenience function: Update plugin by name\n */\nexport async function updatePlugin(\n name: string,\n options?: { global?: boolean },\n): Promise<void> {\n const installer = new PluginInstaller()\n return installer.updatePlugin(name, options)\n}\n\n/**\n * List all installed plugins\n */\nexport function listInstalledPlugins(global?: boolean): PluginRegistryEntry[] {\n const installer = new PluginInstaller()\n const globalRegistry = installer['loadRegistry'](true)\n const projectRegistry = installer['loadRegistry'](false)\n\n if (global === true) {\n return globalRegistry\n } else if (global === false) {\n return projectRegistry\n } else {\n // Return both, with project plugins overriding global\n const combined = new Map<string, PluginRegistryEntry>()\n\n for (const entry of globalRegistry) {\n combined.set(entry.name, entry)\n }\n\n for (const entry of projectRegistry) {\n combined.set(entry.name, entry)\n }\n\n return Array.from(combined.values())\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Plugin Installer\n *\n * Comprehensive plugin installation utility with proper error handling,\n * progress tracking, and cleanup on failure.\n *\n * Supports installation from:\n * - Git repositories (GitHub shorthand, full URLs)\n * - Local directories (copy or symlink)\n * - NPM packages (future)\n * - Marketplaces (via marketplaceManager)\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n rmSync,\n cpSync,\n symlinkSync,\n statSync,\n readdirSync,\n} from 'fs'\nimport { join, resolve, basename } from 'path'\nimport { homedir } from 'os'\nimport { EventEmitter } from 'events'\nimport { fetchRepo, RepoSource } from './repoFetcher'\nimport { getCwd } from './state'\nimport {\n PluginManifest,\n PluginManifestSchema,\n PluginSource,\n PluginError,\n PluginErrorCode,\n} from '../types/plugin'\nimport { findPlugin } from './marketplaceManager'\nimport { validatePluginDirectory } from '@services/plugins/pluginValidation'\n\n/**\n * Installation scopes\n *\n * user: ~/.minto/plugins/ (user-global)\n * project: .minto/plugins/ (tracked by git)\n * local: .minto/plugins.local/ (gitignored, private)\n */\nexport type InstallScope = 'user' | 'project' | 'local'\n\n/**\n * Installation options\n */\nexport interface InstallOptions {\n /** Target directory (default: ~/.minto/plugins/<name> or ./.minto/plugins/<name>) */\n targetDir?: string\n\n /** Overwrite existing installation */\n force?: boolean\n\n /** Create symlink instead of copy (for local development) */\n dev?: boolean\n\n /** Install globally (~/minto/plugins/) vs project-level (./.minto/plugins/) */\n global?: boolean\n\n /** Install scope (overrides 'global' when set) */\n scope?: InstallScope\n\n /** Silent mode (no progress events) */\n silent?: boolean\n\n /** Validation mode: strict (require all components) or loose */\n validation?: 'strict' | 'loose'\n}\n\n/**\n * Installation progress phases\n */\nexport enum InstallPhase {\n VALIDATING_SOURCE = 'validating_source',\n CLONING = 'cloning',\n COPYING = 'copying',\n VALIDATING_MANIFEST = 'validating_manifest',\n CHECKING_DEPENDENCIES = 'checking_dependencies',\n INSTALLING = 'installing',\n REGISTERING = 'registering',\n CLEANUP = 'cleanup',\n COMPLETE = 'complete',\n}\n\n/**\n * Installation progress event\n */\nexport interface InstallProgress {\n phase: InstallPhase\n message: string\n percentage: number\n pluginName?: string\n}\n\n/**\n * Plugin registry entry\n */\ninterface PluginRegistryEntry {\n name: string\n version: string\n source: PluginSource\n installedAt: string\n location: string\n}\n\n/**\n * Plugin installer with event-based progress tracking\n */\nexport class PluginInstaller extends EventEmitter {\n private tempDirs: string[] = []\n\n /**\n * Emit progress event\n */\n private emitProgress(\n phase: InstallPhase,\n message: string,\n percentage: number,\n pluginName?: string,\n ): void {\n this.emit('progress', {\n phase,\n message,\n percentage,\n pluginName,\n } as InstallProgress)\n }\n\n /**\n * Get plugin installation directory based on scope\n */\n private getInstallDir(pluginName: string, options?: InstallOptions): string {\n if (options?.targetDir) {\n return resolve(options.targetDir)\n }\n\n // Scope takes precedence over global flag\n const scope = options?.scope\n if (scope) {\n switch (scope) {\n case 'user':\n return join(homedir(), '.minto', 'plugins', pluginName)\n case 'project':\n return join(getCwd(), '.minto', 'plugins', pluginName)\n case 'local':\n return join(getCwd(), '.minto', 'plugins.local', pluginName)\n }\n }\n\n // Fallback to global flag\n const baseDir = options?.global ? homedir() : getCwd()\n return join(baseDir, '.minto', 'plugins', pluginName)\n }\n\n /**\n * Get plugin registry path\n */\n private getRegistryPath(global: boolean): string {\n const baseDir = global ? homedir() : getCwd()\n return join(baseDir, '.minto', 'plugins', 'registry.json')\n }\n\n /**\n * Load plugin registry\n */\n private loadRegistry(global: boolean): PluginRegistryEntry[] {\n const registryPath = this.getRegistryPath(global)\n\n if (!existsSync(registryPath)) {\n return []\n }\n\n try {\n const content = readFileSync(registryPath, 'utf-8')\n return JSON.parse(content)\n } catch (error) {\n console.error('Error loading plugin registry:', error)\n return []\n }\n }\n\n /**\n * Save plugin registry\n */\n private saveRegistry(entries: PluginRegistryEntry[], global: boolean): void {\n const registryPath = this.getRegistryPath(global)\n const registryDir = join(registryPath, '..')\n\n // Ensure directory exists\n if (!existsSync(registryDir)) {\n mkdirSync(registryDir, { recursive: true })\n }\n\n writeFileSync(registryPath, JSON.stringify(entries, null, 2), 'utf-8')\n }\n\n /**\n * Register plugin in registry\n */\n private registerPlugin(\n manifest: PluginManifest,\n source: PluginSource,\n location: string,\n global: boolean,\n ): void {\n const registry = this.loadRegistry(global)\n\n // Remove existing entry if present\n const filtered = registry.filter(e => e.name !== manifest.name)\n\n // Add new entry\n filtered.push({\n name: manifest.name,\n version: manifest.version,\n source,\n installedAt: new Date().toISOString(),\n location,\n })\n\n this.saveRegistry(filtered, global)\n }\n\n /**\n * Unregister plugin from registry\n */\n private unregisterPlugin(pluginName: string, global: boolean): void {\n const registry = this.loadRegistry(global)\n const filtered = registry.filter(e => e.name !== pluginName)\n this.saveRegistry(filtered, global)\n }\n\n /**\n * Fetch a git repository to a temporary directory using repoFetcher\n */\n private async fetchToTempDir(source: RepoSource): Promise<string> {\n const tempDir = join(\n homedir(),\n '.minto',\n 'temp',\n 'plugins',\n Date.now().toString(),\n )\n\n this.tempDirs.push(tempDir)\n mkdirSync(tempDir, { recursive: true })\n\n this.emitProgress(InstallPhase.CLONING, `Fetching repository...`, 20)\n\n try {\n await fetchRepo(source, tempDir)\n return tempDir\n } catch (error) {\n throw new PluginError(\n `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n }\n\n /**\n * Validate plugin manifest exists and is valid\n */\n private validateManifest(pluginPath: string): PluginManifest {\n // Check all manifest locations (.minto-plugin > .claude-plugin > root)\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 manifestPath = candidates.find(p => existsSync(p))\n\n if (!manifestPath) {\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 try {\n const content = readFileSync(manifestPath, 'utf-8')\n const data = JSON.parse(content)\n\n // Validate with Zod schema\n const manifest = PluginManifestSchema.parse(data)\n\n // Run directory validation for warnings\n const dirValidation = validatePluginDirectory(pluginPath)\n if (dirValidation.warnings.length > 0) {\n for (const warning of dirValidation.warnings) {\n this.emitProgress(\n InstallPhase.VALIDATING_MANIFEST,\n `Warning: ${warning}`,\n 35,\n )\n }\n }\n\n return manifest\n } catch (error) {\n throw new PluginError(\n `Invalid plugin manifest: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.MANIFEST_INVALID,\n undefined,\n error,\n )\n }\n }\n\n /**\n * Check if plugin is already installed\n */\n private isPluginInstalled(pluginName: string, global: boolean): boolean {\n const registry = this.loadRegistry(global)\n return registry.some(e => e.name === pluginName)\n }\n\n /**\n * Validate plugin components exist\n */\n private validateComponents(\n pluginPath: string,\n manifest: PluginManifest,\n strict: boolean,\n ): void {\n const missing: string[] = []\n\n // Check agents\n for (const agentPath of manifest.agents || []) {\n const fullPath = join(pluginPath, agentPath)\n if (!existsSync(fullPath)) {\n missing.push(`Agent: ${agentPath}`)\n }\n }\n\n // Check commands\n for (const commandPath of manifest.commands || []) {\n const fullPath = join(pluginPath, commandPath)\n if (!existsSync(fullPath)) {\n missing.push(`Command: ${commandPath}`)\n }\n }\n\n // Check skills\n for (const skillPath of manifest.skills || []) {\n const fullPath = join(pluginPath, skillPath)\n if (!existsSync(fullPath)) {\n missing.push(`Skill: ${skillPath}`)\n }\n }\n\n if (missing.length > 0 && strict) {\n throw new PluginError(\n `Missing plugin components:\\n${missing.join('\\n')}`,\n PluginErrorCode.COMPONENT_NOT_FOUND,\n manifest.name,\n )\n } else if (missing.length > 0) {\n console.warn(`Warning: Missing plugin components:\\n${missing.join('\\n')}`)\n }\n }\n\n /**\n * Check disk space availability\n */\n private checkDiskSpace(targetDir: string): void {\n try {\n // Create parent directory if it doesn't exist\n const parentDir = join(targetDir, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n } catch (error) {\n throw new PluginError(\n `Insufficient permissions or disk space: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n undefined,\n error,\n )\n }\n }\n\n /**\n * Install plugin from source directory to target directory\n */\n private installToTarget(\n sourceDir: string,\n targetDir: string,\n options?: InstallOptions,\n ): void {\n this.emitProgress(InstallPhase.INSTALLING, `Installing to ${targetDir}`, 60)\n\n // Check if target exists\n if (existsSync(targetDir)) {\n if (options?.force) {\n rmSync(targetDir, { recursive: true, force: true })\n } else {\n throw new PluginError(\n `Plugin directory already exists: ${targetDir}. Use --force to overwrite.`,\n PluginErrorCode.ALREADY_INSTALLED,\n )\n }\n }\n\n // Create parent directory\n const parentDir = join(targetDir, '..')\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true })\n }\n\n // Install: symlink for dev mode, copy otherwise\n if (options?.dev) {\n symlinkSync(sourceDir, targetDir, 'dir')\n } else {\n cpSync(sourceDir, targetDir, { recursive: true })\n }\n }\n\n /**\n * Cleanup temporary directories\n */\n private cleanup(): void {\n for (const tempDir of this.tempDirs) {\n try {\n if (existsSync(tempDir)) {\n rmSync(tempDir, { recursive: true, force: true })\n }\n } catch (error) {\n console.error(`Error cleaning up temp directory ${tempDir}:`, error)\n }\n }\n\n this.tempDirs = []\n }\n\n /**\n * Install plugin from any source\n */\n async installPlugin(\n source: PluginSource,\n options?: InstallOptions,\n ): Promise<string> {\n let sourceDir: string | undefined\n let manifest: PluginManifest | undefined\n\n try {\n // Phase 1: Validate and fetch source\n this.emitProgress(\n InstallPhase.VALIDATING_SOURCE,\n 'Validating plugin source',\n 0,\n )\n\n switch (source.type) {\n case 'git': {\n // Detect GitHub URLs and use tarball; otherwise use URL source\n const ghMatch = source.repo.match(\n /github\\.com[/:]([^/]+\\/[^/.]+?)(?:\\.git)?$/,\n )\n if (ghMatch) {\n sourceDir = await this.fetchToTempDir({\n type: 'github',\n repo: ghMatch[1],\n ref: source.ref,\n })\n } else {\n sourceDir = await this.fetchToTempDir({\n type: 'url',\n url: source.repo,\n ref: source.ref,\n })\n }\n break\n }\n\n case 'local':\n sourceDir = resolve(source.path)\n if (!existsSync(sourceDir)) {\n throw new PluginError(\n `Local plugin path does not exist: ${sourceDir}`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n break\n\n case 'npm':\n throw new PluginError(\n 'NPM package installation not yet supported',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n\n case 'marketplace':\n // Find plugin in marketplace\n const found = findPlugin(source.name, source.marketplace)\n\n if (!found) {\n throw new PluginError(\n source.marketplace\n ? `Plugin \"${source.name}\" not found in marketplace \"${source.marketplace}\"`\n : `Plugin \"${source.name}\" not found in any marketplace`,\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n const { plugin } = found\n\n // Recursively install from plugin's source\n if (typeof plugin.source === 'string') {\n throw new PluginError(\n 'Relative path plugins not yet supported',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n } else if (plugin.source.source === 'github') {\n sourceDir = await this.fetchToTempDir({\n type: 'github',\n repo: plugin.source.repo,\n ref: plugin.source.ref,\n })\n } else if (plugin.source.source === 'url') {\n sourceDir = await this.fetchToTempDir({\n type: 'url',\n url: plugin.source.url,\n ref: plugin.source.ref,\n })\n } else {\n throw new PluginError(\n 'Unsupported marketplace plugin source type',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n break\n\n default:\n throw new PluginError(\n 'Unknown plugin source type',\n PluginErrorCode.MANIFEST_NOT_FOUND,\n )\n }\n\n // Phase 2: Validate manifest\n this.emitProgress(\n InstallPhase.VALIDATING_MANIFEST,\n 'Validating plugin manifest',\n 30,\n )\n\n manifest = this.validateManifest(sourceDir)\n\n // Check if already installed\n const global = options?.global ?? false\n if (this.isPluginInstalled(manifest.name, global) && !options?.force) {\n throw new PluginError(\n `Plugin \"${manifest.name}\" is already installed. Use --force to overwrite.`,\n PluginErrorCode.ALREADY_INSTALLED,\n manifest.name,\n )\n }\n\n // Phase 3: Validate components\n this.emitProgress(\n InstallPhase.VALIDATING_MANIFEST,\n 'Validating plugin components',\n 40,\n )\n\n const strict = options?.validation === 'strict'\n this.validateComponents(sourceDir, manifest, strict)\n\n // Phase 4: Check dependencies (placeholder)\n this.emitProgress(\n InstallPhase.CHECKING_DEPENDENCIES,\n 'Checking dependencies',\n 50,\n )\n\n // TODO: Check engine versions, dependencies, etc.\n\n // Phase 5: Determine target directory\n const targetDir = this.getInstallDir(manifest.name, options)\n\n // Check disk space and permissions\n this.checkDiskSpace(targetDir)\n\n // Phase 6: Install to target\n this.installToTarget(sourceDir, targetDir, options)\n\n // Phase 7: Register plugin\n this.emitProgress(InstallPhase.REGISTERING, 'Registering plugin', 80)\n\n this.registerPlugin(manifest, source, targetDir, global)\n\n // Phase 8: Complete\n this.emitProgress(\n InstallPhase.COMPLETE,\n `Successfully installed ${manifest.name}`,\n 100,\n manifest.name,\n )\n\n return targetDir\n } catch (error) {\n // Cleanup on error\n this.emitProgress(\n InstallPhase.CLEANUP,\n 'Installation failed, cleaning up',\n 0,\n )\n\n throw error\n } finally {\n // Always cleanup temp directories\n this.cleanup()\n }\n }\n\n /**\n * Uninstall a plugin by name\n */\n async uninstallPlugin(\n pluginName: string,\n options?: { global?: boolean },\n ): Promise<void> {\n const global = options?.global ?? false\n const registry = this.loadRegistry(global)\n\n // Find plugin in registry\n const entry = registry.find(e => e.name === pluginName)\n\n if (!entry) {\n throw new PluginError(\n `Plugin \"${pluginName}\" is not installed`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n // Remove plugin directory\n if (existsSync(entry.location)) {\n try {\n rmSync(entry.location, { recursive: true, force: true })\n } catch (error) {\n throw new PluginError(\n `Failed to remove plugin directory: ${error instanceof Error ? error.message : String(error)}`,\n PluginErrorCode.PERMISSION_DENIED,\n pluginName,\n error,\n )\n }\n }\n\n // Unregister from registry\n this.unregisterPlugin(pluginName, global)\n }\n\n /**\n * Update a plugin (re-install from source)\n */\n async updatePlugin(\n pluginName: string,\n options?: { global?: boolean },\n ): Promise<void> {\n const global = options?.global ?? false\n const registry = this.loadRegistry(global)\n\n // Find plugin in registry\n const entry = registry.find(e => e.name === pluginName)\n\n if (!entry) {\n throw new PluginError(\n `Plugin \"${pluginName}\" is not installed`,\n PluginErrorCode.NOT_INSTALLED,\n pluginName,\n )\n }\n\n // Uninstall and reinstall\n await this.uninstallPlugin(pluginName, { global })\n await this.installPlugin(entry.source, { global, force: true })\n }\n}\n\n/**\n * Convenience function: Install plugin from source\n */\nexport async function installPlugin(\n source: PluginSource,\n options?: InstallOptions,\n): Promise<string> {\n const installer = new PluginInstaller()\n\n // Setup progress listener if not silent\n if (!options?.silent) {\n installer.on('progress', (progress: InstallProgress) => {\n console.log(\n `[${progress.percentage}%] ${progress.phase}: ${progress.message}`,\n )\n })\n }\n\n return installer.installPlugin(source, options)\n}\n\n/**\n * Convenience function: Uninstall plugin by name\n */\nexport async function uninstallPlugin(\n name: string,\n options?: { global?: boolean },\n): Promise<void> {\n const installer = new PluginInstaller()\n return installer.uninstallPlugin(name, options)\n}\n\n/**\n * Convenience function: Update plugin by name\n */\nexport async function updatePlugin(\n name: string,\n options?: { global?: boolean },\n): Promise<void> {\n const installer = new PluginInstaller()\n return installer.updatePlugin(name, options)\n}\n\n/**\n * List all installed plugins\n */\nexport function listInstalledPlugins(global?: boolean): PluginRegistryEntry[] {\n const installer = new PluginInstaller()\n const globalRegistry = installer['loadRegistry'](true)\n const projectRegistry = installer['loadRegistry'](false)\n\n if (global === true) {\n return globalRegistry\n } else if (global === false) {\n return projectRegistry\n } else {\n // Return both, with project plugins overriding global\n const combined = new Map<string, PluginRegistryEntry>()\n\n for (const entry of globalRegistry) {\n combined.set(entry.name, entry)\n }\n\n for (const entry of projectRegistry) {\n combined.set(entry.name, entry)\n }\n\n return Array.from(combined.values())\n }\n}\n"],
5
+ "mappings": "AAaA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,MAAM,eAAyB;AACxC,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,iBAA6B;AACtC,SAAS,cAAc;AACvB;AAAA,EAEE;AAAA,EAEA;AAAA,EACA;AAAA,OACK;AACP,SAAS,kBAAkB;AAC3B,SAAS,+BAA+B;AAwCjC,IAAK,eAAL,kBAAKA,kBAAL;AACL,EAAAA,cAAA,uBAAoB;AACpB,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,yBAAsB;AACtB,EAAAA,cAAA,2BAAwB;AACxB,EAAAA,cAAA,gBAAa;AACb,EAAAA,cAAA,iBAAc;AACd,EAAAA,cAAA,aAAU;AACV,EAAAA,cAAA,cAAW;AATD,SAAAA;AAAA,GAAA;AAoCL,MAAM,wBAAwB,aAAa;AAAA,EACxC,WAAqB,CAAC;AAAA;AAAA;AAAA;AAAA,EAKtB,aACN,OACA,SACA,YACA,YACM;AACN,SAAK,KAAK,YAAY;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAoB;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA,EAKQ,cAAc,YAAoB,SAAkC;AAC1E,QAAI,SAAS,WAAW;AACtB,aAAO,QAAQ,QAAQ,SAAS;AAAA,IAClC;AAGA,UAAM,QAAQ,SAAS;AACvB,QAAI,OAAO;AACT,cAAQ,OAAO;AAAA,QACb,KAAK;AACH,iBAAO,KAAK,QAAQ,GAAG,UAAU,WAAW,UAAU;AAAA,QACxD,KAAK;AACH,iBAAO,KAAK,OAAO,GAAG,UAAU,WAAW,UAAU;AAAA,QACvD,KAAK;AACH,iBAAO,KAAK,OAAO,GAAG,UAAU,iBAAiB,UAAU;AAAA,MAC/D;AAAA,IACF;AAGA,UAAM,UAAU,SAAS,SAAS,QAAQ,IAAI,OAAO;AACrD,WAAO,KAAK,SAAS,UAAU,WAAW,UAAU;AAAA,EACtD;AAAA;AAAA;AAAA;AAAA,EAKQ,gBAAgB,QAAyB;AAC/C,UAAM,UAAU,SAAS,QAAQ,IAAI,OAAO;AAC5C,WAAO,KAAK,SAAS,UAAU,WAAW,eAAe;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,QAAwC;AAC3D,UAAM,eAAe,KAAK,gBAAgB,MAAM;AAEhD,QAAI,CAAC,WAAW,YAAY,GAAG;AAC7B,aAAO,CAAC;AAAA,IACV;AAEA,QAAI;AACF,YAAM,UAAU,aAAa,cAAc,OAAO;AAClD,aAAO,KAAK,MAAM,OAAO;AAAA,IAC3B,SAAS,OAAO;AACd,cAAQ,MAAM,kCAAkC,KAAK;AACrD,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,SAAgC,QAAuB;AAC1E,UAAM,eAAe,KAAK,gBAAgB,MAAM;AAChD,UAAM,cAAc,KAAK,cAAc,IAAI;AAG3C,QAAI,CAAC,WAAW,WAAW,GAAG;AAC5B,gBAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAAA,IAC5C;AAEA,kBAAc,cAAc,KAAK,UAAU,SAAS,MAAM,CAAC,GAAG,OAAO;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA,EAKQ,eACN,UACA,QACA,UACA,QACM;AACN,UAAM,WAAW,KAAK,aAAa,MAAM;AAGzC,UAAM,WAAW,SAAS,OAAO,OAAK,EAAE,SAAS,SAAS,IAAI;AAG9D,aAAS,KAAK;AAAA,MACZ,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,IACF,CAAC;AAED,SAAK,aAAa,UAAU,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,YAAoB,QAAuB;AAClE,UAAM,WAAW,KAAK,aAAa,MAAM;AACzC,UAAM,WAAW,SAAS,OAAO,OAAK,EAAE,SAAS,UAAU;AAC3D,SAAK,aAAa,UAAU,MAAM;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,eAAe,QAAqC;AAChE,UAAM,UAAU;AAAA,MACd,QAAQ;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA,KAAK,IAAI,EAAE,SAAS;AAAA,IACtB;AAEA,SAAK,SAAS,KAAK,OAAO;AAC1B,cAAU,SAAS,EAAE,WAAW,KAAK,CAAC;AAEtC,SAAK,aAAa,yBAAsB,0BAA0B,EAAE;AAEpE,QAAI;AACF,YAAM,UAAU,QAAQ,OAAO;AAC/B,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,+BAA+B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACrF,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,iBAAiB,YAAoC;AAE3D,UAAM,aAAa;AAAA,MACjB,KAAK,YAAY,iBAAiB,aAAa;AAAA,MAC/C,KAAK,YAAY,kBAAkB,aAAa;AAAA,MAChD,KAAK,YAAY,aAAa;AAAA,IAChC;AAEA,UAAM,eAAe,WAAW,KAAK,OAAK,WAAW,CAAC,CAAC;AAEvD,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI;AAAA,QACR;AAAA,EAAsC,WAAW,IAAI,OAAK,OAAO,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,QAChF,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,aAAa,cAAc,OAAO;AAClD,YAAM,OAAO,KAAK,MAAM,OAAO;AAG/B,YAAM,WAAW,qBAAqB,MAAM,IAAI;AAGhD,YAAM,gBAAgB,wBAAwB,UAAU;AACxD,UAAI,cAAc,SAAS,SAAS,GAAG;AACrC,mBAAW,WAAW,cAAc,UAAU;AAC5C,eAAK;AAAA,YACH;AAAA,YACA,YAAY,OAAO;AAAA,YACnB;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,4BAA4B,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QAClF,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB,YAAoB,QAA0B;AACtE,UAAM,WAAW,KAAK,aAAa,MAAM;AACzC,WAAO,SAAS,KAAK,OAAK,EAAE,SAAS,UAAU;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKQ,mBACN,YACA,UACA,QACM;AACN,UAAM,UAAoB,CAAC;AAG3B,eAAW,aAAa,SAAS,UAAU,CAAC,GAAG;AAC7C,YAAM,WAAW,KAAK,YAAY,SAAS;AAC3C,UAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,gBAAQ,KAAK,UAAU,SAAS,EAAE;AAAA,MACpC;AAAA,IACF;AAGA,eAAW,eAAe,SAAS,YAAY,CAAC,GAAG;AACjD,YAAM,WAAW,KAAK,YAAY,WAAW;AAC7C,UAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,gBAAQ,KAAK,YAAY,WAAW,EAAE;AAAA,MACxC;AAAA,IACF;AAGA,eAAW,aAAa,SAAS,UAAU,CAAC,GAAG;AAC7C,YAAM,WAAW,KAAK,YAAY,SAAS;AAC3C,UAAI,CAAC,WAAW,QAAQ,GAAG;AACzB,gBAAQ,KAAK,UAAU,SAAS,EAAE;AAAA,MACpC;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,KAAK,QAAQ;AAChC,YAAM,IAAI;AAAA,QACR;AAAA,EAA+B,QAAQ,KAAK,IAAI,CAAC;AAAA,QACjD,gBAAgB;AAAA,QAChB,SAAS;AAAA,MACX;AAAA,IACF,WAAW,QAAQ,SAAS,GAAG;AAC7B,cAAQ,KAAK;AAAA,EAAwC,QAAQ,KAAK,IAAI,CAAC,EAAE;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,WAAyB;AAC9C,QAAI;AAEF,YAAM,YAAY,KAAK,WAAW,IAAI;AACtC,UAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,kBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,MAC1C;AAAA,IACF,SAAS,OAAO;AACd,YAAM,IAAI;AAAA,QACR,2CAA2C,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,QACjG,gBAAgB;AAAA,QAChB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,gBACN,WACA,WACA,SACM;AACN,SAAK,aAAa,+BAAyB,iBAAiB,SAAS,IAAI,EAAE;AAG3E,QAAI,WAAW,SAAS,GAAG;AACzB,UAAI,SAAS,OAAO;AAClB,eAAO,WAAW,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACpD,OAAO;AACL,cAAM,IAAI;AAAA,UACR,oCAAoC,SAAS;AAAA,UAC7C,gBAAgB;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,YAAY,KAAK,WAAW,IAAI;AACtC,QAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,gBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAC1C;AAGA,QAAI,SAAS,KAAK;AAChB,kBAAY,WAAW,WAAW,KAAK;AAAA,IACzC,OAAO;AACL,aAAO,WAAW,WAAW,EAAE,WAAW,KAAK,CAAC;AAAA,IAClD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,UAAgB;AACtB,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI;AACF,YAAI,WAAW,OAAO,GAAG;AACvB,iBAAO,SAAS,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,QAClD;AAAA,MACF,SAAS,OAAO;AACd,gBAAQ,MAAM,oCAAoC,OAAO,KAAK,KAAK;AAAA,MACrE;AAAA,IACF;AAEA,SAAK,WAAW,CAAC;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cACJ,QACA,SACiB;AACjB,QAAI;AACJ,QAAI;AAEJ,QAAI;AAEF,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,cAAQ,OAAO,MAAM;AAAA,QACnB,KAAK,OAAO;AAEV,gBAAM,UAAU,OAAO,KAAK;AAAA,YAC1B;AAAA,UACF;AACA,cAAI,SAAS;AACX,wBAAY,MAAM,KAAK,eAAe;AAAA,cACpC,MAAM;AAAA,cACN,MAAM,QAAQ,CAAC;AAAA,cACf,KAAK,OAAO;AAAA,YACd,CAAC;AAAA,UACH,OAAO;AACL,wBAAY,MAAM,KAAK,eAAe;AAAA,cACpC,MAAM;AAAA,cACN,KAAK,OAAO;AAAA,cACZ,KAAK,OAAO;AAAA,YACd,CAAC;AAAA,UACH;AACA;AAAA,QACF;AAAA,QAEA,KAAK;AACH,sBAAY,QAAQ,OAAO,IAAI;AAC/B,cAAI,CAAC,WAAW,SAAS,GAAG;AAC1B,kBAAM,IAAI;AAAA,cACR,qCAAqC,SAAS;AAAA,cAC9C,gBAAgB;AAAA,YAClB;AAAA,UACF;AACA;AAAA,QAEF,KAAK;AACH,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,gBAAgB;AAAA,UAClB;AAAA,QAEF,KAAK;AAEH,gBAAM,QAAQ,WAAW,OAAO,MAAM,OAAO,WAAW;AAExD,cAAI,CAAC,OAAO;AACV,kBAAM,IAAI;AAAA,cACR,OAAO,cACH,WAAW,OAAO,IAAI,+BAA+B,OAAO,WAAW,MACvE,WAAW,OAAO,IAAI;AAAA,cAC1B,gBAAgB;AAAA,YAClB;AAAA,UACF;AAEA,gBAAM,EAAE,OAAO,IAAI;AAGnB,cAAI,OAAO,OAAO,WAAW,UAAU;AACrC,kBAAM,IAAI;AAAA,cACR;AAAA,cACA,gBAAgB;AAAA,YAClB;AAAA,UACF,WAAW,OAAO,OAAO,WAAW,UAAU;AAC5C,wBAAY,MAAM,KAAK,eAAe;AAAA,cACpC,MAAM;AAAA,cACN,MAAM,OAAO,OAAO;AAAA,cACpB,KAAK,OAAO,OAAO;AAAA,YACrB,CAAC;AAAA,UACH,WAAW,OAAO,OAAO,WAAW,OAAO;AACzC,wBAAY,MAAM,KAAK,eAAe;AAAA,cACpC,MAAM;AAAA,cACN,KAAK,OAAO,OAAO;AAAA,cACnB,KAAK,OAAO,OAAO;AAAA,YACrB,CAAC;AAAA,UACH,OAAO;AACL,kBAAM,IAAI;AAAA,cACR;AAAA,cACA,gBAAgB;AAAA,YAClB;AAAA,UACF;AACA;AAAA,QAEF;AACE,gBAAM,IAAI;AAAA,YACR;AAAA,YACA,gBAAgB;AAAA,UAClB;AAAA,MACJ;AAGA,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,iBAAW,KAAK,iBAAiB,SAAS;AAG1C,YAAM,SAAS,SAAS,UAAU;AAClC,UAAI,KAAK,kBAAkB,SAAS,MAAM,MAAM,KAAK,CAAC,SAAS,OAAO;AACpE,cAAM,IAAI;AAAA,UACR,WAAW,SAAS,IAAI;AAAA,UACxB,gBAAgB;AAAA,UAChB,SAAS;AAAA,QACX;AAAA,MACF;AAGA,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM,SAAS,SAAS,eAAe;AACvC,WAAK,mBAAmB,WAAW,UAAU,MAAM;AAGnD,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAKA,YAAM,YAAY,KAAK,cAAc,SAAS,MAAM,OAAO;AAG3D,WAAK,eAAe,SAAS;AAG7B,WAAK,gBAAgB,WAAW,WAAW,OAAO;AAGlD,WAAK,aAAa,iCAA0B,sBAAsB,EAAE;AAEpE,WAAK,eAAe,UAAU,QAAQ,WAAW,MAAM;AAGvD,WAAK;AAAA,QACH;AAAA,QACA,0BAA0B,SAAS,IAAI;AAAA,QACvC;AAAA,QACA,SAAS;AAAA,MACX;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,WAAK;AAAA,QACH;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAEA,YAAM;AAAA,IACR,UAAE;AAEA,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,gBACJ,YACA,SACe;AACf,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,WAAW,KAAK,aAAa,MAAM;AAGzC,UAAM,QAAQ,SAAS,KAAK,OAAK,EAAE,SAAS,UAAU;AAEtD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,WAAW,UAAU;AAAA,QACrB,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAGA,QAAI,WAAW,MAAM,QAAQ,GAAG;AAC9B,UAAI;AACF,eAAO,MAAM,UAAU,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,MACzD,SAAS,OAAO;AACd,cAAM,IAAI;AAAA,UACR,sCAAsC,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,UAC5F,gBAAgB;AAAA,UAChB;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,SAAK,iBAAiB,YAAY,MAAM;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aACJ,YACA,SACe;AACf,UAAM,SAAS,SAAS,UAAU;AAClC,UAAM,WAAW,KAAK,aAAa,MAAM;AAGzC,UAAM,QAAQ,SAAS,KAAK,OAAK,EAAE,SAAS,UAAU;AAEtD,QAAI,CAAC,OAAO;AACV,YAAM,IAAI;AAAA,QACR,WAAW,UAAU;AAAA,QACrB,gBAAgB;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAGA,UAAM,KAAK,gBAAgB,YAAY,EAAE,OAAO,CAAC;AACjD,UAAM,KAAK,cAAc,MAAM,QAAQ,EAAE,QAAQ,OAAO,KAAK,CAAC;AAAA,EAChE;AACF;AAKA,eAAsB,cACpB,QACA,SACiB;AACjB,QAAM,YAAY,IAAI,gBAAgB;AAGtC,MAAI,CAAC,SAAS,QAAQ;AACpB,cAAU,GAAG,YAAY,CAAC,aAA8B;AACtD,cAAQ;AAAA,QACN,IAAI,SAAS,UAAU,MAAM,SAAS,KAAK,KAAK,SAAS,OAAO;AAAA,MAClE;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO,UAAU,cAAc,QAAQ,OAAO;AAChD;AAKA,eAAsB,gBACpB,MACA,SACe;AACf,QAAM,YAAY,IAAI,gBAAgB;AACtC,SAAO,UAAU,gBAAgB,MAAM,OAAO;AAChD;AAKA,eAAsB,aACpB,MACA,SACe;AACf,QAAM,YAAY,IAAI,gBAAgB;AACtC,SAAO,UAAU,aAAa,MAAM,OAAO;AAC7C;AAKO,SAAS,qBAAqB,QAAyC;AAC5E,QAAM,YAAY,IAAI,gBAAgB;AACtC,QAAM,iBAAiB,UAAU,cAAc,EAAE,IAAI;AACrD,QAAM,kBAAkB,UAAU,cAAc,EAAE,KAAK;AAEvD,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT,WAAW,WAAW,OAAO;AAC3B,WAAO;AAAA,EACT,OAAO;AAEL,UAAM,WAAW,oBAAI,IAAiC;AAEtD,eAAW,SAAS,gBAAgB;AAClC,eAAS,IAAI,MAAM,MAAM,KAAK;AAAA,IAChC;AAEA,eAAW,SAAS,iBAAiB;AACnC,eAAS,IAAI,MAAM,MAAM,KAAK;AAAA,IAChC;AAEA,WAAO,MAAM,KAAK,SAAS,OAAO,CAAC;AAAA,EACrC;AACF;",
6
6
  "names": ["InstallPhase"]
7
7
  }