@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,3 +1,6 @@
1
+ import { existsSync, mkdirSync, appendFileSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
1
4
  import { countTokens } from "./tokens.js";
2
5
  import { getMessagesSetter } from "../messages.js";
3
6
  import { getContext } from "../context.js";
@@ -10,6 +13,10 @@ import { addLineNumbers } from "./file.js";
10
13
  import { getModelManager } from "./model.js";
11
14
  import { getCompressionPrompt } from "../constants/compressionPrompts.js";
12
15
  import { getCompressionMode } from "./compressionMode.js";
16
+ import { getHookManager } from "./hookManager.js";
17
+ import { emitReminderEvent } from "../services/systemReminder.js";
18
+ import { CONFIG_BASE_DIR } from "../constants/product.js";
19
+ import { getGlobalConfig } from "./config.js";
13
20
  const AUTO_COMPACT_THRESHOLD_RATIO = 0.92;
14
21
  async function getCompressionModelContextLimit() {
15
22
  try {
@@ -44,6 +51,11 @@ async function checkAutoCompact(messages, toolUseContext) {
44
51
  return { messages, wasCompacted: false };
45
52
  }
46
53
  try {
54
+ const hookManager = getHookManager();
55
+ if (hookManager) {
56
+ hookManager.executePreCompact("auto").catch(() => {
57
+ });
58
+ }
47
59
  const compactedMessages = await executeAutoCompact(messages, toolUseContext);
48
60
  return {
49
61
  messages: compactedMessages,
@@ -57,6 +69,52 @@ async function checkAutoCompact(messages, toolUseContext) {
57
69
  return { messages, wasCompacted: false };
58
70
  }
59
71
  }
72
+ const REMEMBER_PATTERNS = [
73
+ /\bremember\s+(this|that)\b/i,
74
+ /\balways\s+(use|do|prefer|avoid|skip)\b/i,
75
+ /\bnever\s+(use|do|commit|push|deploy)\b/i,
76
+ /\bfrom\s+now\s+on\b/i,
77
+ /\bin\s+the\s+future\b/i,
78
+ /\bgoing\s+forward\b/i,
79
+ /\bkeep\s+in\s+mind\b/i,
80
+ /\bdon'?t\s+forget\b/i
81
+ ];
82
+ function extractAutoMemory(messages) {
83
+ try {
84
+ const config = getGlobalConfig();
85
+ if (!config.autoMemory) return;
86
+ const memories = [];
87
+ for (const msg of messages) {
88
+ if (msg.type !== "user") continue;
89
+ const content = msg.message.content;
90
+ const text = typeof content === "string" ? content : Array.isArray(content) ? content.filter((b) => b.type === "text").map((b) => b.text).join("\n") : "";
91
+ if (!text) continue;
92
+ const matchesPattern = REMEMBER_PATTERNS.some((p) => p.test(text));
93
+ if (matchesPattern) {
94
+ const lines = text.split("\n");
95
+ for (const line of lines) {
96
+ const trimmed = line.trim();
97
+ if (trimmed && REMEMBER_PATTERNS.some((p) => p.test(trimmed))) {
98
+ memories.push(trimmed);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ if (memories.length === 0) return;
104
+ const autoMemoryDir = join(homedir(), CONFIG_BASE_DIR);
105
+ const autoMemoryPath = join(autoMemoryDir, "auto-memory.md");
106
+ if (!existsSync(autoMemoryDir)) {
107
+ mkdirSync(autoMemoryDir, { recursive: true });
108
+ }
109
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
110
+ const entry = `
111
+ ## ${timestamp}
112
+ ${memories.map((m) => `- ${m}`).join("\n")}
113
+ `;
114
+ appendFileSync(autoMemoryPath, entry, "utf-8");
115
+ } catch {
116
+ }
117
+ }
60
118
  async function executeAutoCompact(messages, toolUseContext) {
61
119
  const compressionMode = getCompressionMode();
62
120
  const compressionPrompt = getCompressionPrompt(compressionMode);
@@ -112,8 +170,10 @@ ${contentWithLines}
112
170
  *Automatically recovered (${file.tokens} tokens)${file.truncated ? " [truncated]" : ""}*`
113
171
  );
114
172
  compactedMessages.push(recoveryMessage);
173
+ emitReminderEvent("compact:file_reference", { filePath: file.path });
115
174
  }
116
175
  }
176
+ extractAutoMemory(messages);
117
177
  getMessagesSetter()([]);
118
178
  getContext.cache.clear?.();
119
179
  getCodeStyle.cache.clear?.();
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/autoCompactCore.ts"],
4
- "sourcesContent": ["import { Message } from '@query'\nimport { countTokens } from './tokens'\nimport { getMessagesGetter, getMessagesSetter } from '@messages'\nimport { getContext } from '@context'\nimport { getCodeStyle } from '@utils/style'\nimport { clearTerminal } from '@utils/terminal'\nimport { resetFileFreshnessSession } from '@services/fileFreshness'\nimport { createUserMessage, normalizeMessagesForAPI } from '@utils/messages'\nimport { queryLLM } from '@services/claude'\nimport { selectAndReadFiles } from './fileRecoveryCore'\nimport { addLineNumbers } from './file'\nimport { getModelManager } from './model'\nimport { getCompressionPrompt } from '@constants/compressionPrompts'\nimport { getCompressionMode } from './compressionMode'\n\n/**\n * Threshold ratio for triggering automatic context compression\n * When context usage exceeds 92% of the model's limit, auto-compact activates\n */\nconst AUTO_COMPACT_THRESHOLD_RATIO = 0.92\n\n/**\n * Retrieves the context length for the main model that should execute compression\n * Uses ModelManager to get the current model's context length\n */\nasync function getCompressionModelContextLimit(): Promise<number> {\n try {\n // \uD83D\uDD27 Fix: Use ModelManager instead of legacy config\n const modelManager = getModelManager()\n const modelProfile = modelManager.getModel('main')\n\n if (modelProfile?.contextLength) {\n return modelProfile.contextLength\n }\n\n // Fallback to a reasonable default\n return 200_000\n } catch (error) {\n return 200_000\n }\n}\n\n/**\n * Get the appropriate compression prompt based on current compression mode\n * This is now handled by the compression mode system\n */\n\n/**\n * Calculates context usage thresholds based on the main model's capabilities\n * Uses the main model context length since compression tasks require a capable model\n */\nasync function calculateThresholds(tokenCount: number) {\n const contextLimit = await getCompressionModelContextLimit()\n const autoCompactThreshold = contextLimit * AUTO_COMPACT_THRESHOLD_RATIO\n\n return {\n isAboveAutoCompactThreshold: tokenCount >= autoCompactThreshold,\n percentUsed: Math.round((tokenCount / contextLimit) * 100),\n tokensRemaining: Math.max(0, autoCompactThreshold - tokenCount),\n contextLimit,\n }\n}\n\n/**\n * Determines if auto-compact should trigger based on token usage\n * Uses the main model context limit since compression requires a capable model\n */\nasync function shouldAutoCompact(messages: Message[]): Promise<boolean> {\n if (messages.length < 3) return false\n\n const tokenCount = countTokens(messages)\n const { isAboveAutoCompactThreshold } = await calculateThresholds(tokenCount)\n\n return isAboveAutoCompactThreshold\n}\n\n/**\n * Main entry point for automatic context compression\n *\n * This function is called before each query to check if the conversation\n * has grown too large and needs compression. When triggered, it:\n * - Generates a structured summary of the conversation using the main model\n * - Recovers recently accessed files to maintain development context\n * - Resets conversation state while preserving essential information\n *\n * Uses the main model for compression tasks to ensure high-quality summaries\n *\n * @param messages Current conversation messages\n * @param toolUseContext Execution context with model and tool configuration\n * @returns Updated messages (compressed if needed) and compression status\n */\nexport async function checkAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<{ messages: Message[]; wasCompacted: boolean }> {\n if (!(await shouldAutoCompact(messages))) {\n return { messages, wasCompacted: false }\n }\n\n try {\n const compactedMessages = await executeAutoCompact(messages, toolUseContext)\n\n return {\n messages: compactedMessages,\n wasCompacted: true,\n }\n } catch (error) {\n // Graceful degradation: if auto-compact fails, continue with original messages\n // This ensures system remains functional even if compression encounters issues\n console.error(\n 'Auto-compact failed, continuing with original messages:',\n error,\n )\n return { messages, wasCompacted: false }\n }\n}\n\n/**\n * Executes the conversation compression process using the main model\n *\n * This function generates a comprehensive summary using the main model\n * which is better suited for complex summarization tasks. It also\n * automatically recovers important files to maintain development context.\n */\nasync function executeAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<Message[]> {\n // Get the compression prompt based on current mode (business or code)\n const compressionMode = getCompressionMode()\n const compressionPrompt = getCompressionPrompt(compressionMode)\n\n const summaryRequest = createUserMessage(compressionPrompt)\n\n const summaryResponse = await queryLLM(\n normalizeMessagesForAPI([...messages, summaryRequest]),\n [\n 'You are a helpful AI assistant tasked with creating comprehensive conversation summaries that preserve all essential context for continuing development work.',\n ],\n 0,\n toolUseContext.options.tools,\n toolUseContext.abortController.signal,\n {\n safeMode: false,\n model: 'main', // \u4F7F\u7528\u6A21\u578B\u6307\u9488\uFF0C\u8BA9queryLLM\u7EDF\u4E00\u89E3\u6790\n prependCLISysprompt: true,\n },\n )\n\n const content = summaryResponse.message.content\n const summary =\n typeof content === 'string'\n ? content\n : content.length > 0 && content[0]?.type === 'text'\n ? content[0].text\n : null\n\n if (!summary) {\n throw new Error(\n 'Failed to generate conversation summary - response did not contain valid text content',\n )\n }\n\n summaryResponse.message.usage = {\n input_tokens: 0,\n output_tokens: summaryResponse.message.usage.output_tokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n }\n\n // Automatic file recovery: preserve recently accessed development files\n // This maintains coding context even after conversation compression\n const recoveredFiles = await selectAndReadFiles()\n\n const compactedMessages = [\n createUserMessage(\n 'Context automatically compressed due to token limit. Essential information preserved.',\n ),\n summaryResponse,\n ]\n\n // Append recovered files to maintain development workflow continuity\n // Files are prioritized by recency and importance, with strict token limits\n if (recoveredFiles.length > 0) {\n for (const file of recoveredFiles) {\n const contentWithLines = addLineNumbers({\n content: file.content,\n startLine: 1,\n })\n const recoveryMessage = createUserMessage(\n `**Recovered File: ${file.path}**\\n\\n\\`\\`\\`\\n${contentWithLines}\\n\\`\\`\\`\\n\\n` +\n `*Automatically recovered (${file.tokens} tokens)${file.truncated ? ' [truncated]' : ''}*`,\n )\n compactedMessages.push(recoveryMessage)\n }\n }\n\n // State cleanup to ensure fresh context after compression\n // Mirrors the cleanup sequence from manual /compact command\n getMessagesSetter()([])\n getContext.cache.clear?.()\n getCodeStyle.cache.clear?.()\n resetFileFreshnessSession()\n\n return compactedMessages\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { existsSync, mkdirSync, appendFileSync } from 'fs'\nimport { join } from 'path'\nimport { homedir } from 'os'\nimport { Message } from '@query'\nimport { countTokens } from './tokens'\nimport { getMessagesGetter, getMessagesSetter } from '@messages'\nimport { getContext } from '@context'\nimport { getCodeStyle } from '@utils/style'\nimport { clearTerminal } from '@utils/terminal'\nimport { resetFileFreshnessSession } from '@services/fileFreshness'\nimport { createUserMessage, normalizeMessagesForAPI } from '@utils/messages'\nimport { queryLLM } from '@services/claude'\nimport { selectAndReadFiles } from './fileRecoveryCore'\nimport { addLineNumbers } from './file'\nimport { getModelManager } from './model'\nimport { getCompressionPrompt } from '@constants/compressionPrompts'\nimport { getCompressionMode } from './compressionMode'\nimport { getHookManager } from './hookManager'\nimport { emitReminderEvent } from '@services/systemReminder'\nimport { CONFIG_BASE_DIR } from '@constants/product'\nimport { getGlobalConfig } from './config'\n\n/**\n * Threshold ratio for triggering automatic context compression\n * When context usage exceeds 92% of the model's limit, auto-compact activates\n */\nconst AUTO_COMPACT_THRESHOLD_RATIO = 0.92\n\n/**\n * Retrieves the context length for the main model that should execute compression\n * Uses ModelManager to get the current model's context length\n */\nasync function getCompressionModelContextLimit(): Promise<number> {\n try {\n // \uD83D\uDD27 Fix: Use ModelManager instead of legacy config\n const modelManager = getModelManager()\n const modelProfile = modelManager.getModel('main')\n\n if (modelProfile?.contextLength) {\n return modelProfile.contextLength\n }\n\n // Fallback to a reasonable default\n return 200_000\n } catch (error) {\n return 200_000\n }\n}\n\n/**\n * Get the appropriate compression prompt based on current compression mode\n * This is now handled by the compression mode system\n */\n\n/**\n * Calculates context usage thresholds based on the main model's capabilities\n * Uses the main model context length since compression tasks require a capable model\n */\nasync function calculateThresholds(tokenCount: number) {\n const contextLimit = await getCompressionModelContextLimit()\n const autoCompactThreshold = contextLimit * AUTO_COMPACT_THRESHOLD_RATIO\n\n return {\n isAboveAutoCompactThreshold: tokenCount >= autoCompactThreshold,\n percentUsed: Math.round((tokenCount / contextLimit) * 100),\n tokensRemaining: Math.max(0, autoCompactThreshold - tokenCount),\n contextLimit,\n }\n}\n\n/**\n * Determines if auto-compact should trigger based on token usage\n * Uses the main model context limit since compression requires a capable model\n */\nasync function shouldAutoCompact(messages: Message[]): Promise<boolean> {\n if (messages.length < 3) return false\n\n const tokenCount = countTokens(messages)\n const { isAboveAutoCompactThreshold } = await calculateThresholds(tokenCount)\n\n return isAboveAutoCompactThreshold\n}\n\n/**\n * Main entry point for automatic context compression\n *\n * This function is called before each query to check if the conversation\n * has grown too large and needs compression. When triggered, it:\n * - Generates a structured summary of the conversation using the main model\n * - Recovers recently accessed files to maintain development context\n * - Resets conversation state while preserving essential information\n *\n * Uses the main model for compression tasks to ensure high-quality summaries\n *\n * @param messages Current conversation messages\n * @param toolUseContext Execution context with model and tool configuration\n * @returns Updated messages (compressed if needed) and compression status\n */\nexport async function checkAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<{ messages: Message[]; wasCompacted: boolean }> {\n if (!(await shouldAutoCompact(messages))) {\n return { messages, wasCompacted: false }\n }\n\n try {\n // Fire PreCompact hook before compaction\n const hookManager = getHookManager()\n if (hookManager) {\n hookManager.executePreCompact('auto').catch(() => {})\n }\n\n const compactedMessages = await executeAutoCompact(messages, toolUseContext)\n\n return {\n messages: compactedMessages,\n wasCompacted: true,\n }\n } catch (error) {\n // Graceful degradation: if auto-compact fails, continue with original messages\n // This ensures system remains functional even if compression encounters issues\n console.error(\n 'Auto-compact failed, continuing with original messages:',\n error,\n )\n return { messages, wasCompacted: false }\n }\n}\n\n/**\n * Patterns that indicate the user wants something remembered across sessions.\n */\nconst REMEMBER_PATTERNS = [\n /\\bremember\\s+(this|that)\\b/i,\n /\\balways\\s+(use|do|prefer|avoid|skip)\\b/i,\n /\\bnever\\s+(use|do|commit|push|deploy)\\b/i,\n /\\bfrom\\s+now\\s+on\\b/i,\n /\\bin\\s+the\\s+future\\b/i,\n /\\bgoing\\s+forward\\b/i,\n /\\bkeep\\s+in\\s+mind\\b/i,\n /\\bdon'?t\\s+forget\\b/i,\n]\n\n/**\n * Extracts \"remember this\" instructions from user messages and appends\n * them to ~/.minto/auto-memory.md. Only active when autoMemory config is true.\n */\nfunction extractAutoMemory(messages: Message[]): void {\n try {\n const config = getGlobalConfig()\n if (!config.autoMemory) return\n\n const memories: string[] = []\n\n for (const msg of messages) {\n if (msg.type !== 'user') continue\n const content = msg.message.content\n const text =\n typeof content === 'string'\n ? content\n : Array.isArray(content)\n ? content\n .filter((b: any) => b.type === 'text')\n .map((b: any) => b.text)\n .join('\\n')\n : ''\n\n if (!text) continue\n\n const matchesPattern = REMEMBER_PATTERNS.some(p => p.test(text))\n if (matchesPattern) {\n // Extract the relevant line(s) containing the pattern\n const lines = text.split('\\n')\n for (const line of lines) {\n const trimmed = line.trim()\n if (trimmed && REMEMBER_PATTERNS.some(p => p.test(trimmed))) {\n memories.push(trimmed)\n }\n }\n }\n }\n\n if (memories.length === 0) return\n\n const autoMemoryDir = join(homedir(), CONFIG_BASE_DIR)\n const autoMemoryPath = join(autoMemoryDir, 'auto-memory.md')\n\n if (!existsSync(autoMemoryDir)) {\n mkdirSync(autoMemoryDir, { recursive: true })\n }\n\n const timestamp = new Date().toISOString().split('T')[0]\n const entry = `\\n## ${timestamp}\\n${memories.map(m => `- ${m}`).join('\\n')}\\n`\n\n appendFileSync(autoMemoryPath, entry, 'utf-8')\n } catch {\n // Graceful degradation: auto-memory extraction is best-effort\n }\n}\n\n/**\n * Executes the conversation compression process using the main model\n *\n * This function generates a comprehensive summary using the main model\n * which is better suited for complex summarization tasks. It also\n * automatically recovers important files to maintain development context.\n */\nasync function executeAutoCompact(\n messages: Message[],\n toolUseContext: any,\n): Promise<Message[]> {\n // Get the compression prompt based on current mode (business or code)\n const compressionMode = getCompressionMode()\n const compressionPrompt = getCompressionPrompt(compressionMode)\n\n const summaryRequest = createUserMessage(compressionPrompt)\n\n const summaryResponse = await queryLLM(\n normalizeMessagesForAPI([...messages, summaryRequest]),\n [\n 'You are a helpful AI assistant tasked with creating comprehensive conversation summaries that preserve all essential context for continuing development work.',\n ],\n 0,\n toolUseContext.options.tools,\n toolUseContext.abortController.signal,\n {\n safeMode: false,\n model: 'main', // \u4F7F\u7528\u6A21\u578B\u6307\u9488\uFF0C\u8BA9queryLLM\u7EDF\u4E00\u89E3\u6790\n prependCLISysprompt: true,\n },\n )\n\n const content = summaryResponse.message.content\n const summary =\n typeof content === 'string'\n ? content\n : content.length > 0 && content[0]?.type === 'text'\n ? content[0].text\n : null\n\n if (!summary) {\n throw new Error(\n 'Failed to generate conversation summary - response did not contain valid text content',\n )\n }\n\n summaryResponse.message.usage = {\n input_tokens: 0,\n output_tokens: summaryResponse.message.usage.output_tokens,\n cache_creation_input_tokens: 0,\n cache_read_input_tokens: 0,\n }\n\n // Automatic file recovery: preserve recently accessed development files\n // This maintains coding context even after conversation compression\n const recoveredFiles = await selectAndReadFiles()\n\n const compactedMessages = [\n createUserMessage(\n 'Context automatically compressed due to token limit. Essential information preserved.',\n ),\n summaryResponse,\n ]\n\n // Append recovered files to maintain development workflow continuity\n // Files are prioritized by recency and importance, with strict token limits\n if (recoveredFiles.length > 0) {\n for (const file of recoveredFiles) {\n const contentWithLines = addLineNumbers({\n content: file.content,\n startLine: 1,\n })\n const recoveryMessage = createUserMessage(\n `**Recovered File: ${file.path}**\\n\\n\\`\\`\\`\\n${contentWithLines}\\n\\`\\`\\`\\n\\n` +\n `*Automatically recovered (${file.tokens} tokens)${file.truncated ? ' [truncated]' : ''}*`,\n )\n compactedMessages.push(recoveryMessage)\n\n emitReminderEvent('compact:file_reference', { filePath: file.path })\n }\n }\n\n // Extract auto-memory from conversation before discarding messages\n extractAutoMemory(messages)\n\n // State cleanup to ensure fresh context after compression\n // Mirrors the cleanup sequence from manual /compact command\n getMessagesSetter()([])\n getContext.cache.clear?.()\n getCodeStyle.cache.clear?.()\n resetFileFreshnessSession()\n\n return compactedMessages\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,439 @@
1
+ import {
2
+ existsSync,
3
+ readFileSync,
4
+ writeFileSync,
5
+ mkdirSync,
6
+ rmSync,
7
+ cpSync,
8
+ readdirSync,
9
+ statSync
10
+ } from "fs";
11
+ import { join, basename } from "path";
12
+ import { homedir } from "os";
13
+ import {
14
+ isMarketplaceRegistered,
15
+ registerMarketplaceFromDirectory
16
+ } from "./marketplaceManager.js";
17
+ const CC_HOME = join(homedir(), ".claude");
18
+ const CC_REGISTRY_PATH = join(CC_HOME, "plugins", "installed_plugins.json");
19
+ const CC_SETTINGS_PATH = join(CC_HOME, "settings.json");
20
+ const CC_MARKETPLACES_PATH = join(CC_HOME, "plugins", "known_marketplaces.json");
21
+ const MINTO_HOME = join(homedir(), ".minto");
22
+ const MINTO_SYNC_STATE_PATH = join(MINTO_HOME, "cc-sync-state.json");
23
+ const MINTO_PLUGINS_DIR = join(MINTO_HOME, "plugins");
24
+ function loadJSON(path) {
25
+ if (!existsSync(path)) return null;
26
+ try {
27
+ return JSON.parse(readFileSync(path, "utf-8"));
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+ function loadCCRegistry() {
33
+ return loadJSON(CC_REGISTRY_PATH);
34
+ }
35
+ function loadCCSettings() {
36
+ return loadJSON(CC_SETTINGS_PATH) ?? {};
37
+ }
38
+ function loadCCKnownMarketplaces() {
39
+ return loadJSON(CC_MARKETPLACES_PATH);
40
+ }
41
+ function convertCCSourceToMintoSource(ccSource) {
42
+ switch (ccSource.source) {
43
+ case "github":
44
+ if (!ccSource.repo) return null;
45
+ return { type: "github", repo: ccSource.repo, ref: ccSource.ref };
46
+ case "url":
47
+ if (!ccSource.url) return null;
48
+ return { type: "url", url: ccSource.url, ref: ccSource.ref };
49
+ case "local":
50
+ return null;
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+ function resolveMarketplaceSource(marketplace, knownMarketplaces) {
56
+ if (!knownMarketplaces) return null;
57
+ const mp = knownMarketplaces[marketplace];
58
+ if (!mp) return null;
59
+ return convertCCSourceToMintoSource(mp.source);
60
+ }
61
+ function syncMarketplaces(knownMarketplaces, dryRun, onProgress) {
62
+ const result = {
63
+ registered: [],
64
+ skipped: [],
65
+ failed: []
66
+ };
67
+ if (!knownMarketplaces) return result;
68
+ for (const [name, mp] of Object.entries(knownMarketplaces)) {
69
+ try {
70
+ if (isMarketplaceRegistered(name)) {
71
+ result.skipped.push(name);
72
+ continue;
73
+ }
74
+ const mintoSource = convertCCSourceToMintoSource(mp.source);
75
+ if (!mintoSource) {
76
+ result.skipped.push(name);
77
+ continue;
78
+ }
79
+ if (!mp.installLocation || !existsSync(mp.installLocation)) {
80
+ result.failed.push({
81
+ name,
82
+ error: `Install location not found: ${mp.installLocation || "(empty)"}`
83
+ });
84
+ continue;
85
+ }
86
+ if (dryRun) {
87
+ result.registered.push(name);
88
+ continue;
89
+ }
90
+ onProgress?.(`Registering marketplace ${name}...`);
91
+ const registered = registerMarketplaceFromDirectory(
92
+ name,
93
+ mintoSource,
94
+ mp.installLocation
95
+ );
96
+ if (registered) {
97
+ result.registered.push(name);
98
+ } else {
99
+ result.skipped.push(name);
100
+ }
101
+ } catch (err) {
102
+ result.failed.push({
103
+ name,
104
+ error: err instanceof Error ? err.message : String(err)
105
+ });
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ function loadSyncState() {
111
+ return loadJSON(MINTO_SYNC_STATE_PATH);
112
+ }
113
+ function saveSyncState(state) {
114
+ if (!existsSync(MINTO_HOME)) {
115
+ mkdirSync(MINTO_HOME, { recursive: true });
116
+ }
117
+ writeFileSync(MINTO_SYNC_STATE_PATH, JSON.stringify(state, null, 2), "utf-8");
118
+ }
119
+ function hasClaudeCodeInstallation() {
120
+ return existsSync(CC_REGISTRY_PATH);
121
+ }
122
+ function getClaudeCodePluginCount() {
123
+ const registry = loadCCRegistry();
124
+ if (!registry) return 0;
125
+ return Object.keys(registry.plugins).length;
126
+ }
127
+ function needsSync() {
128
+ if (!existsSync(CC_REGISTRY_PATH)) return false;
129
+ const state = loadSyncState();
130
+ if (!state) return true;
131
+ try {
132
+ const stat = statSync(CC_REGISTRY_PATH);
133
+ const mtime = stat.mtime.toISOString();
134
+ return mtime !== state.lastRegistryModified;
135
+ } catch {
136
+ return false;
137
+ }
138
+ }
139
+ const EXCLUDE_PATTERNS = /* @__PURE__ */ new Set([
140
+ ".git",
141
+ ".orphaned_at",
142
+ ".DS_Store",
143
+ "node_modules",
144
+ ".github"
145
+ ]);
146
+ function shouldCopy(src) {
147
+ const name = basename(src);
148
+ return !EXCLUDE_PATTERNS.has(name);
149
+ }
150
+ function copyPluginFromCache(sourcePath, targetPath) {
151
+ if (!existsSync(sourcePath)) {
152
+ throw new Error(`Source path does not exist: ${sourcePath}`);
153
+ }
154
+ if (!existsSync(targetPath)) {
155
+ mkdirSync(targetPath, { recursive: true });
156
+ }
157
+ cpSync(sourcePath, targetPath, {
158
+ recursive: true,
159
+ filter: shouldCopy
160
+ });
161
+ }
162
+ function loadMarketplacePluginMeta(marketplaceName, pluginName) {
163
+ const knownMPs = loadCCKnownMarketplaces();
164
+ if (!knownMPs) return null;
165
+ const mp = knownMPs[marketplaceName];
166
+ if (!mp?.installLocation) return null;
167
+ const mpJsonPath = join(
168
+ mp.installLocation,
169
+ ".claude-plugin",
170
+ "marketplace.json"
171
+ );
172
+ if (!existsSync(mpJsonPath)) return null;
173
+ try {
174
+ const manifest = JSON.parse(readFileSync(mpJsonPath, "utf-8"));
175
+ const plugins = manifest.plugins || [];
176
+ return plugins.find((p) => p.name === pluginName) ?? null;
177
+ } catch {
178
+ return null;
179
+ }
180
+ }
181
+ function generatePluginManifest(pluginName, marketplace, ccEntry, meta) {
182
+ const agents = [];
183
+ const commands = [];
184
+ const skills = [];
185
+ const agentsDir = join(ccEntry.installPath, "agents");
186
+ if (existsSync(agentsDir)) {
187
+ try {
188
+ agents.push(
189
+ ...readdirSync(agentsDir).filter((f) => f.endsWith(".md")).map((f) => `agents/${f}`)
190
+ );
191
+ } catch {
192
+ }
193
+ }
194
+ const commandsDir = join(ccEntry.installPath, "commands");
195
+ if (existsSync(commandsDir)) {
196
+ try {
197
+ commands.push(
198
+ ...readdirSync(commandsDir).filter((f) => f.endsWith(".md")).map((f) => `commands/${f}`)
199
+ );
200
+ } catch {
201
+ }
202
+ }
203
+ const skillsDir = join(ccEntry.installPath, "skills");
204
+ if (existsSync(skillsDir)) {
205
+ try {
206
+ for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
207
+ if (entry.isDirectory()) {
208
+ const skillMd = join(skillsDir, entry.name, "SKILL.md");
209
+ if (existsSync(skillMd)) {
210
+ skills.push(`skills/${entry.name}/SKILL.md`);
211
+ }
212
+ } else if (entry.isFile() && entry.name.endsWith(".md")) {
213
+ skills.push(`skills/${entry.name}`);
214
+ }
215
+ }
216
+ } catch {
217
+ }
218
+ }
219
+ return {
220
+ name: pluginName,
221
+ version: meta?.version || ccEntry.version || "1.0.0",
222
+ description: meta?.description || `Claude Code plugin: ${pluginName}`,
223
+ displayName: pluginName,
224
+ author: meta?.author,
225
+ homepage: meta?.homepage,
226
+ repository: meta?.repository,
227
+ license: meta?.license,
228
+ agents,
229
+ commands,
230
+ skills
231
+ };
232
+ }
233
+ function syncSinglePlugin(pluginName, marketplace, entry, enabled, syncState, dryRun, knownMarketplaces) {
234
+ const targetPath = join(MINTO_PLUGINS_DIR, pluginName);
235
+ const ccSyncPath = join(targetPath, ".cc-sync.json");
236
+ if (existsSync(targetPath) && !existsSync(ccSyncPath)) {
237
+ return "skipped";
238
+ }
239
+ if (existsSync(ccSyncPath)) {
240
+ try {
241
+ const existing = JSON.parse(readFileSync(ccSyncPath, "utf-8"));
242
+ if (existing.version === entry.version && existing.gitCommitSha === entry.gitCommitSha) {
243
+ return "skipped";
244
+ }
245
+ } catch {
246
+ }
247
+ }
248
+ const isUpdate = existsSync(targetPath);
249
+ if (dryRun) {
250
+ return isUpdate ? "updated" : "installed";
251
+ }
252
+ if (isUpdate) {
253
+ rmSync(targetPath, { recursive: true, force: true });
254
+ }
255
+ copyPluginFromCache(entry.installPath, targetPath);
256
+ const meta = loadMarketplacePluginMeta(marketplace, pluginName);
257
+ const manifest = generatePluginManifest(pluginName, marketplace, entry, meta);
258
+ const mintoPluginDir = join(targetPath, ".minto-plugin");
259
+ mkdirSync(mintoPluginDir, { recursive: true });
260
+ writeFileSync(
261
+ join(mintoPluginDir, "plugin.json"),
262
+ JSON.stringify(manifest, null, 2),
263
+ "utf-8"
264
+ );
265
+ const realSource = resolveMarketplaceSource(marketplace, knownMarketplaces);
266
+ writeFileSync(
267
+ join(targetPath, ".marketplace-meta.json"),
268
+ JSON.stringify(
269
+ {
270
+ marketplace,
271
+ plugin: pluginName,
272
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
273
+ source: realSource ?? { source: "claude-code" },
274
+ ...realSource ? { syncedFrom: "claude-code" } : {}
275
+ },
276
+ null,
277
+ 2
278
+ ),
279
+ "utf-8"
280
+ );
281
+ writeFileSync(
282
+ join(targetPath, ".cc-sync.json"),
283
+ JSON.stringify(
284
+ {
285
+ name: pluginName,
286
+ version: entry.version,
287
+ gitCommitSha: entry.gitCommitSha,
288
+ marketplace,
289
+ syncedAt: (/* @__PURE__ */ new Date()).toISOString(),
290
+ source: entry.installPath
291
+ },
292
+ null,
293
+ 2
294
+ ),
295
+ "utf-8"
296
+ );
297
+ writeFileSync(
298
+ join(targetPath, ".plugin-config.json"),
299
+ JSON.stringify({ enabled }, null, 2),
300
+ "utf-8"
301
+ );
302
+ return isUpdate ? "updated" : "installed";
303
+ }
304
+ async function syncFromClaudeCode(options = {}) {
305
+ const { force = false, clean = false, dryRun = false, onProgress } = options;
306
+ const result = {
307
+ installed: [],
308
+ updated: [],
309
+ skipped: [],
310
+ failed: [],
311
+ cleaned: [],
312
+ total: 0,
313
+ marketplaces: { registered: [], skipped: [], failed: [] }
314
+ };
315
+ const registry = loadCCRegistry();
316
+ if (!registry) {
317
+ return result;
318
+ }
319
+ const settings = loadCCSettings();
320
+ const enabledPlugins = settings.enabledPlugins || {};
321
+ const syncState = force ? null : loadSyncState();
322
+ const knownMarketplaces = loadCCKnownMarketplaces();
323
+ if (!existsSync(MINTO_PLUGINS_DIR)) {
324
+ mkdirSync(MINTO_PLUGINS_DIR, { recursive: true });
325
+ }
326
+ try {
327
+ for (const dir of readdirSync(MINTO_PLUGINS_DIR, { withFileTypes: true })) {
328
+ if (!dir.isDirectory()) continue;
329
+ const pluginDir = join(MINTO_PLUGINS_DIR, dir.name);
330
+ const rootManifest = join(pluginDir, "plugin.json");
331
+ const mintoManifest = join(pluginDir, ".minto-plugin", "plugin.json");
332
+ const ccSyncMarker = join(pluginDir, ".cc-sync.json");
333
+ if (existsSync(ccSyncMarker) && existsSync(rootManifest) && !existsSync(mintoManifest)) {
334
+ mkdirSync(join(pluginDir, ".minto-plugin"), { recursive: true });
335
+ cpSync(rootManifest, mintoManifest);
336
+ }
337
+ }
338
+ } catch {
339
+ }
340
+ onProgress?.("Scanning Claude Code registry...");
341
+ const pluginKeys = Object.keys(registry.plugins);
342
+ result.total = pluginKeys.length;
343
+ for (const pluginKey of pluginKeys) {
344
+ const atIdx = pluginKey.indexOf("@");
345
+ if (atIdx === -1) continue;
346
+ const pluginName = pluginKey.slice(0, atIdx);
347
+ const marketplace = pluginKey.slice(atIdx + 1);
348
+ const entries = registry.plugins[pluginKey];
349
+ const entry = entries.find((e) => e.scope === "user") || entries[0];
350
+ if (!entry) continue;
351
+ const enabled = enabledPlugins[pluginKey] !== false;
352
+ try {
353
+ onProgress?.(
354
+ existsSync(join(MINTO_PLUGINS_DIR, pluginName)) ? `Updating ${pluginName}...` : `Installing ${pluginName}...`
355
+ );
356
+ const action = syncSinglePlugin(
357
+ pluginName,
358
+ marketplace,
359
+ entry,
360
+ enabled,
361
+ syncState,
362
+ dryRun,
363
+ knownMarketplaces
364
+ );
365
+ switch (action) {
366
+ case "installed":
367
+ result.installed.push(pluginName);
368
+ break;
369
+ case "updated":
370
+ result.updated.push(pluginName);
371
+ break;
372
+ case "skipped":
373
+ result.skipped.push(pluginName);
374
+ break;
375
+ }
376
+ } catch (err) {
377
+ result.failed.push({
378
+ name: pluginName,
379
+ error: err instanceof Error ? err.message : String(err)
380
+ });
381
+ }
382
+ }
383
+ if (clean && !dryRun && existsSync(MINTO_PLUGINS_DIR)) {
384
+ const ccPluginNames = new Set(
385
+ pluginKeys.map((k) => k.slice(0, k.indexOf("@")))
386
+ );
387
+ for (const dir of readdirSync(MINTO_PLUGINS_DIR)) {
388
+ const pluginPath = join(MINTO_PLUGINS_DIR, dir);
389
+ const ccSyncPath = join(pluginPath, ".cc-sync.json");
390
+ if (!existsSync(ccSyncPath)) continue;
391
+ if (ccPluginNames.has(dir)) continue;
392
+ rmSync(pluginPath, { recursive: true, force: true });
393
+ result.cleaned.push(dir);
394
+ }
395
+ }
396
+ try {
397
+ onProgress?.("Syncing marketplaces...");
398
+ result.marketplaces = syncMarketplaces(
399
+ knownMarketplaces,
400
+ dryRun,
401
+ onProgress
402
+ );
403
+ } catch {
404
+ }
405
+ if (!dryRun) {
406
+ const registryStat = statSync(CC_REGISTRY_PATH);
407
+ const newState = {
408
+ lastSyncedAt: (/* @__PURE__ */ new Date()).toISOString(),
409
+ lastRegistryModified: registryStat.mtime.toISOString(),
410
+ plugins: {}
411
+ };
412
+ if (existsSync(MINTO_PLUGINS_DIR)) {
413
+ for (const dir of readdirSync(MINTO_PLUGINS_DIR)) {
414
+ const ccSyncPath = join(MINTO_PLUGINS_DIR, dir, ".cc-sync.json");
415
+ if (!existsSync(ccSyncPath)) continue;
416
+ try {
417
+ const meta = JSON.parse(readFileSync(ccSyncPath, "utf-8"));
418
+ newState.plugins[dir] = {
419
+ version: meta.version,
420
+ gitCommitSha: meta.gitCommitSha,
421
+ syncedAt: meta.syncedAt,
422
+ marketplace: meta.marketplace
423
+ };
424
+ } catch {
425
+ }
426
+ }
427
+ }
428
+ saveSyncState(newState);
429
+ }
430
+ return result;
431
+ }
432
+ export {
433
+ getClaudeCodePluginCount,
434
+ hasClaudeCodeInstallation,
435
+ loadCCKnownMarketplaces,
436
+ needsSync,
437
+ syncFromClaudeCode
438
+ };
439
+ //# sourceMappingURL=claudeCodeSync.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/claudeCodeSync.ts"],
4
+ "sourcesContent": ["/**\n * Claude Code \u2192 Minto Plugin Sync\n *\n * Reads Claude Code's installed_plugins.json registry, compares with Minto's\n * sync state, and copies new/updated plugins into ~/.minto/plugins/.\n *\n * Design:\n * - Never modifies Claude Code files\n * - Minto-manual plugins (no .cc-sync.json) are never overwritten\n * - Sync state tracked in ~/.minto/cc-sync-state.json\n */\n\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n rmSync,\n cpSync,\n readdirSync,\n statSync,\n} from 'fs'\nimport { join, basename } from 'path'\nimport { homedir } from 'os'\nimport type { MarketplaceSource } from '../types/marketplace'\nimport {\n isMarketplaceRegistered,\n registerMarketplaceFromDirectory,\n} from './marketplaceManager'\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\ninterface CCPluginEntry {\n scope: 'user' | 'project'\n installPath: string\n version: string\n installedAt: string\n lastUpdated: string\n gitCommitSha?: string\n}\n\ninterface CCRegistry {\n version: number\n plugins: Record<string, CCPluginEntry[]> // key = \"name@marketplace\"\n}\n\ninterface CCSettings {\n enabledPlugins?: Record<string, boolean>\n}\n\ninterface CCKnownMarketplace {\n source: { source: string; repo?: string; url?: string; ref?: string }\n installLocation: string\n lastUpdated: string\n}\n\ninterface CCSyncPluginState {\n version: string\n gitCommitSha?: string\n syncedAt: string\n marketplace: string\n}\n\ninterface CCSyncState {\n lastSyncedAt: string\n lastRegistryModified: string // mtime ISO string\n plugins: Record<string, CCSyncPluginState> // key = plugin name\n}\n\nexport interface MarketplaceSyncResult {\n registered: string[]\n skipped: string[]\n failed: Array<{ name: string; error: string }>\n}\n\nexport interface SyncResult {\n installed: string[]\n updated: string[]\n skipped: string[]\n failed: Array<{ name: string; error: string }>\n cleaned: string[]\n total: number\n marketplaces: MarketplaceSyncResult\n}\n\nexport interface SyncOptions {\n force?: boolean\n clean?: boolean\n dryRun?: boolean\n onProgress?: (msg: string) => void\n}\n\n// ---------------------------------------------------------------------------\n// Path constants\n// ---------------------------------------------------------------------------\n\nconst CC_HOME = join(homedir(), '.claude')\nconst CC_REGISTRY_PATH = join(CC_HOME, 'plugins', 'installed_plugins.json')\nconst CC_SETTINGS_PATH = join(CC_HOME, 'settings.json')\nconst CC_MARKETPLACES_PATH = join(CC_HOME, 'plugins', 'known_marketplaces.json')\nconst MINTO_HOME = join(homedir(), '.minto')\nconst MINTO_SYNC_STATE_PATH = join(MINTO_HOME, 'cc-sync-state.json')\nconst MINTO_PLUGINS_DIR = join(MINTO_HOME, 'plugins')\n\n// ---------------------------------------------------------------------------\n// Helpers \u2014 load CC data\n// ---------------------------------------------------------------------------\n\nfunction loadJSON<T>(path: string): T | null {\n if (!existsSync(path)) return null\n try {\n return JSON.parse(readFileSync(path, 'utf-8')) as T\n } catch {\n return null\n }\n}\n\nfunction loadCCRegistry(): CCRegistry | null {\n return loadJSON<CCRegistry>(CC_REGISTRY_PATH)\n}\n\nfunction loadCCSettings(): CCSettings {\n return loadJSON<CCSettings>(CC_SETTINGS_PATH) ?? {}\n}\n\nexport function loadCCKnownMarketplaces(): Record<\n string,\n CCKnownMarketplace\n> | null {\n return loadJSON<Record<string, CCKnownMarketplace>>(CC_MARKETPLACES_PATH)\n}\n\n// ---------------------------------------------------------------------------\n// Helpers \u2014 CC\u2192Minto source conversion\n// ---------------------------------------------------------------------------\n\n/**\n * Convert Claude Code's marketplace source format to Minto's MarketplaceSource.\n * CC uses `{ source: 'github', repo }` while Minto uses `{ type: 'github', repo }`.\n * Returns null for unknown types or missing required fields.\n */\nfunction convertCCSourceToMintoSource(\n ccSource: CCKnownMarketplace['source'],\n): MarketplaceSource | null {\n switch (ccSource.source) {\n case 'github':\n if (!ccSource.repo) return null\n return { type: 'github', repo: ccSource.repo, ref: ccSource.ref }\n case 'url':\n if (!ccSource.url) return null\n return { type: 'url', url: ccSource.url, ref: ccSource.ref }\n case 'local':\n // Local sources from CC don't transfer meaningfully\n return null\n default:\n return null\n }\n}\n\n/**\n * Resolve a marketplace source for a plugin from CC's known_marketplaces.json.\n * Used to write real source info into .marketplace-meta.json instead of `{ source: 'claude-code' }`.\n */\nfunction resolveMarketplaceSource(\n marketplace: string,\n knownMarketplaces: Record<string, CCKnownMarketplace> | null,\n): MarketplaceSource | null {\n if (!knownMarketplaces) return null\n const mp = knownMarketplaces[marketplace]\n if (!mp) return null\n return convertCCSourceToMintoSource(mp.source)\n}\n\n/**\n * Sync marketplaces from Claude Code's known_marketplaces.json into Minto's registry.\n * Non-blocking: errors per-marketplace are caught and recorded.\n */\nfunction syncMarketplaces(\n knownMarketplaces: Record<string, CCKnownMarketplace> | null,\n dryRun: boolean,\n onProgress?: (msg: string) => void,\n): MarketplaceSyncResult {\n const result: MarketplaceSyncResult = {\n registered: [],\n skipped: [],\n failed: [],\n }\n\n if (!knownMarketplaces) return result\n\n for (const [name, mp] of Object.entries(knownMarketplaces)) {\n try {\n // Already in Minto registry?\n if (isMarketplaceRegistered(name)) {\n result.skipped.push(name)\n continue\n }\n\n // Convert source format\n const mintoSource = convertCCSourceToMintoSource(mp.source)\n if (!mintoSource) {\n result.skipped.push(name)\n continue\n }\n\n // Verify CC's local clone exists\n if (!mp.installLocation || !existsSync(mp.installLocation)) {\n result.failed.push({\n name,\n error: `Install location not found: ${mp.installLocation || '(empty)'}`,\n })\n continue\n }\n\n if (dryRun) {\n result.registered.push(name)\n continue\n }\n\n onProgress?.(`Registering marketplace ${name}...`)\n const registered = registerMarketplaceFromDirectory(\n name,\n mintoSource,\n mp.installLocation,\n )\n\n if (registered) {\n result.registered.push(name)\n } else {\n result.skipped.push(name) // race: registered between check and call\n }\n } catch (err) {\n result.failed.push({\n name,\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n return result\n}\n\n// ---------------------------------------------------------------------------\n// Helpers \u2014 sync state\n// ---------------------------------------------------------------------------\n\nfunction loadSyncState(): CCSyncState | null {\n return loadJSON<CCSyncState>(MINTO_SYNC_STATE_PATH)\n}\n\nfunction saveSyncState(state: CCSyncState): void {\n if (!existsSync(MINTO_HOME)) {\n mkdirSync(MINTO_HOME, { recursive: true })\n }\n writeFileSync(MINTO_SYNC_STATE_PATH, JSON.stringify(state, null, 2), 'utf-8')\n}\n\n// ---------------------------------------------------------------------------\n// Public \u2014 quick checks\n// ---------------------------------------------------------------------------\n\n/** Returns true if Claude Code is installed with plugins */\nexport function hasClaudeCodeInstallation(): boolean {\n return existsSync(CC_REGISTRY_PATH)\n}\n\n/** Returns total plugin count in CC registry (for prompts) */\nexport function getClaudeCodePluginCount(): number {\n const registry = loadCCRegistry()\n if (!registry) return 0\n return Object.keys(registry.plugins).length\n}\n\n/**\n * Fast check: does Minto need to sync from CC?\n * O(1) \u2014 only stats one file.\n */\nexport function needsSync(): boolean {\n if (!existsSync(CC_REGISTRY_PATH)) return false\n\n const state = loadSyncState()\n if (!state) return true // never synced\n\n try {\n const stat = statSync(CC_REGISTRY_PATH)\n const mtime = stat.mtime.toISOString()\n return mtime !== state.lastRegistryModified\n } catch {\n return false\n }\n}\n\n// ---------------------------------------------------------------------------\n// Core \u2014 copy plugin from CC cache\n// ---------------------------------------------------------------------------\n\nconst EXCLUDE_PATTERNS = new Set([\n '.git',\n '.orphaned_at',\n '.DS_Store',\n 'node_modules',\n '.github',\n])\n\nfunction shouldCopy(src: string): boolean {\n const name = basename(src)\n return !EXCLUDE_PATTERNS.has(name)\n}\n\nfunction copyPluginFromCache(sourcePath: string, targetPath: string): void {\n if (!existsSync(sourcePath)) {\n throw new Error(`Source path does not exist: ${sourcePath}`)\n }\n\n if (!existsSync(targetPath)) {\n mkdirSync(targetPath, { recursive: true })\n }\n\n cpSync(sourcePath, targetPath, {\n recursive: true,\n filter: shouldCopy,\n })\n}\n\n// ---------------------------------------------------------------------------\n// Core \u2014 generate Minto plugin.json from CC metadata\n// ---------------------------------------------------------------------------\n\ninterface MarketplacePluginMeta {\n name: string\n description?: string\n version?: string\n author?: string | { name: string; url?: string; email?: string }\n homepage?: string\n repository?: string\n license?: string\n keywords?: string[]\n category?: string\n}\n\nfunction loadMarketplacePluginMeta(\n marketplaceName: string,\n pluginName: string,\n): MarketplacePluginMeta | null {\n const knownMPs = loadCCKnownMarketplaces()\n if (!knownMPs) return null\n\n const mp = knownMPs[marketplaceName]\n if (!mp?.installLocation) return null\n\n // Try .claude-plugin/marketplace.json\n const mpJsonPath = join(\n mp.installLocation,\n '.claude-plugin',\n 'marketplace.json',\n )\n if (!existsSync(mpJsonPath)) return null\n\n try {\n const manifest = JSON.parse(readFileSync(mpJsonPath, 'utf-8'))\n const plugins: MarketplacePluginMeta[] = manifest.plugins || []\n return plugins.find(p => p.name === pluginName) ?? null\n } catch {\n return null\n }\n}\n\nfunction generatePluginManifest(\n pluginName: string,\n marketplace: string,\n ccEntry: CCPluginEntry,\n meta: MarketplacePluginMeta | null,\n): Record<string, unknown> {\n // Scan for component directories\n const agents: string[] = []\n const commands: string[] = []\n const skills: string[] = []\n\n const agentsDir = join(ccEntry.installPath, 'agents')\n if (existsSync(agentsDir)) {\n try {\n agents.push(\n ...readdirSync(agentsDir)\n .filter(f => f.endsWith('.md'))\n .map(f => `agents/${f}`),\n )\n } catch {\n /* ignore */\n }\n }\n\n const commandsDir = join(ccEntry.installPath, 'commands')\n if (existsSync(commandsDir)) {\n try {\n commands.push(\n ...readdirSync(commandsDir)\n .filter(f => f.endsWith('.md'))\n .map(f => `commands/${f}`),\n )\n } catch {\n /* ignore */\n }\n }\n\n const skillsDir = join(ccEntry.installPath, 'skills')\n if (existsSync(skillsDir)) {\n try {\n for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n const skillMd = join(skillsDir, entry.name, 'SKILL.md')\n if (existsSync(skillMd)) {\n skills.push(`skills/${entry.name}/SKILL.md`)\n }\n } else if (entry.isFile() && entry.name.endsWith('.md')) {\n skills.push(`skills/${entry.name}`)\n }\n }\n } catch {\n /* ignore */\n }\n }\n\n return {\n name: pluginName,\n version: meta?.version || ccEntry.version || '1.0.0',\n description: meta?.description || `Claude Code plugin: ${pluginName}`,\n displayName: pluginName,\n author: meta?.author,\n homepage: meta?.homepage,\n repository: meta?.repository,\n license: meta?.license,\n agents,\n commands,\n skills,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Core \u2014 sync a single plugin\n// ---------------------------------------------------------------------------\n\ntype SyncAction = 'installed' | 'updated' | 'skipped'\n\nfunction syncSinglePlugin(\n pluginName: string,\n marketplace: string,\n entry: CCPluginEntry,\n enabled: boolean,\n syncState: CCSyncState | null,\n dryRun: boolean,\n knownMarketplaces: Record<string, CCKnownMarketplace> | null,\n): SyncAction {\n const targetPath = join(MINTO_PLUGINS_DIR, pluginName)\n const ccSyncPath = join(targetPath, '.cc-sync.json')\n\n // Conflict check: plugin exists without .cc-sync.json \u2192 manually installed, skip\n if (existsSync(targetPath) && !existsSync(ccSyncPath)) {\n return 'skipped'\n }\n\n // Already synced and up to date?\n if (existsSync(ccSyncPath)) {\n try {\n const existing = JSON.parse(readFileSync(ccSyncPath, 'utf-8'))\n if (\n existing.version === entry.version &&\n existing.gitCommitSha === entry.gitCommitSha\n ) {\n return 'skipped'\n }\n } catch {\n /* re-sync on corrupt file */\n }\n }\n\n const isUpdate = existsSync(targetPath)\n\n if (dryRun) {\n return isUpdate ? 'updated' : 'installed'\n }\n\n // Clear target for update\n if (isUpdate) {\n rmSync(targetPath, { recursive: true, force: true })\n }\n\n // Copy from CC cache\n copyPluginFromCache(entry.installPath, targetPath)\n\n // Generate plugin.json in .minto-plugin/ (highest priority for loadManifest)\n const meta = loadMarketplacePluginMeta(marketplace, pluginName)\n const manifest = generatePluginManifest(pluginName, marketplace, entry, meta)\n const mintoPluginDir = join(targetPath, '.minto-plugin')\n mkdirSync(mintoPluginDir, { recursive: true })\n writeFileSync(\n join(mintoPluginDir, 'plugin.json'),\n JSON.stringify(manifest, null, 2),\n 'utf-8',\n )\n\n // Write .marketplace-meta.json with real source info when available\n const realSource = resolveMarketplaceSource(marketplace, knownMarketplaces)\n writeFileSync(\n join(targetPath, '.marketplace-meta.json'),\n JSON.stringify(\n {\n marketplace,\n plugin: pluginName,\n installedAt: new Date().toISOString(),\n source: realSource ?? { source: 'claude-code' },\n ...(realSource ? { syncedFrom: 'claude-code' } : {}),\n },\n null,\n 2,\n ),\n 'utf-8',\n )\n\n // Write .cc-sync.json\n writeFileSync(\n join(targetPath, '.cc-sync.json'),\n JSON.stringify(\n {\n name: pluginName,\n version: entry.version,\n gitCommitSha: entry.gitCommitSha,\n marketplace,\n syncedAt: new Date().toISOString(),\n source: entry.installPath,\n },\n null,\n 2,\n ),\n 'utf-8',\n )\n\n // Write .plugin-config.json (enabled state)\n writeFileSync(\n join(targetPath, '.plugin-config.json'),\n JSON.stringify({ enabled }, null, 2),\n 'utf-8',\n )\n\n return isUpdate ? 'updated' : 'installed'\n}\n\n// ---------------------------------------------------------------------------\n// Public \u2014 full sync\n// ---------------------------------------------------------------------------\n\nexport async function syncFromClaudeCode(\n options: SyncOptions = {},\n): Promise<SyncResult> {\n const { force = false, clean = false, dryRun = false, onProgress } = options\n\n const result: SyncResult = {\n installed: [],\n updated: [],\n skipped: [],\n failed: [],\n cleaned: [],\n total: 0,\n marketplaces: { registered: [], skipped: [], failed: [] },\n }\n\n // Load CC data\n const registry = loadCCRegistry()\n if (!registry) {\n return result\n }\n\n const settings = loadCCSettings()\n const enabledPlugins = settings.enabledPlugins || {}\n const syncState = force ? null : loadSyncState()\n const knownMarketplaces = loadCCKnownMarketplaces()\n\n // Ensure plugins directory\n if (!existsSync(MINTO_PLUGINS_DIR)) {\n mkdirSync(MINTO_PLUGINS_DIR, { recursive: true })\n }\n\n // Migrate: promote root plugin.json \u2192 .minto-plugin/plugin.json for older syncs\n try {\n for (const dir of readdirSync(MINTO_PLUGINS_DIR, { withFileTypes: true })) {\n if (!dir.isDirectory()) continue\n const pluginDir = join(MINTO_PLUGINS_DIR, dir.name)\n const rootManifest = join(pluginDir, 'plugin.json')\n const mintoManifest = join(pluginDir, '.minto-plugin', 'plugin.json')\n const ccSyncMarker = join(pluginDir, '.cc-sync.json')\n if (\n existsSync(ccSyncMarker) &&\n existsSync(rootManifest) &&\n !existsSync(mintoManifest)\n ) {\n mkdirSync(join(pluginDir, '.minto-plugin'), { recursive: true })\n cpSync(rootManifest, mintoManifest)\n }\n }\n } catch {\n /* non-fatal */\n }\n\n onProgress?.('Scanning Claude Code registry...')\n\n // Process each CC plugin\n const pluginKeys = Object.keys(registry.plugins)\n result.total = pluginKeys.length\n\n for (const pluginKey of pluginKeys) {\n // Parse \"name@marketplace\"\n const atIdx = pluginKey.indexOf('@')\n if (atIdx === -1) continue\n const pluginName = pluginKey.slice(0, atIdx)\n const marketplace = pluginKey.slice(atIdx + 1)\n\n // Get the user-scope entry (prefer user over project)\n const entries = registry.plugins[pluginKey]\n const entry = entries.find(e => e.scope === 'user') || entries[0]\n if (!entry) continue\n\n const enabled = enabledPlugins[pluginKey] !== false\n\n try {\n onProgress?.(\n existsSync(join(MINTO_PLUGINS_DIR, pluginName))\n ? `Updating ${pluginName}...`\n : `Installing ${pluginName}...`,\n )\n\n const action = syncSinglePlugin(\n pluginName,\n marketplace,\n entry,\n enabled,\n syncState,\n dryRun,\n knownMarketplaces,\n )\n\n switch (action) {\n case 'installed':\n result.installed.push(pluginName)\n break\n case 'updated':\n result.updated.push(pluginName)\n break\n case 'skipped':\n result.skipped.push(pluginName)\n break\n }\n } catch (err) {\n result.failed.push({\n name: pluginName,\n error: err instanceof Error ? err.message : String(err),\n })\n }\n }\n\n // Clean orphans: CC-synced plugins that are no longer in CC registry\n if (clean && !dryRun && existsSync(MINTO_PLUGINS_DIR)) {\n const ccPluginNames = new Set(\n pluginKeys.map(k => k.slice(0, k.indexOf('@'))),\n )\n\n for (const dir of readdirSync(MINTO_PLUGINS_DIR)) {\n const pluginPath = join(MINTO_PLUGINS_DIR, dir)\n const ccSyncPath = join(pluginPath, '.cc-sync.json')\n\n if (!existsSync(ccSyncPath)) continue // not CC-synced\n if (ccPluginNames.has(dir)) continue // still in CC\n\n rmSync(pluginPath, { recursive: true, force: true })\n result.cleaned.push(dir)\n }\n }\n\n // Sync marketplaces from CC \u2192 Minto registry (non-blocking)\n try {\n onProgress?.('Syncing marketplaces...')\n result.marketplaces = syncMarketplaces(\n knownMarketplaces,\n dryRun,\n onProgress,\n )\n } catch {\n // Never block plugin sync if marketplace sync fails\n }\n\n // Save sync state\n if (!dryRun) {\n const registryStat = statSync(CC_REGISTRY_PATH)\n const newState: CCSyncState = {\n lastSyncedAt: new Date().toISOString(),\n lastRegistryModified: registryStat.mtime.toISOString(),\n plugins: {},\n }\n\n // Rebuild state from what's now on disk\n if (existsSync(MINTO_PLUGINS_DIR)) {\n for (const dir of readdirSync(MINTO_PLUGINS_DIR)) {\n const ccSyncPath = join(MINTO_PLUGINS_DIR, dir, '.cc-sync.json')\n if (!existsSync(ccSyncPath)) continue\n try {\n const meta = JSON.parse(readFileSync(ccSyncPath, 'utf-8'))\n newState.plugins[dir] = {\n version: meta.version,\n gitCommitSha: meta.gitCommitSha,\n syncedAt: meta.syncedAt,\n marketplace: meta.marketplace,\n }\n } catch {\n /* ignore corrupt */\n }\n }\n }\n\n saveSyncState(newState)\n }\n\n return result\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }