@within-7/minto 0.3.9 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (383) hide show
  1. package/dist/Tool.js.map +2 -2
  2. package/dist/commands/agents/AgentsCommand.js +461 -657
  3. package/dist/commands/agents/AgentsCommand.js.map +2 -2
  4. package/dist/commands/agents/types.js +1 -0
  5. package/dist/commands/agents/types.js.map +2 -2
  6. package/dist/commands/agents/utils/fileOperations.js +96 -36
  7. package/dist/commands/agents/utils/fileOperations.js.map +3 -3
  8. package/dist/commands/agents/utils/index.js +3 -1
  9. package/dist/commands/agents/utils/index.js.map +2 -2
  10. package/dist/commands/context.js +54 -23
  11. package/dist/commands/context.js.map +2 -2
  12. package/dist/commands/ctx_viz.js +1 -1
  13. package/dist/commands/effort.js +87 -0
  14. package/dist/commands/effort.js.map +7 -0
  15. package/dist/commands/export.js +684 -94
  16. package/dist/commands/export.js.map +2 -2
  17. package/dist/commands/ide.js +18 -0
  18. package/dist/commands/ide.js.map +7 -0
  19. package/dist/commands/language.js +19 -46
  20. package/dist/commands/language.js.map +2 -2
  21. package/dist/commands/mcp-interactive.js +425 -217
  22. package/dist/commands/mcp-interactive.js.map +2 -2
  23. package/dist/commands/memory.js +168 -0
  24. package/dist/commands/memory.js.map +7 -0
  25. package/dist/commands/model.js +457 -65
  26. package/dist/commands/model.js.map +2 -2
  27. package/dist/commands/outputStyle.js +64 -0
  28. package/dist/commands/outputStyle.js.map +7 -0
  29. package/dist/commands/permissions.js +75 -49
  30. package/dist/commands/permissions.js.map +2 -2
  31. package/dist/commands/plugin/utils.js +33 -1
  32. package/dist/commands/plugin/utils.js.map +2 -2
  33. package/dist/commands/plugin.js +891 -185
  34. package/dist/commands/plugin.js.map +3 -3
  35. package/dist/commands/refreshCommands.js +2 -0
  36. package/dist/commands/refreshCommands.js.map +2 -2
  37. package/dist/commands/resume.js +1 -1
  38. package/dist/commands/resume.js.map +1 -1
  39. package/dist/commands/review.js +51 -0
  40. package/dist/commands/review.js.map +7 -0
  41. package/dist/commands/sandbox.js +168 -70
  42. package/dist/commands/sandbox.js.map +2 -2
  43. package/dist/commands/setup.js +593 -107
  44. package/dist/commands/setup.js.map +2 -2
  45. package/dist/commands/stats.js +188 -131
  46. package/dist/commands/stats.js.map +2 -2
  47. package/dist/commands/status.js +75 -13
  48. package/dist/commands/status.js.map +2 -2
  49. package/dist/commands/terminalSetup.js +6 -0
  50. package/dist/commands/terminalSetup.js.map +2 -2
  51. package/dist/commands/undo.js +146 -174
  52. package/dist/commands/undo.js.map +2 -2
  53. package/dist/commands/vim.js +22 -0
  54. package/dist/commands/vim.js.map +7 -0
  55. package/dist/commands.js +12 -0
  56. package/dist/commands.js.map +2 -2
  57. package/dist/components/Help.js +165 -32
  58. package/dist/components/Help.js.map +2 -2
  59. package/dist/components/HighlightedCode.js +1 -0
  60. package/dist/components/HighlightedCode.js.map +2 -2
  61. package/dist/components/InfoPanel/InfoPanel.js +123 -0
  62. package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
  63. package/dist/components/InfoPanel/index.js +5 -0
  64. package/dist/components/InfoPanel/index.js.map +7 -0
  65. package/dist/components/InfoPanel/types.js +1 -0
  66. package/dist/components/InfoPanel/types.js.map +7 -0
  67. package/dist/components/ModelSelector/BrandTextInput.js +43 -0
  68. package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
  69. package/dist/components/ModelSelector/ModelSelector.js +590 -565
  70. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  71. package/dist/components/ModelSelector/WizardContainer.js +45 -0
  72. package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
  73. package/dist/components/ModelSelector/index.js +1 -3
  74. package/dist/components/ModelSelector/index.js.map +2 -2
  75. package/dist/components/PromptInput.js +26 -11
  76. package/dist/components/PromptInput.js.map +2 -2
  77. package/dist/components/PulseLabel.js +44 -0
  78. package/dist/components/PulseLabel.js.map +7 -0
  79. package/dist/components/RequestStatusIndicator.js +1 -1
  80. package/dist/components/RequestStatusIndicator.js.map +1 -1
  81. package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
  82. package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
  83. package/dist/components/SimpleSelector/index.js +5 -0
  84. package/dist/components/SimpleSelector/index.js.map +7 -0
  85. package/dist/components/SimpleSelector/types.js +1 -0
  86. package/dist/components/SimpleSelector/types.js.map +7 -0
  87. package/dist/components/Spinner.js +12 -42
  88. package/dist/components/Spinner.js.map +3 -3
  89. package/dist/components/StartupStatus.js +57 -0
  90. package/dist/components/StartupStatus.js.map +7 -0
  91. package/dist/components/StatusOverlayContent.js +21 -0
  92. package/dist/components/StatusOverlayContent.js.map +7 -0
  93. package/dist/components/SubagentBlock.js +43 -6
  94. package/dist/components/SubagentBlock.js.map +2 -2
  95. package/dist/components/TabbedListView/ScrollableList.js +31 -5
  96. package/dist/components/TabbedListView/ScrollableList.js.map +2 -2
  97. package/dist/components/TabbedListView/TabBar.js +13 -8
  98. package/dist/components/TabbedListView/TabBar.js.map +2 -2
  99. package/dist/components/TabbedListView/TabbedListView.js +123 -48
  100. package/dist/components/TabbedListView/TabbedListView.js.map +2 -2
  101. package/dist/components/TodoPanel.js +1 -1
  102. package/dist/components/TodoPanel.js.map +1 -1
  103. package/dist/components/ToolUseLoader.js +5 -0
  104. package/dist/components/ToolUseLoader.js.map +2 -2
  105. package/dist/components/TrustDialog.js +0 -2
  106. package/dist/components/TrustDialog.js.map +2 -2
  107. package/dist/components/messages/TaskInModuleView.js +1 -1
  108. package/dist/components/messages/TaskInModuleView.js.map +2 -2
  109. package/dist/components/messages/TaskToolMessage.js +1 -1
  110. package/dist/components/messages/TaskToolMessage.js.map +2 -2
  111. package/dist/components/messages/UserPromptMessage.js +6 -1
  112. package/dist/components/messages/UserPromptMessage.js.map +2 -2
  113. package/dist/constants/modelCapabilities.js +103 -18
  114. package/dist/constants/modelCapabilities.js.map +2 -2
  115. package/dist/constants/product.js +2 -0
  116. package/dist/constants/product.js.map +2 -2
  117. package/dist/constants/prompts/agentPrompt.js +30 -0
  118. package/dist/constants/prompts/agentPrompt.js.map +7 -0
  119. package/dist/constants/prompts/codeConventions.js +27 -0
  120. package/dist/constants/prompts/codeConventions.js.map +7 -0
  121. package/dist/constants/prompts/doingTasks.js +15 -0
  122. package/dist/constants/prompts/doingTasks.js.map +7 -0
  123. package/dist/constants/prompts/envInfo.js +17 -0
  124. package/dist/constants/prompts/envInfo.js.map +7 -0
  125. package/dist/constants/prompts/executingWithCare.js +17 -0
  126. package/dist/constants/prompts/executingWithCare.js.map +7 -0
  127. package/dist/constants/prompts/identity.js +10 -0
  128. package/dist/constants/prompts/identity.js.map +7 -0
  129. package/dist/constants/prompts/index.js +78 -0
  130. package/dist/constants/prompts/index.js.map +7 -0
  131. package/dist/constants/prompts/taskManagement.js +60 -0
  132. package/dist/constants/prompts/taskManagement.js.map +7 -0
  133. package/dist/constants/prompts/toneAndStyle.js +62 -0
  134. package/dist/constants/prompts/toneAndStyle.js.map +7 -0
  135. package/dist/constants/prompts/toolUsagePolicy.js +38 -0
  136. package/dist/constants/prompts/toolUsagePolicy.js.map +7 -0
  137. package/dist/constants/prompts.js +5 -176
  138. package/dist/constants/prompts.js.map +2 -2
  139. package/dist/constants/providerRegistry.js +235 -0
  140. package/dist/constants/providerRegistry.js.map +7 -0
  141. package/dist/constants/providers.js +35 -0
  142. package/dist/constants/providers.js.map +7 -0
  143. package/dist/context/PermissionContext.js +0 -1
  144. package/dist/context/PermissionContext.js.map +2 -2
  145. package/dist/context.js +87 -31
  146. package/dist/context.js.map +2 -2
  147. package/dist/core/backupHook.js +29 -0
  148. package/dist/core/backupHook.js.map +7 -0
  149. package/dist/core/config/defaults.js +11 -2
  150. package/dist/core/config/defaults.js.map +2 -2
  151. package/dist/core/config/schema.js +21 -3
  152. package/dist/core/config/schema.js.map +2 -2
  153. package/dist/core/costTracker.js +18 -16
  154. package/dist/core/costTracker.js.map +2 -2
  155. package/dist/core/index.js +0 -1
  156. package/dist/core/index.js.map +2 -2
  157. package/dist/core/tokenStatsManager.js +22 -4
  158. package/dist/core/tokenStatsManager.js.map +2 -2
  159. package/dist/cost-tracker.js +0 -16
  160. package/dist/cost-tracker.js.map +2 -2
  161. package/dist/entrypoints/bootstrap.js +3 -1
  162. package/dist/entrypoints/bootstrap.js.map +2 -2
  163. package/dist/entrypoints/cli.js +81 -68
  164. package/dist/entrypoints/cli.js.map +2 -2
  165. package/dist/hooks/useAgentTokenStats.js +1 -1
  166. package/dist/hooks/useAgentTokenStats.js.map +2 -2
  167. package/dist/hooks/useAgentTranscripts.js +2 -1
  168. package/dist/hooks/useAgentTranscripts.js.map +2 -2
  169. package/dist/hooks/useBackgroundShells.js +29 -0
  170. package/dist/hooks/useBackgroundShells.js.map +7 -0
  171. package/dist/hooks/useCanUseTool.js +1 -1
  172. package/dist/hooks/useCanUseTool.js.map +2 -2
  173. package/dist/hooks/useDeferredLoading.js +64 -0
  174. package/dist/hooks/useDeferredLoading.js.map +7 -0
  175. package/dist/hooks/useHookStatus.js +1 -1
  176. package/dist/hooks/useHookStatus.js.map +2 -2
  177. package/dist/hooks/useSessionTracking.js +55 -0
  178. package/dist/hooks/useSessionTracking.js.map +7 -0
  179. package/dist/hooks/useTerminalSize.js +21 -0
  180. package/dist/hooks/useTerminalSize.js.map +2 -2
  181. package/dist/hooks/useTextInput.js +1 -0
  182. package/dist/hooks/useTextInput.js.map +2 -2
  183. package/dist/hooks/useUnifiedCompletion.js +3 -2
  184. package/dist/hooks/useUnifiedCompletion.js.map +2 -2
  185. package/dist/i18n/locales/en.js +299 -1
  186. package/dist/i18n/locales/en.js.map +2 -2
  187. package/dist/i18n/locales/zh-CN.js +300 -2
  188. package/dist/i18n/locales/zh-CN.js.map +2 -2
  189. package/dist/i18n/types.js.map +1 -1
  190. package/dist/messages.js +41 -17
  191. package/dist/messages.js.map +2 -2
  192. package/dist/permissions.js +94 -1
  193. package/dist/permissions.js.map +2 -2
  194. package/dist/query.js +27 -19
  195. package/dist/query.js.map +2 -2
  196. package/dist/screens/REPL.js +83 -74
  197. package/dist/screens/REPL.js.map +2 -2
  198. package/dist/services/adapters/responsesAPI.js +6 -0
  199. package/dist/services/adapters/responsesAPI.js.map +2 -2
  200. package/dist/services/agentTeams/index.js +35 -0
  201. package/dist/services/agentTeams/index.js.map +7 -0
  202. package/dist/services/agentTeams/mailbox.js +114 -0
  203. package/dist/services/agentTeams/mailbox.js.map +7 -0
  204. package/dist/services/agentTeams/teamManager.js +149 -0
  205. package/dist/services/agentTeams/teamManager.js.map +7 -0
  206. package/dist/services/agentTeams/teamTaskStore.js +114 -0
  207. package/dist/services/agentTeams/teamTaskStore.js.map +7 -0
  208. package/dist/services/agentTeams/teammateSpawner.js +80 -0
  209. package/dist/services/agentTeams/teammateSpawner.js.map +7 -0
  210. package/dist/services/checkpointManager.js +16 -3
  211. package/dist/services/checkpointManager.js.map +2 -2
  212. package/dist/services/claude.js +19 -1728
  213. package/dist/services/claude.js.map +3 -3
  214. package/dist/services/customCommands.js +30 -8
  215. package/dist/services/customCommands.js.map +2 -2
  216. package/dist/services/gpt5ConnectionTest.js +4 -2
  217. package/dist/services/gpt5ConnectionTest.js.map +2 -2
  218. package/dist/services/hookExecutor.js +411 -127
  219. package/dist/services/hookExecutor.js.map +2 -2
  220. package/dist/services/llm/anthropicProvider.js +807 -0
  221. package/dist/services/llm/anthropicProvider.js.map +7 -0
  222. package/dist/services/llm/dispatch.js +218 -0
  223. package/dist/services/llm/dispatch.js.map +7 -0
  224. package/dist/services/llm/index.js +44 -0
  225. package/dist/services/llm/index.js.map +7 -0
  226. package/dist/services/llm/mintoContext.js +69 -0
  227. package/dist/services/llm/mintoContext.js.map +7 -0
  228. package/dist/services/llm/openaiProvider.js +622 -0
  229. package/dist/services/llm/openaiProvider.js.map +7 -0
  230. package/dist/services/llm/types.js +157 -0
  231. package/dist/services/llm/types.js.map +7 -0
  232. package/dist/services/mcpClient.js +183 -33
  233. package/dist/services/mcpClient.js.map +2 -2
  234. package/dist/services/notifier.js +14 -0
  235. package/dist/services/notifier.js.map +2 -2
  236. package/dist/services/oauth.js +4 -2
  237. package/dist/services/oauth.js.map +2 -2
  238. package/dist/services/openai.js +66 -56
  239. package/dist/services/openai.js.map +3 -3
  240. package/dist/services/outputStyles.js +102 -21
  241. package/dist/services/outputStyles.js.map +2 -2
  242. package/dist/services/plugins/lspServers.js +1 -1
  243. package/dist/services/plugins/lspServers.js.map +2 -2
  244. package/dist/services/plugins/pluginRuntime.js +2 -1
  245. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  246. package/dist/services/plugins/pluginValidation.js +10 -3
  247. package/dist/services/plugins/pluginValidation.js.map +2 -2
  248. package/dist/services/plugins/skillMarketplace.js +20 -9
  249. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  250. package/dist/services/sentry.js +1 -1
  251. package/dist/services/sentry.js.map +2 -2
  252. package/dist/services/sessionMemory.js +16 -3
  253. package/dist/services/sessionMemory.js.map +2 -2
  254. package/dist/services/systemReminder.js +367 -9
  255. package/dist/services/systemReminder.js.map +2 -2
  256. package/dist/services/taskStore.js +19 -0
  257. package/dist/services/taskStore.js.map +2 -2
  258. package/dist/tools/ArchitectTool/ArchitectTool.js.map +1 -1
  259. package/dist/tools/AskUserQuestionTool/AskUserQuestionTool.js.map +1 -1
  260. package/dist/tools/BashOutputTool/BashOutputTool.js.map +1 -1
  261. package/dist/tools/BashTool/BashTool.js +28 -0
  262. package/dist/tools/BashTool/BashTool.js.map +2 -2
  263. package/dist/tools/FileEditTool/FileEditTool.js +8 -1
  264. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  265. package/dist/tools/FileReadTool/FileReadTool.js +14 -0
  266. package/dist/tools/FileReadTool/FileReadTool.js.map +2 -2
  267. package/dist/tools/FileWriteTool/FileWriteTool.js +10 -1
  268. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  269. package/dist/tools/GlobTool/GlobTool.js.map +1 -1
  270. package/dist/tools/GrepTool/GrepTool.js.map +1 -1
  271. package/dist/tools/KillShellTool/KillShellTool.js.map +1 -1
  272. package/dist/tools/ListMcpResourcesTool/ListMcpResourcesTool.js.map +2 -2
  273. package/dist/tools/LspTool/LspTool.js +11 -2
  274. package/dist/tools/LspTool/LspTool.js.map +2 -2
  275. package/dist/tools/MCPTool/MCPTool.js.map +1 -1
  276. package/dist/tools/MemoryReadTool/MemoryReadTool.js +2 -1
  277. package/dist/tools/MemoryReadTool/MemoryReadTool.js.map +2 -2
  278. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js +2 -1
  279. package/dist/tools/MemoryWriteTool/MemoryWriteTool.js.map +2 -2
  280. package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
  281. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  282. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
  283. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  284. package/dist/tools/NotebookReadTool/NotebookReadTool.js.map +1 -1
  285. package/dist/tools/PlanModeTool/EnterPlanModeTool.js +8 -2
  286. package/dist/tools/PlanModeTool/EnterPlanModeTool.js.map +2 -2
  287. package/dist/tools/PlanModeTool/ExitPlanModeTool.js +2 -0
  288. package/dist/tools/PlanModeTool/ExitPlanModeTool.js.map +2 -2
  289. package/dist/tools/ReadMcpResourceTool/ReadMcpResourceTool.js.map +1 -1
  290. package/dist/tools/SlashCommandTool/SlashCommandTool.js +174 -18
  291. package/dist/tools/SlashCommandTool/SlashCommandTool.js.map +3 -3
  292. package/dist/tools/TaskCreateTool/TaskCreateTool.js.map +1 -1
  293. package/dist/tools/TaskGetTool/TaskGetTool.js.map +1 -1
  294. package/dist/tools/TaskListTool/TaskListTool.js.map +1 -1
  295. package/dist/tools/TaskOutputTool/TaskOutputTool.js.map +1 -1
  296. package/dist/tools/TaskStopTool/TaskStopTool.js.map +1 -1
  297. package/dist/tools/TaskTool/TaskTool.js +84 -11
  298. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  299. package/dist/tools/TaskTool/prompt.js +12 -6
  300. package/dist/tools/TaskTool/prompt.js.map +2 -2
  301. package/dist/tools/TaskUpdateTool/TaskUpdateTool.js.map +1 -1
  302. package/dist/tools/ThinkTool/ThinkTool.js.map +1 -1
  303. package/dist/tools/TodoWriteTool/TodoWriteTool.js.map +1 -1
  304. package/dist/tools/URLFetcherTool/URLFetcherTool.js.map +1 -1
  305. package/dist/tools/WebSearchTool/WebSearchTool.js.map +1 -1
  306. package/dist/tools/WebSearchTool/searchProviders.js +2 -1
  307. package/dist/tools/WebSearchTool/searchProviders.js.map +2 -2
  308. package/dist/tools/lsTool/lsTool.js.map +2 -2
  309. package/dist/tools/lsTool/prompt.js.map +1 -1
  310. package/dist/tools.js +14 -3
  311. package/dist/tools.js.map +2 -2
  312. package/dist/types/PermissionMode.js +21 -1
  313. package/dist/types/PermissionMode.js.map +2 -2
  314. package/dist/types/agentTeams.js +1 -0
  315. package/dist/types/agentTeams.js.map +7 -0
  316. package/dist/types/hooks.js +8 -2
  317. package/dist/types/hooks.js.map +2 -2
  318. package/dist/types/plugin.js +3 -5
  319. package/dist/types/plugin.js.map +2 -2
  320. package/dist/utils/agentHookExecutor.js +1 -4
  321. package/dist/utils/agentHookExecutor.js.map +2 -2
  322. package/dist/utils/agentLoader.js +91 -15
  323. package/dist/utils/agentLoader.js.map +2 -2
  324. package/dist/utils/agentMemory.js.map +2 -2
  325. package/dist/utils/animationManager.js +1 -1
  326. package/dist/utils/animationManager.js.map +2 -2
  327. package/dist/utils/ask.js +1 -1
  328. package/dist/utils/async.js +5 -1
  329. package/dist/utils/async.js.map +2 -2
  330. package/dist/utils/autoCompactCore.js +60 -0
  331. package/dist/utils/autoCompactCore.js.map +2 -2
  332. package/dist/utils/claudeCodeSync.js +439 -0
  333. package/dist/utils/claudeCodeSync.js.map +7 -0
  334. package/dist/utils/config.js +27 -151
  335. package/dist/utils/config.js.map +2 -2
  336. package/dist/utils/configSchema.js +227 -0
  337. package/dist/utils/configSchema.js.map +7 -0
  338. package/dist/utils/debugLogger.js.map +2 -2
  339. package/dist/utils/env.js +4 -3
  340. package/dist/utils/env.js.map +2 -2
  341. package/dist/utils/envConfig.js +34 -0
  342. package/dist/utils/envConfig.js.map +3 -3
  343. package/dist/utils/execFileNoThrow.js +2 -1
  344. package/dist/utils/execFileNoThrow.js.map +2 -2
  345. package/dist/utils/gpt5.js +146 -0
  346. package/dist/utils/gpt5.js.map +7 -0
  347. package/dist/utils/hookManager.js +374 -140
  348. package/dist/utils/hookManager.js.map +2 -2
  349. package/dist/utils/markdown.js +47 -0
  350. package/dist/utils/markdown.js.map +2 -2
  351. package/dist/utils/marketplaceManager.js +80 -43
  352. package/dist/utils/marketplaceManager.js.map +2 -2
  353. package/dist/utils/memoizeWithTTL.js +25 -0
  354. package/dist/utils/memoizeWithTTL.js.map +7 -0
  355. package/dist/utils/messages.js +2 -2
  356. package/dist/utils/messages.js.map +2 -2
  357. package/dist/utils/model.js +34 -9
  358. package/dist/utils/model.js.map +2 -2
  359. package/dist/utils/pluginInstaller.js +68 -29
  360. package/dist/utils/pluginInstaller.js.map +2 -2
  361. package/dist/utils/pluginLoader.js +249 -57
  362. package/dist/utils/pluginLoader.js.map +2 -2
  363. package/dist/utils/repoFetcher.js +110 -0
  364. package/dist/utils/repoFetcher.js.map +7 -0
  365. package/dist/utils/safeFetch.js +45 -0
  366. package/dist/utils/safeFetch.js.map +7 -0
  367. package/dist/utils/skillLoader.js +77 -12
  368. package/dist/utils/skillLoader.js.map +2 -2
  369. package/dist/utils/streamingState.js +52 -0
  370. package/dist/utils/streamingState.js.map +7 -0
  371. package/dist/utils/stringSubstitution.js +4 -5
  372. package/dist/utils/stringSubstitution.js.map +2 -2
  373. package/dist/utils/style.js +6 -3
  374. package/dist/utils/style.js.map +2 -2
  375. package/dist/utils/teamConfig.js +162 -16
  376. package/dist/utils/teamConfig.js.map +2 -2
  377. package/dist/utils/terminal.js +1 -1
  378. package/dist/utils/terminal.js.map +2 -2
  379. package/dist/utils/toolRiskClassification.js +0 -6
  380. package/dist/utils/toolRiskClassification.js.map +2 -2
  381. package/dist/version.js +2 -2
  382. package/dist/version.js.map +1 -1
  383. package/package.json +7 -6
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/hookManager.ts"],
4
- "sourcesContent": ["/**\n * Hook Manager\n *\n * Central manager for plugin hooks lifecycle.\n * Coordinates hook execution across the application.\n */\n\nimport { HookEvent } from '../types/hooks'\nimport { LoadedPlugin } from '../types/plugin'\nimport {\n executeHooksForEvent,\n processHookDecisions,\n createPreToolUseInput,\n createPostToolUseInput,\n createUserPromptSubmitInput,\n createSessionStartInput,\n createSessionEndInput,\n type HookExecutionOptions,\n type HookExecutionResult,\n} from '../services/hookExecutor'\nimport { logError } from './log'\n\n// Simple logging helpers\nconst logInfo = (msg: string) => {\n // Only log in debug mode to reduce noise\n if (process.env.DEBUG) console.log(`[INFO] ${msg}`)\n}\nconst logDebug = (msg: string, ...args: any[]) => {\n if (process.env.DEBUG) console.log(`[DEBUG] ${msg}`, ...args)\n}\n\n/**\n * Hook manager instance\n */\nexport class HookManager {\n private plugins: LoadedPlugin[] = []\n private sessionId: string\n private transcriptPath: string\n private enabled: boolean = true\n\n constructor(sessionId: string, transcriptPath: string) {\n this.sessionId = sessionId\n this.transcriptPath = transcriptPath\n }\n\n /**\n * Register plugins with hooks\n */\n registerPlugins(plugins: LoadedPlugin[]) {\n this.plugins = plugins\n const totalHooks = plugins.reduce((sum, p) => sum + p.hooks.length, 0)\n logInfo(\n `HookManager: Registered ${plugins.length} plugin(s) with ${totalHooks} hook(s)`,\n )\n }\n\n /**\n * Enable or disable hook execution\n */\n setEnabled(enabled: boolean) {\n this.enabled = enabled\n logDebug(`HookManager: ${enabled ? 'Enabled' : 'Disabled'}`)\n }\n\n /**\n * Execute PreToolUse hooks\n */\n async executePreToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n ): Promise<{\n shouldContinue: boolean\n shouldAskUser: boolean\n reason?: string\n }> {\n if (!this.enabled) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n // Collect all hooks across all plugins\n const allHooks = this.plugins.flatMap(p => p.hooks)\n\n // Filter hooks that match this tool\n const matchingHooks = allHooks.filter(hook => {\n if (hook.event !== HookEvent.PreToolUse) return false\n if (!hook.matcher) return true // No matcher means match all\n if (hook.matcher === '*' || hook.matcher === '') return true\n\n // Check if tool name matches the pattern\n try {\n const regex = new RegExp(hook.matcher)\n return regex.test(toolName)\n } catch {\n // If regex is invalid, try exact match\n return hook.matcher === toolName\n }\n })\n\n if (matchingHooks.length === 0) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n logDebug(\n `PreToolUse: ${matchingHooks.length} hook(s) matched for tool: ${toolName}`,\n )\n\n // Execute hooks\n const input = createPreToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n )\n\n const results: HookExecutionResult[] = []\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n const result = await executeHooksForEvent(\n HookEvent.PreToolUse,\n [hook],\n input,\n options,\n )\n\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n /**\n * Execute PostToolUse hooks\n */\n async executePostToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n toolOutput: Record<string, unknown>,\n ): Promise<void> {\n if (!this.enabled) {\n return\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n\n const matchingHooks = allHooks.filter(hook => {\n if (hook.event !== HookEvent.PostToolUse) return false\n if (!hook.matcher) return true\n if (hook.matcher === '*' || hook.matcher === '') return true\n\n try {\n const regex = new RegExp(hook.matcher)\n return regex.test(toolName)\n } catch {\n return hook.matcher === toolName\n }\n })\n\n if (matchingHooks.length === 0) {\n return\n }\n\n logDebug(\n `PostToolUse: ${matchingHooks.length} hook(s) matched for tool: ${toolName}`,\n )\n\n const input = createPostToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n toolOutput,\n )\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n // PostToolUse hooks don't affect workflow, just execute them\n await executeHooksForEvent(HookEvent.PostToolUse, [hook], input, options)\n }\n }\n\n /**\n * Execute UserPromptSubmit hooks\n */\n async executeUserPromptSubmit(userPrompt: string): Promise<{\n shouldContinue: boolean\n shouldAskUser: boolean\n reason?: string\n }> {\n if (!this.enabled) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n const matchingHooks = allHooks.filter(\n hook => hook.event === HookEvent.UserPromptSubmit,\n )\n\n if (matchingHooks.length === 0) {\n return { shouldContinue: true, shouldAskUser: false }\n }\n\n logDebug(`UserPromptSubmit: ${matchingHooks.length} hook(s)`)\n\n const input = createUserPromptSubmitInput(\n this.sessionId,\n this.transcriptPath,\n userPrompt,\n )\n\n const results: HookExecutionResult[] = []\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n const result = await executeHooksForEvent(\n HookEvent.UserPromptSubmit,\n [hook],\n input,\n options,\n )\n\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n /**\n * Execute SessionStart hooks\n */\n async executeSessionStart(): Promise<void> {\n if (!this.enabled) {\n return\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n const matchingHooks = allHooks.filter(\n hook => hook.event === HookEvent.SessionStart,\n )\n\n if (matchingHooks.length === 0) {\n return\n }\n\n logInfo(`SessionStart: Executing ${matchingHooks.length} hook(s)`)\n\n const input = createSessionStartInput(this.sessionId, this.transcriptPath)\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n await executeHooksForEvent(HookEvent.SessionStart, [hook], input, options)\n }\n }\n\n /**\n * Execute SessionEnd hooks\n */\n async executeSessionEnd(\n reason: 'clear' | 'logout' | 'prompt_input_exit' | 'other' = 'other',\n ): Promise<void> {\n if (!this.enabled) {\n return\n }\n\n const allHooks = this.plugins.flatMap(p => p.hooks)\n const matchingHooks = allHooks.filter(\n hook => hook.event === HookEvent.SessionEnd,\n )\n\n if (matchingHooks.length === 0) {\n return\n }\n\n logInfo(`SessionEnd: Executing ${matchingHooks.length} hook(s)`)\n\n const input = createSessionEndInput(\n this.sessionId,\n this.transcriptPath,\n reason,\n )\n\n for (const hook of matchingHooks) {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n if (!plugin) continue\n\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: plugin.location,\n }\n\n await executeHooksForEvent(HookEvent.SessionEnd, [hook], input, options)\n }\n }\n}\n\n/**\n * Global hook manager instance\n */\nlet globalHookManager: HookManager | null = null\n\n/**\n * Initialize global hook manager\n */\nexport function initializeHookManager(\n sessionId: string,\n transcriptPath: string,\n plugins: LoadedPlugin[],\n): HookManager {\n globalHookManager = new HookManager(sessionId, transcriptPath)\n globalHookManager.registerPlugins(plugins)\n return globalHookManager\n}\n\n/**\n * Get global hook manager\n */\nexport function getHookManager(): HookManager | null {\n return globalHookManager\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Hook Manager\n *\n * Central manager for hook lifecycle.\n * Coordinates hook execution across plugins and settings.json configurations.\n * Supports all CC hook events with proper toolInput matching.\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { HookEvent, HookMatcher, HooksConfigSchema } from '../types/hooks'\nimport { LoadedPlugin, LoadedHook } from '../types/plugin'\nimport { emitReminderEvent } from '@services/systemReminder'\nimport {\n executeHooksForEvent,\n processHookDecisions,\n createPreToolUseInput,\n createPostToolUseInput,\n createPostToolUseFailureInput,\n createPermissionRequestInput,\n createUserPromptSubmitInput,\n createSessionStartInput,\n createSessionEndInput,\n createStopInput,\n createSubagentStartInput,\n createSubagentStopInput,\n createNotificationInput,\n createPreCompactInput,\n createPostCompactInput,\n createConfigChangeInput,\n createTaskCompletedInput,\n createTeammateIdleInput,\n resetOnceHooks,\n type HookExecutionOptions,\n type HookExecutionResult,\n} from '../services/hookExecutor'\nimport { logError } from './log'\nimport { safeParseJSON } from './json'\nimport { getCwd } from './state'\n\nconst logInfo = (msg: string) => {\n if (process.env.DEBUG) console.log(`[INFO] ${msg}`)\n}\nconst logDebug = (msg: string, ...args: any[]) => {\n if (process.env.DEBUG) console.log(`[DEBUG] ${msg}`, ...args)\n}\n\n/**\n * Check if a hook matcher matches a tool name and optionally tool input\n */\nfunction matchHook(\n hook: LoadedHook,\n toolName: string,\n toolInput?: Record<string, unknown>,\n): boolean {\n // Check tool name matcher\n if (hook.matcher) {\n if (hook.matcher !== '*' && hook.matcher !== '') {\n try {\n const regex = new RegExp(hook.matcher)\n if (!regex.test(toolName)) return false\n } catch {\n if (hook.matcher !== toolName) return false\n }\n }\n }\n\n // Check toolInput matcher (CC spec: matcher.toolInput field matching)\n const hookConfig = hook.config as any\n if (hookConfig.toolInput && toolInput) {\n for (const [field, pattern] of Object.entries(\n hookConfig.toolInput as Record<string, string>,\n )) {\n const fieldValue = String(toolInput[field] ?? '')\n try {\n const regex = new RegExp(pattern)\n if (!regex.test(fieldValue)) return false\n } catch {\n if (fieldValue !== pattern) return false\n }\n }\n }\n\n return true\n}\n\n/**\n * Standard decision return type for blocking hooks\n */\ninterface HookDecisionResult {\n shouldContinue: boolean\n shouldAskUser: boolean\n reason?: string\n updatedInput?: Record<string, unknown>\n additionalContext?: string\n}\n\nconst ALLOW_RESULT: HookDecisionResult = {\n shouldContinue: true,\n shouldAskUser: false,\n}\n\n/**\n * Hook manager instance\n */\nexport class HookManager {\n private plugins: LoadedPlugin[] = []\n private settingsHooks: LoadedHook[] = []\n private managedHooks: LoadedHook[] = []\n private sessionId: string\n private transcriptPath: string\n private enabled: boolean = true\n private disableAllHooks: boolean = false\n\n constructor(sessionId: string, transcriptPath: string) {\n this.sessionId = sessionId\n this.transcriptPath = transcriptPath\n resetOnceHooks()\n }\n\n /**\n * Register plugins with hooks\n */\n registerPlugins(plugins: LoadedPlugin[]) {\n this.plugins = plugins\n const totalHooks = plugins.reduce((sum, p) => sum + p.hooks.length, 0)\n logInfo(\n `HookManager: Registered ${plugins.length} plugin(s) with ${totalHooks} hook(s)`,\n )\n }\n\n /**\n * Load hooks from settings.json files\n * Priority (high to low): managed > .minto/settings.json > .claude/settings.json >\n * .minto/settings.local.json > ~/.minto/settings.json > ~/.claude/settings.json\n */\n loadSettingsHooks() {\n const cwd = getCwd()\n const home = homedir()\n\n // Load paths in priority order (lowest first, higher overrides)\n const settingsPaths = [\n join(home, '.claude', 'settings.json'),\n join(home, '.minto', 'settings.json'),\n join(cwd, '.minto', 'settings.local.json'),\n join(cwd, '.claude', 'settings.json'),\n join(cwd, '.minto', 'settings.json'),\n ]\n\n const allHooks: LoadedHook[] = []\n\n for (const settingsPath of settingsPaths) {\n try {\n if (!existsSync(settingsPath)) continue\n const content = readFileSync(settingsPath, 'utf-8')\n const settings = safeParseJSON(content)\n if (!settings || typeof settings !== 'object') continue\n\n const hooksConfig = (settings as any).hooks\n if (!hooksConfig || typeof hooksConfig !== 'object') continue\n\n const parsed = HooksConfigSchema.safeParse({ hooks: hooksConfig })\n if (!parsed.success) {\n logDebug(`Invalid hooks in ${settingsPath}: ${parsed.error.message}`)\n continue\n }\n\n const hooks = parsed.data.hooks\n if (!hooks) continue\n\n for (const [eventName, matchers] of Object.entries(hooks)) {\n const event = eventName as HookEvent\n for (const matcher of matchers as HookMatcher[]) {\n for (let i = 0; i < matcher.hooks.length; i++) {\n const hookDef = matcher.hooks[i]!\n allHooks.push({\n name: `settings:${eventName}:${i}`,\n filePath: settingsPath,\n config: {\n event,\n matcher: matcher.matcher,\n type: hookDef.type as any,\n command: hookDef.command,\n timeout: hookDef.timeout,\n once: hookDef.once,\n async: hookDef.async,\n } as any,\n pluginName: 'settings',\n event,\n matcher: matcher.matcher,\n })\n }\n }\n }\n } catch (err) {\n logDebug(`Error loading hooks from ${settingsPath}: ${err}`)\n }\n }\n\n this.settingsHooks = allHooks\n\n // Check for disableAllHooks\n try {\n const localSettings = join(cwd, '.minto', 'settings.json')\n const globalSettings = join(home, '.minto', 'settings.json')\n for (const p of [localSettings, globalSettings]) {\n if (existsSync(p)) {\n const content = safeParseJSON(readFileSync(p, 'utf-8'))\n if (content && (content as any).disableAllHooks) {\n this.disableAllHooks = true\n break\n }\n }\n }\n } catch {\n // ignore\n }\n\n logInfo(`HookManager: Loaded ${allHooks.length} hook(s) from settings`)\n }\n\n /**\n * Dynamically add temporary hooks (e.g., skill-level hooks)\n * Returns a cleanup function to remove them\n */\n addHooks(hooks: LoadedHook[]): () => void {\n this.settingsHooks.push(...hooks)\n logDebug(`HookManager: Added ${hooks.length} temporary hook(s)`)\n return () => {\n this.settingsHooks = this.settingsHooks.filter(h => !hooks.includes(h))\n logDebug(`HookManager: Removed ${hooks.length} temporary hook(s)`)\n }\n }\n\n /**\n * Enable or disable hook execution\n */\n setEnabled(enabled: boolean) {\n this.enabled = enabled\n logDebug(`HookManager: ${enabled ? 'Enabled' : 'Disabled'}`)\n }\n\n /**\n * Get all hooks (plugins + settings), respecting disableAllHooks\n */\n private getAllHooks(): LoadedHook[] {\n // Managed hooks always execute even if disableAllHooks is true\n const managed = this.managedHooks\n\n if (this.disableAllHooks) {\n return managed\n }\n\n const pluginHooks = this.plugins.flatMap(p => p.hooks)\n return [...pluginHooks, ...this.settingsHooks, ...managed]\n }\n\n /**\n * Get matching hooks for a tool-based event\n */\n private getMatchingToolHooks(\n event: HookEvent,\n toolName: string,\n toolInput?: Record<string, unknown>,\n ): { hooks: LoadedHook[]; plugins: LoadedPlugin[] } {\n const allHooks = this.getAllHooks()\n const matching = allHooks.filter(hook => {\n if (hook.event !== event) return false\n return matchHook(hook, toolName, toolInput)\n })\n return { hooks: matching, plugins: this.plugins }\n }\n\n /**\n * Get matching hooks for a non-tool event\n */\n private getMatchingEventHooks(event: HookEvent): LoadedHook[] {\n return this.getAllHooks().filter(hook => hook.event === event)\n }\n\n /**\n * Find plugin root for a hook\n */\n private getPluginRoot(hook: LoadedHook): string {\n const plugin = this.plugins.find(p => p.manifest.name === hook.pluginName)\n return plugin?.location || getCwd()\n }\n\n /**\n * Execute hooks for a tool-based event (PreToolUse, PostToolUse, etc.)\n */\n private async executeToolEvent(\n event: HookEvent,\n toolName: string,\n input: any,\n toolInput?: Record<string, unknown>,\n ): Promise<HookDecisionResult> {\n if (!this.enabled) return ALLOW_RESULT\n\n const { hooks } = this.getMatchingToolHooks(event, toolName, toolInput)\n if (hooks.length === 0) return ALLOW_RESULT\n\n logDebug(`${event}: ${hooks.length} hook(s) matched for tool: ${toolName}`)\n\n const results: HookExecutionResult[] = []\n for (const hook of hooks) {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n const result = await executeHooksForEvent(event, [hook], input, options)\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n /**\n * Execute hooks for a non-tool event (fire-and-forget)\n */\n private async executeFireAndForget(\n event: HookEvent,\n input: any,\n ): Promise<void> {\n if (!this.enabled) return\n\n const hooks = this.getMatchingEventHooks(event)\n if (hooks.length === 0) return\n\n logDebug(`${event}: ${hooks.length} hook(s)`)\n\n // Fire-and-forget: don't await individual results\n await Promise.allSettled(\n hooks.map(hook => {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n return executeHooksForEvent(event, [hook], input, options)\n }),\n )\n }\n\n /**\n * Execute hooks for a blockable non-tool event\n */\n private async executeBlockableEvent(\n event: HookEvent,\n input: any,\n ): Promise<HookDecisionResult> {\n if (!this.enabled) return ALLOW_RESULT\n\n const hooks = this.getMatchingEventHooks(event)\n if (hooks.length === 0) return ALLOW_RESULT\n\n logDebug(`${event}: ${hooks.length} hook(s)`)\n\n const results: HookExecutionResult[] = []\n for (const hook of hooks) {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n const result = await executeHooksForEvent(event, [hook], input, options)\n results.push(...result)\n }\n\n return processHookDecisions(results)\n }\n\n // ========================================================================\n // Public event methods\n // ========================================================================\n\n async executePreToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n ): Promise<HookDecisionResult> {\n const input = createPreToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n )\n return this.executeToolEvent(\n HookEvent.PreToolUse,\n toolName,\n input,\n toolInput,\n )\n }\n\n async executePostToolUse(\n toolName: string,\n toolInput: Record<string, unknown>,\n toolOutput: Record<string, unknown>,\n ): Promise<void> {\n const input = createPostToolUseInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n toolOutput,\n )\n await this.executeFireAndForget(HookEvent.PostToolUse, input)\n }\n\n async executePostToolUseFailure(\n toolName: string,\n toolInput: Record<string, unknown>,\n error: string,\n errorType?: string,\n ): Promise<void> {\n const input = createPostToolUseFailureInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n error,\n errorType,\n )\n await this.executeFireAndForget(HookEvent.PostToolUseFailure, input)\n\n // Emit diagnostics:new for tool failures (linter/compiler errors)\n emitReminderEvent('diagnostics:new', {\n source: toolName,\n count: 1,\n })\n }\n\n async executePermissionRequest(\n toolName: string,\n toolInput: Record<string, unknown>,\n permissionType: 'read' | 'write' | 'execute' | 'network' | 'other',\n description?: string,\n ): Promise<HookDecisionResult> {\n const input = createPermissionRequestInput(\n this.sessionId,\n this.transcriptPath,\n toolName,\n toolInput,\n permissionType,\n description,\n )\n return this.executeBlockableEvent(HookEvent.PermissionRequest, input)\n }\n\n async executeUserPromptSubmit(\n userPrompt: string,\n ): Promise<HookDecisionResult> {\n const input = createUserPromptSubmitInput(\n this.sessionId,\n this.transcriptPath,\n userPrompt,\n )\n return this.executeBlockableEvent(HookEvent.UserPromptSubmit, input)\n }\n\n async executeSessionStart(): Promise<void> {\n const input = createSessionStartInput(this.sessionId, this.transcriptPath)\n await this.executeFireAndForget(HookEvent.SessionStart, input)\n }\n\n async executeSessionEnd(\n reason: 'clear' | 'logout' | 'prompt_input_exit' | 'other' = 'other',\n ): Promise<void> {\n const input = createSessionEndInput(\n this.sessionId,\n this.transcriptPath,\n reason,\n )\n await this.executeFireAndForget(HookEvent.SessionEnd, input)\n }\n\n async executeStop(\n lastAssistantMessage?: string,\n ): Promise<HookDecisionResult> {\n const input = createStopInput(this.sessionId, this.transcriptPath, true)\n if (lastAssistantMessage) {\n ;(input as any).last_assistant_message = lastAssistantMessage\n }\n return this.executeBlockableEvent(HookEvent.Stop, input)\n }\n\n async executeSubagentStart(\n agentType: string,\n agentDescription?: string,\n runInBackground?: boolean,\n ): Promise<void> {\n const input = createSubagentStartInput(\n this.sessionId,\n this.transcriptPath,\n agentType,\n agentDescription,\n runInBackground,\n )\n await this.executeFireAndForget(HookEvent.SubagentStart, input)\n }\n\n async executeSubagentStop(\n agentType: string,\n agentId?: string,\n transcriptPath?: string,\n lastMessage?: string,\n ): Promise<HookDecisionResult> {\n const input = createSubagentStopInput(\n this.sessionId,\n this.transcriptPath,\n agentType,\n agentId,\n )\n if (transcriptPath) {\n ;(input as any).agent_transcript_path = transcriptPath\n }\n if (lastMessage) {\n ;(input as any).last_message = lastMessage\n }\n return this.executeBlockableEvent(HookEvent.SubagentStop, input)\n }\n\n async executeNotification(\n message: string,\n title?: string,\n type?: string,\n ): Promise<{ suppressNotification?: boolean }> {\n if (!this.enabled) return {}\n\n const input = createNotificationInput(\n this.sessionId,\n this.transcriptPath,\n message,\n title,\n type,\n )\n\n const hooks = this.getMatchingEventHooks(HookEvent.Notification)\n if (hooks.length === 0) return {}\n\n const results: HookExecutionResult[] = []\n for (const hook of hooks) {\n const options: HookExecutionOptions = {\n sessionId: this.sessionId,\n transcriptPath: this.transcriptPath,\n pluginRoot: this.getPluginRoot(hook),\n }\n const result = await executeHooksForEvent(\n HookEvent.Notification,\n [hook],\n input,\n options,\n )\n results.push(...result)\n }\n\n // Check if any hook suppressed the notification\n const suppress = results.some(\n r => r.success && (r.output as any)?.suppressNotification,\n )\n return { suppressNotification: suppress }\n }\n\n async executePreCompact(\n trigger: 'manual' | 'auto',\n customInstructions?: string,\n ): Promise<void> {\n const input = createPreCompactInput(\n this.sessionId,\n this.transcriptPath,\n trigger,\n customInstructions || '',\n )\n await this.executeFireAndForget(HookEvent.PreCompact, input)\n }\n\n async executePostCompact(\n trigger: 'manual' | 'auto',\n summary: string,\n compressionRatio: number,\n originalTokens: number,\n compressedTokens: number,\n ): Promise<void> {\n const input = createPostCompactInput(\n this.sessionId,\n this.transcriptPath,\n trigger,\n summary,\n compressionRatio,\n originalTokens,\n compressedTokens,\n )\n await this.executeFireAndForget(HookEvent.PostCompact, input)\n }\n\n async executeConfigChange(\n source: 'settings' | 'project' | 'global' | 'env' | 'cli',\n filePath?: string,\n ): Promise<HookDecisionResult> {\n const input = createConfigChangeInput(\n this.sessionId,\n this.transcriptPath,\n source,\n filePath,\n )\n return this.executeBlockableEvent(HookEvent.ConfigChange, input)\n }\n\n async executeTaskCompleted(\n taskId: string,\n subject: string,\n description?: string,\n ): Promise<HookDecisionResult> {\n const input = createTaskCompletedInput(\n this.sessionId,\n this.transcriptPath,\n taskId,\n subject,\n description,\n )\n return this.executeBlockableEvent(HookEvent.TaskCompleted, input)\n }\n\n async executeTeammateIdle(\n teammateName: string,\n teamName: string,\n ): Promise<HookDecisionResult> {\n const input = createTeammateIdleInput(\n this.sessionId,\n this.transcriptPath,\n teammateName,\n teamName,\n )\n return this.executeBlockableEvent(HookEvent.TeammateIdle, input)\n }\n}\n\n// ============================================================================\n// Global Hook Manager\n// ============================================================================\n\nlet globalHookManager: HookManager | null = null\n\nexport function initializeHookManager(\n sessionId: string,\n transcriptPath: string,\n plugins: LoadedPlugin[],\n): HookManager {\n globalHookManager = new HookManager(sessionId, transcriptPath)\n globalHookManager.registerPlugins(plugins)\n globalHookManager.loadSettingsHooks()\n return globalHookManager\n}\n\nexport function getHookManager(): HookManager | null {\n return globalHookManager\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -79,9 +79,56 @@ function format(token, listDepth = 0, orderedListNumber = null, parent = null) {
79
79
  } else {
80
80
  return token.text;
81
81
  }
82
+ case "table": {
83
+ const headerTexts = token.header.map(
84
+ (cell) => (cell.tokens ?? []).map((_) => format(_)).join("")
85
+ );
86
+ const rowTexts = token.rows.map(
87
+ (row) => row.map(
88
+ (cell) => (cell.tokens ?? []).map((_) => format(_)).join("")
89
+ )
90
+ );
91
+ const colCount = headerTexts.length;
92
+ const colWidths = [];
93
+ for (let c = 0; c < colCount; c++) {
94
+ let maxWidth = stripAnsi(headerTexts[c] ?? "").length;
95
+ for (const row of rowTexts) {
96
+ maxWidth = Math.max(maxWidth, stripAnsi(row[c] ?? "").length);
97
+ }
98
+ colWidths.push(Math.max(maxWidth, 3));
99
+ }
100
+ const headerRow = headerTexts.map(
101
+ (text, i) => chalk.bold(padCell(text, colWidths[i], token.align[i]))
102
+ ).join(" | ");
103
+ const separator = colWidths.map((w, i) => {
104
+ const align = token.align[i];
105
+ if (align === "center") return ":" + "-".repeat(w - 2) + ":";
106
+ if (align === "right") return "-".repeat(w - 1) + ":";
107
+ if (align === "left") return ":" + "-".repeat(w - 1);
108
+ return "-".repeat(w);
109
+ }).join(" | ");
110
+ const dataRows = rowTexts.map(
111
+ (row) => row.map((text, i) => padCell(text, colWidths[i], token.align[i])).join(" | ")
112
+ );
113
+ return [headerRow, separator, ...dataRows].join(EOL) + EOL;
114
+ }
82
115
  }
83
116
  return "";
84
117
  }
118
+ function stripAnsi(str) {
119
+ return str.replace(/\x1B\[[0-9;]*m/g, "");
120
+ }
121
+ function padCell(text, width, align) {
122
+ const visibleLength = stripAnsi(text).length;
123
+ const padding = Math.max(0, width - visibleLength);
124
+ if (align === "right") return " ".repeat(padding) + text;
125
+ if (align === "center") {
126
+ const left = Math.floor(padding / 2);
127
+ const right = padding - left;
128
+ return " ".repeat(left) + text + " ".repeat(right);
129
+ }
130
+ return text + " ".repeat(padding);
131
+ }
85
132
  const DEPTH_1_LIST_NUMBERS = [
86
133
  "a",
87
134
  "b",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/markdown.ts"],
4
- "sourcesContent": ["import { marked, Token } from 'marked'\nimport { stripSystemMessages } from './messages'\nimport chalk from 'chalk'\nimport { EOL } from 'os'\nimport { highlight, supportsLanguage } from 'cli-highlight'\nimport { logError } from './log'\n\n/**\n * Strip outer markdown code block wrapper if present.\n * AI models sometimes wrap their response in ```markdown ... ``` which\n * causes the content to be parsed as a code block instead of actual markdown.\n */\nfunction stripMarkdownCodeBlockWrapper(content: string): string {\n const trimmed = content.trim()\n // Match ```markdown or ```md at the start and ``` at the end\n const codeBlockRegex = /^```(?:markdown|md)?\\s*\\n([\\s\\S]*?)\\n```$/\n const match = trimmed.match(codeBlockRegex)\n if (match) {\n return match[1] ?? trimmed\n }\n return content\n}\n\nexport function applyMarkdown(content: string): string {\n // Pre-process: remove outer markdown code block wrapper if present\n const preprocessed = stripMarkdownCodeBlockWrapper(\n stripSystemMessages(content),\n )\n return marked\n .lexer(preprocessed)\n .map(_ => format(_))\n .join('')\n .trim()\n}\n\nfunction format(\n token: Token,\n listDepth = 0,\n orderedListNumber: number | null = null,\n parent: Token | null = null,\n): string {\n switch (token.type) {\n case 'blockquote':\n return chalk.dim.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'code':\n if (token.lang && supportsLanguage(token.lang)) {\n return highlight(token.text, { language: token.lang }) + EOL\n } else {\n logError(\n `Language not supported while highlighting code, falling back to markdown: ${token.lang}`,\n )\n return highlight(token.text, { language: 'markdown' }) + EOL\n }\n case 'codespan':\n // inline code\n return chalk.blue(token.text)\n case 'em':\n return chalk.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'strong':\n return chalk.bold((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'heading':\n switch (token.depth) {\n case 1: // h1\n return (\n chalk.bold.italic.underline(\n (token.tokens ?? []).map(_ => format(_)).join(''),\n ) +\n EOL +\n EOL\n )\n case 2: // h2\n return (\n chalk.bold((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n default: // h3+\n return (\n chalk.bold.dim((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n }\n case 'hr':\n return '---'\n case 'image':\n return `[Image: ${token.title}: ${token.href}]`\n case 'link':\n return chalk.blue(token.href)\n case 'list': {\n return token.items\n .map((_: Token, index: number) =>\n format(\n _,\n listDepth,\n token.ordered ? token.start + index : null,\n token,\n ),\n )\n .join('')\n }\n case 'list_item':\n return (token.tokens ?? [])\n .map(\n _ =>\n `${' '.repeat(listDepth)}${format(_, listDepth + 1, orderedListNumber, token)}`,\n )\n .join('')\n case 'paragraph':\n return (token.tokens ?? []).map(_ => format(_)).join('') + EOL\n case 'space':\n return EOL\n case 'text':\n if (parent?.type === 'list_item') {\n return `${orderedListNumber === null ? '-' : getListNumber(listDepth, orderedListNumber) + '.'} ${token.tokens ? token.tokens.map(_ => format(_, listDepth, orderedListNumber, token)).join('') : token.text}${EOL}`\n } else {\n return token.text\n }\n }\n // TODO: tables\n return ''\n}\n\nconst DEPTH_1_LIST_NUMBERS = [\n 'a',\n 'b',\n 'c',\n 'd',\n 'e',\n 'f',\n 'g',\n 'h',\n 'i',\n 'j',\n 'k',\n 'l',\n 'm',\n 'n',\n 'o',\n 'p',\n 'q',\n 'r',\n 's',\n 't',\n 'u',\n 'v',\n 'w',\n 'x',\n 'y',\n 'z',\n 'aa',\n 'ab',\n 'ac',\n 'ad',\n 'ae',\n 'af',\n 'ag',\n 'ah',\n 'ai',\n 'aj',\n 'ak',\n 'al',\n 'am',\n 'an',\n 'ao',\n 'ap',\n 'aq',\n 'ar',\n 'as',\n 'at',\n 'au',\n 'av',\n 'aw',\n 'ax',\n 'ay',\n 'az',\n]\nconst DEPTH_2_LIST_NUMBERS = [\n 'i',\n 'ii',\n 'iii',\n 'iv',\n 'v',\n 'vi',\n 'vii',\n 'viii',\n 'ix',\n 'x',\n 'xi',\n 'xii',\n 'xiii',\n 'xiv',\n 'xv',\n 'xvi',\n 'xvii',\n 'xviii',\n 'xix',\n 'xx',\n 'xxi',\n 'xxii',\n 'xxiii',\n 'xxiv',\n 'xxv',\n 'xxvi',\n 'xxvii',\n 'xxviii',\n 'xxix',\n 'xxx',\n 'xxxi',\n 'xxxii',\n 'xxxiii',\n 'xxxiv',\n 'xxxv',\n 'xxxvi',\n 'xxxvii',\n 'xxxviii',\n 'xxxix',\n 'xl',\n]\n\nfunction getListNumber(listDepth: number, orderedListNumber: number): string {\n switch (listDepth) {\n case 0:\n case 1:\n return orderedListNumber.toString()\n case 2:\n return DEPTH_1_LIST_NUMBERS[orderedListNumber - 1]! // TODO: don't hard code the list\n case 3:\n return DEPTH_2_LIST_NUMBERS[orderedListNumber - 1]! // TODO: don't hard code the list\n default:\n return orderedListNumber.toString()\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { marked, Token } from 'marked'\nimport { stripSystemMessages } from './messages'\nimport chalk from 'chalk'\nimport { EOL } from 'os'\nimport { highlight, supportsLanguage } from 'cli-highlight'\nimport { logError } from './log'\n\n/**\n * Strip outer markdown code block wrapper if present.\n * AI models sometimes wrap their response in ```markdown ... ``` which\n * causes the content to be parsed as a code block instead of actual markdown.\n */\nfunction stripMarkdownCodeBlockWrapper(content: string): string {\n const trimmed = content.trim()\n // Match ```markdown or ```md at the start and ``` at the end\n const codeBlockRegex = /^```(?:markdown|md)?\\s*\\n([\\s\\S]*?)\\n```$/\n const match = trimmed.match(codeBlockRegex)\n if (match) {\n return match[1] ?? trimmed\n }\n return content\n}\n\nexport function applyMarkdown(content: string): string {\n // Pre-process: remove outer markdown code block wrapper if present\n const preprocessed = stripMarkdownCodeBlockWrapper(\n stripSystemMessages(content),\n )\n return marked\n .lexer(preprocessed)\n .map(_ => format(_))\n .join('')\n .trim()\n}\n\nfunction format(\n token: Token,\n listDepth = 0,\n orderedListNumber: number | null = null,\n parent: Token | null = null,\n): string {\n switch (token.type) {\n case 'blockquote':\n return chalk.dim.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'code':\n if (token.lang && supportsLanguage(token.lang)) {\n return highlight(token.text, { language: token.lang }) + EOL\n } else {\n logError(\n `Language not supported while highlighting code, falling back to markdown: ${token.lang}`,\n )\n return highlight(token.text, { language: 'markdown' }) + EOL\n }\n case 'codespan':\n // inline code\n return chalk.blue(token.text)\n case 'em':\n return chalk.italic((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'strong':\n return chalk.bold((token.tokens ?? []).map(_ => format(_)).join(''))\n case 'heading':\n switch (token.depth) {\n case 1: // h1\n return (\n chalk.bold.italic.underline(\n (token.tokens ?? []).map(_ => format(_)).join(''),\n ) +\n EOL +\n EOL\n )\n case 2: // h2\n return (\n chalk.bold((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n default: // h3+\n return (\n chalk.bold.dim((token.tokens ?? []).map(_ => format(_)).join('')) +\n EOL +\n EOL\n )\n }\n case 'hr':\n return '---'\n case 'image':\n return `[Image: ${token.title}: ${token.href}]`\n case 'link':\n return chalk.blue(token.href)\n case 'list': {\n return token.items\n .map((_: Token, index: number) =>\n format(\n _,\n listDepth,\n token.ordered ? token.start + index : null,\n token,\n ),\n )\n .join('')\n }\n case 'list_item':\n return (token.tokens ?? [])\n .map(\n _ =>\n `${' '.repeat(listDepth)}${format(_, listDepth + 1, orderedListNumber, token)}`,\n )\n .join('')\n case 'paragraph':\n return (token.tokens ?? []).map(_ => format(_)).join('') + EOL\n case 'space':\n return EOL\n case 'text':\n if (parent?.type === 'list_item') {\n return `${orderedListNumber === null ? '-' : getListNumber(listDepth, orderedListNumber) + '.'} ${token.tokens ? token.tokens.map(_ => format(_, listDepth, orderedListNumber, token)).join('') : token.text}${EOL}`\n } else {\n return token.text\n }\n case 'table': {\n // Render each cell's inline tokens to get display text\n const headerTexts = (token.header as any[]).map((cell: any) =>\n (cell.tokens ?? []).map((_: Token) => format(_)).join(''),\n )\n const rowTexts = (token.rows as any[][]).map((row: any[]) =>\n row.map((cell: any) =>\n (cell.tokens ?? []).map((_: Token) => format(_)).join(''),\n ),\n )\n\n // Calculate column widths (max of header and all rows)\n const colCount = headerTexts.length\n const colWidths: number[] = []\n for (let c = 0; c < colCount; c++) {\n let maxWidth = stripAnsi(headerTexts[c] ?? '').length\n for (const row of rowTexts) {\n maxWidth = Math.max(maxWidth, stripAnsi(row[c] ?? '').length)\n }\n colWidths.push(Math.max(maxWidth, 3)) // minimum 3 chars\n }\n\n // Build header row\n const headerRow = headerTexts\n .map((text, i) =>\n chalk.bold(padCell(text, colWidths[i]!, token.align[i])),\n )\n .join(' | ')\n\n // Build separator\n const separator = colWidths\n .map((w, i) => {\n const align = token.align[i]\n if (align === 'center') return ':' + '-'.repeat(w - 2) + ':'\n if (align === 'right') return '-'.repeat(w - 1) + ':'\n if (align === 'left') return ':' + '-'.repeat(w - 1)\n return '-'.repeat(w)\n })\n .join(' | ')\n\n // Build data rows\n const dataRows = rowTexts.map(row =>\n row\n .map((text, i) => padCell(text, colWidths[i]!, token.align[i]))\n .join(' | '),\n )\n\n return [headerRow, separator, ...dataRows].join(EOL) + EOL\n }\n }\n return ''\n}\n\n/**\n * Strip ANSI escape codes for accurate width calculation\n */\nfunction stripAnsi(str: string): string {\n // eslint-disable-next-line no-control-regex\n return str.replace(/\\x1B\\[[0-9;]*m/g, '')\n}\n\n/**\n * Pad a cell to a target width, respecting alignment and ANSI codes\n */\nfunction padCell(\n text: string,\n width: number,\n align: 'center' | 'left' | 'right' | null,\n): string {\n const visibleLength = stripAnsi(text).length\n const padding = Math.max(0, width - visibleLength)\n if (align === 'right') return ' '.repeat(padding) + text\n if (align === 'center') {\n const left = Math.floor(padding / 2)\n const right = padding - left\n return ' '.repeat(left) + text + ' '.repeat(right)\n }\n // left or null (default left)\n return text + ' '.repeat(padding)\n}\n\nconst DEPTH_1_LIST_NUMBERS = [\n 'a',\n 'b',\n 'c',\n 'd',\n 'e',\n 'f',\n 'g',\n 'h',\n 'i',\n 'j',\n 'k',\n 'l',\n 'm',\n 'n',\n 'o',\n 'p',\n 'q',\n 'r',\n 's',\n 't',\n 'u',\n 'v',\n 'w',\n 'x',\n 'y',\n 'z',\n 'aa',\n 'ab',\n 'ac',\n 'ad',\n 'ae',\n 'af',\n 'ag',\n 'ah',\n 'ai',\n 'aj',\n 'ak',\n 'al',\n 'am',\n 'an',\n 'ao',\n 'ap',\n 'aq',\n 'ar',\n 'as',\n 'at',\n 'au',\n 'av',\n 'aw',\n 'ax',\n 'ay',\n 'az',\n]\nconst DEPTH_2_LIST_NUMBERS = [\n 'i',\n 'ii',\n 'iii',\n 'iv',\n 'v',\n 'vi',\n 'vii',\n 'viii',\n 'ix',\n 'x',\n 'xi',\n 'xii',\n 'xiii',\n 'xiv',\n 'xv',\n 'xvi',\n 'xvii',\n 'xviii',\n 'xix',\n 'xx',\n 'xxi',\n 'xxii',\n 'xxiii',\n 'xxiv',\n 'xxv',\n 'xxvi',\n 'xxvii',\n 'xxviii',\n 'xxix',\n 'xxx',\n 'xxxi',\n 'xxxii',\n 'xxxiii',\n 'xxxiv',\n 'xxxv',\n 'xxxvi',\n 'xxxvii',\n 'xxxviii',\n 'xxxix',\n 'xl',\n]\n\nfunction getListNumber(listDepth: number, orderedListNumber: number): string {\n switch (listDepth) {\n case 0:\n case 1:\n return orderedListNumber.toString()\n case 2:\n return DEPTH_1_LIST_NUMBERS[orderedListNumber - 1]! // TODO: don't hard code the list\n case 3:\n return DEPTH_2_LIST_NUMBERS[orderedListNumber - 1]! // TODO: don't hard code the list\n default:\n return orderedListNumber.toString()\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -10,7 +10,7 @@ import {
10
10
  } from "fs";
11
11
  import { join, resolve, isAbsolute } from "path";
12
12
  import { homedir } from "os";
13
- import { execFileNoThrow } from "./execFileNoThrow.js";
13
+ import { fetchRepo } from "./repoFetcher.js";
14
14
  import {
15
15
  MarketplaceManifestSchema,
16
16
  MarketplaceError,
@@ -45,38 +45,13 @@ function saveRegistry(marketplaces) {
45
45
  const registryPath = getRegistryPath();
46
46
  writeFileSync(registryPath, JSON.stringify(marketplaces, null, 2), "utf-8");
47
47
  }
48
- async function cloneGitRepo(url, ref) {
49
- const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
50
- mkdirSync(tempDir, { recursive: true });
51
- try {
52
- const args = ["clone", "--depth", "1"];
53
- if (ref) {
54
- args.push("--branch", ref);
55
- }
56
- args.push(url, tempDir);
57
- const result = await execFileNoThrow("git", args);
58
- if (result.code !== 0) {
59
- throw new Error(`Git clone failed: ${result.stderr || result.stdout}`);
60
- }
61
- return tempDir;
62
- } catch (error) {
63
- try {
64
- rmSync(tempDir, { recursive: true, force: true });
65
- } catch (cleanupError) {
66
- }
67
- throw new MarketplaceError(
68
- `Failed to clone repository: ${error instanceof Error ? error.message : String(error)}`,
69
- MarketplaceErrorCode.GIT_ERROR,
70
- void 0,
71
- error
72
- );
73
- }
74
- }
75
48
  function loadManifestFromDirectory(dir) {
76
- const manifestPath = join(dir, ".minto-plugin", "marketplace.json");
77
- if (!existsSync(manifestPath)) {
49
+ const mintoPath = join(dir, ".minto-plugin", "marketplace.json");
50
+ const claudePath = join(dir, ".claude-plugin", "marketplace.json");
51
+ const manifestPath = existsSync(mintoPath) ? mintoPath : existsSync(claudePath) ? claudePath : null;
52
+ if (!manifestPath) {
78
53
  throw new MarketplaceError(
79
- `Marketplace manifest not found at ${manifestPath}`,
54
+ `Marketplace manifest not found (checked .minto-plugin/ and .claude-plugin/ in ${dir})`,
80
55
  MarketplaceErrorCode.MANIFEST_NOT_FOUND
81
56
  );
82
57
  }
@@ -94,10 +69,18 @@ function loadManifestFromDirectory(dir) {
94
69
  }
95
70
  }
96
71
  async function fetchGitHubMarketplace(repo, ref) {
97
- const url = `https://github.com/${repo}.git`;
98
- const tempDir = await cloneGitRepo(url, ref);
72
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
73
+ mkdirSync(tempDir, { recursive: true });
99
74
  try {
75
+ await fetchRepo({ type: "github", repo, ref }, tempDir);
100
76
  return loadManifestFromDirectory(tempDir);
77
+ } catch (error) {
78
+ throw new MarketplaceError(
79
+ `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,
80
+ MarketplaceErrorCode.GIT_ERROR,
81
+ void 0,
82
+ error
83
+ );
101
84
  } finally {
102
85
  try {
103
86
  rmSync(tempDir, { recursive: true, force: true });
@@ -106,9 +89,18 @@ async function fetchGitHubMarketplace(repo, ref) {
106
89
  }
107
90
  }
108
91
  async function fetchUrlMarketplace(url, ref) {
109
- const tempDir = await cloneGitRepo(url, ref);
92
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
93
+ mkdirSync(tempDir, { recursive: true });
110
94
  try {
95
+ await fetchRepo({ type: "url", url, ref }, tempDir);
111
96
  return loadManifestFromDirectory(tempDir);
97
+ } catch (error) {
98
+ throw new MarketplaceError(
99
+ `Failed to fetch repository: ${error instanceof Error ? error.message : String(error)}`,
100
+ MarketplaceErrorCode.GIT_ERROR,
101
+ void 0,
102
+ error
103
+ );
112
104
  } finally {
113
105
  try {
114
106
  rmSync(tempDir, { recursive: true, force: true });
@@ -120,6 +112,24 @@ function loadLocalMarketplace(path) {
120
112
  const resolvedPath = path.startsWith("/") ? path : join(getCwd(), path);
121
113
  return loadManifestFromDirectory(resolvedPath);
122
114
  }
115
+ function isMarketplaceRegistered(name) {
116
+ return loadRegistry().some((m) => m.name === name);
117
+ }
118
+ function registerMarketplaceFromDirectory(name, source, localDir) {
119
+ const registry = loadRegistry();
120
+ if (registry.some((m) => m.name === name)) return null;
121
+ const manifest = loadManifestFromDirectory(localDir);
122
+ const registered = {
123
+ name: manifest.name,
124
+ source,
125
+ manifest,
126
+ lastUpdated: /* @__PURE__ */ new Date(),
127
+ enabled: true
128
+ };
129
+ registry.push(registered);
130
+ saveRegistry(registry);
131
+ return registered;
132
+ }
123
133
  function parseMarketplaceSource(input) {
124
134
  if (/^[\w-]+\/[\w-]+$/.test(input)) {
125
135
  return { type: "github", repo: input };
@@ -243,7 +253,9 @@ function loadMarketplaceSettings() {
243
253
  const home = homedir();
244
254
  const settingsPaths = [
245
255
  { path: join(cwd, ".minto", "settings.json"), label: "project" },
246
- { path: join(home, ".minto", "settings.json"), label: "user" }
256
+ { path: join(cwd, ".claude", "settings.json"), label: "project/.claude" },
257
+ { path: join(home, ".minto", "settings.json"), label: "user" },
258
+ { path: join(home, ".claude", "settings.json"), label: "user/.claude" }
247
259
  ];
248
260
  for (const { path, label } of settingsPaths) {
249
261
  if (existsSync(path)) {
@@ -312,14 +324,28 @@ async function autoRegisterMarketplaces() {
312
324
  async function getMarketplaceRepoPath(marketplace) {
313
325
  switch (marketplace.source.type) {
314
326
  case "github": {
315
- const url = `https://github.com/${marketplace.source.repo}.git`;
316
- const tempDir = await cloneGitRepo(url, marketplace.source.ref);
327
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
328
+ mkdirSync(tempDir, { recursive: true });
329
+ await fetchRepo(
330
+ {
331
+ type: "github",
332
+ repo: marketplace.source.repo,
333
+ ref: marketplace.source.ref
334
+ },
335
+ tempDir
336
+ );
317
337
  return { path: tempDir, cleanup: true };
318
338
  }
319
339
  case "url": {
320
- const tempDir = await cloneGitRepo(
321
- marketplace.source.url,
322
- marketplace.source.ref
340
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
341
+ mkdirSync(tempDir, { recursive: true });
342
+ await fetchRepo(
343
+ {
344
+ type: "url",
345
+ url: marketplace.source.url,
346
+ ref: marketplace.source.ref
347
+ },
348
+ tempDir
323
349
  );
324
350
  return { path: tempDir, cleanup: true };
325
351
  }
@@ -426,16 +452,25 @@ async function installPluginFromMarketplace(pluginName, marketplaceName, targetD
426
452
  }
427
453
  copyDirectory(pluginSourcePath, installDir);
428
454
  } else if (plugin.source.source === "github") {
429
- const url = `https://github.com/${plugin.source.repo}.git`;
430
- const tempDir = await cloneGitRepo(url, plugin.source.ref);
455
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
456
+ mkdirSync(tempDir, { recursive: true });
431
457
  try {
458
+ await fetchRepo(
459
+ { type: "github", repo: plugin.source.repo, ref: plugin.source.ref },
460
+ tempDir
461
+ );
432
462
  copyDirectory(tempDir, installDir);
433
463
  } finally {
434
464
  rmSync(tempDir, { recursive: true, force: true });
435
465
  }
436
466
  } else if (plugin.source.source === "url") {
437
- const tempDir = await cloneGitRepo(plugin.source.url, plugin.source.ref);
467
+ const tempDir = join(getMarketplaceDir(), "temp", Date.now().toString());
468
+ mkdirSync(tempDir, { recursive: true });
438
469
  try {
470
+ await fetchRepo(
471
+ { type: "url", url: plugin.source.url, ref: plugin.source.ref },
472
+ tempDir
473
+ );
439
474
  copyDirectory(tempDir, installDir);
440
475
  } finally {
441
476
  rmSync(tempDir, { recursive: true, force: true });
@@ -499,9 +534,11 @@ export {
499
534
  findPlugin,
500
535
  getMarketplace,
501
536
  installPluginFromMarketplace,
537
+ isMarketplaceRegistered,
502
538
  listMarketplaces,
503
539
  loadMarketplaceSettings,
504
540
  parseMarketplaceSource,
541
+ registerMarketplaceFromDirectory,
505
542
  removeMarketplace,
506
543
  updateMarketplace
507
544
  };