@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/skillLoader.ts"],
4
- "sourcesContent": ["/**\n * Skill Loader\n *\n * Progressive disclosure system for loading skills from plugins and standalone directories.\n * Implements Claude Code skill specification for plugin and standalone skills.\n *\n * Directory Priority (later overrides earlier):\n * 1. Plugin skills\n * 2. ~/.minto/skills/ (user directory)\n * 3. ./.minto/skills/ (project directory - highest priority)\n *\n * Supports two file patterns:\n * - skill-name/SKILL.md (subdirectory pattern)\n * - skill-name.md (flat file pattern)\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from 'fs'\nimport { join, basename, dirname } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { LoadedSkill, SkillConfig } from '../types/plugin'\nimport { loadAllPlugins } from './pluginLoader'\nimport { getCwd } from './state'\n\n/**\n * In-memory cache for loaded skills\n * Maps skill name to skill object\n */\nlet skillsCache: Map<string, LoadedSkill> | null = null\n\n/**\n * Cache for fully-loaded skill content\n * Maps skill name to full markdown content\n */\nconst contentCache = new Map<string, string>()\n\n/**\n * Parse a skill file and extract configuration\n * Supports Claude Code skill specification frontmatter fields\n */\nfunction parseSkillFile(\n filePath: string,\n source: 'user' | 'project',\n): LoadedSkill | null {\n try {\n if (!existsSync(filePath)) return null\n\n const fileContent = readFileSync(filePath, 'utf-8')\n const { data: frontmatter, content } = matter(fileContent)\n\n // Determine skill name from frontmatter or filename\n const fileName = basename(filePath, '.md')\n const name =\n frontmatter.name ||\n (fileName === 'SKILL' ? basename(dirname(filePath)) : fileName)\n\n // Parse Claude Code spec fields\n const config: SkillConfig = {\n name,\n description: frontmatter.description || '',\n argumentHint: frontmatter['argument-hint'] || frontmatter.argumentHint,\n disableModelInvocation:\n frontmatter['disable-model-invocation'] ??\n frontmatter.disableModelInvocation,\n userInvocable:\n frontmatter['user-invocable'] ?? frontmatter.userInvocable ?? true,\n allowedTools: parseStringOrArray(\n frontmatter['allowed-tools'] || frontmatter.allowedTools,\n ),\n model: frontmatter.model,\n context: frontmatter.context,\n agent: frontmatter.agent,\n content: content.trim(),\n }\n\n return {\n name,\n filePath,\n config,\n pluginName: 'standalone',\n source,\n }\n } catch (error) {\n console.warn(`Failed to parse skill file ${filePath}:`, error)\n return null\n }\n}\n\n/**\n * Parse a value that could be a string, array, or comma-separated string\n */\nfunction parseStringOrArray(value: unknown): string[] | undefined {\n if (!value) return undefined\n if (Array.isArray(value)) return value.map(String)\n if (typeof value === 'string') {\n return value.split(',').map(s => s.trim())\n }\n return undefined\n}\n\n/**\n * Scan a standalone skills directory\n * Supports both patterns:\n * - skill-name/SKILL.md (subdirectory pattern)\n * - skill-name.md (flat file pattern)\n */\nfunction scanStandaloneSkillsDirectory(\n dirPath: string,\n source: 'user' | 'project',\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n\n if (!existsSync(dirPath)) return skills\n\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true })\n\n for (const entry of entries) {\n const entryPath = join(dirPath, entry.name)\n\n if (entry.isDirectory()) {\n // Pattern 1: skill-name/SKILL.md\n const skillMdPath = join(entryPath, 'SKILL.md')\n if (existsSync(skillMdPath)) {\n const skill = parseSkillFile(skillMdPath, source)\n if (skill) skills.push(skill)\n }\n } else if (entry.name.endsWith('.md') && entry.name !== 'README.md') {\n // Pattern 2: skill-name.md\n const skill = parseSkillFile(entryPath, source)\n if (skill) skills.push(skill)\n }\n }\n } catch (error) {\n console.warn(`Failed to scan skills directory ${dirPath}:`, error)\n }\n\n return skills\n}\n\n/**\n * Load all standalone skills from user and project directories\n */\nfunction loadStandaloneSkills(): LoadedSkill[] {\n const home = homedir()\n const cwd = getCwd()\n\n const userSkillsDir = join(home, '.minto', 'skills')\n const projectSkillsDir = join(cwd, '.minto', 'skills')\n\n const userSkills = scanStandaloneSkillsDirectory(userSkillsDir, 'user')\n const projectSkills = scanStandaloneSkillsDirectory(\n projectSkillsDir,\n 'project',\n )\n\n return [...userSkills, ...projectSkills]\n}\n\n/**\n * Load all skills from plugins and standalone directories\n * Uses progressive disclosure - only loads metadata (name, description)\n * Content is lazy-loaded when needed\n *\n * Priority: plugin < user < project (later overrides earlier)\n */\nexport function loadAllSkills(): LoadedSkill[] {\n // Return cached skills if available\n if (skillsCache !== null) {\n return Array.from(skillsCache.values())\n }\n\n const pluginSkills: LoadedSkill[] = []\n const plugins = loadAllPlugins()\n\n // Collect all skills from all plugins\n for (const plugin of plugins) {\n if (!plugin.enabled) continue\n\n for (const skill of plugin.skills) {\n // Ensure plugin skills have source field\n pluginSkills.push({\n ...skill,\n source: 'plugin',\n })\n }\n }\n\n // Load standalone skills\n const standaloneSkills = loadStandaloneSkills()\n\n // Build cache map for fast lookups (later entries override earlier ones)\n skillsCache = new Map()\n\n // Add in priority order: plugin < standalone (user < project)\n for (const skill of pluginSkills) {\n skillsCache.set(skill.name, skill)\n }\n for (const skill of standaloneSkills) {\n skillsCache.set(skill.name, skill)\n }\n\n return Array.from(skillsCache.values())\n}\n\n/**\n * Get a specific skill by name\n * Returns undefined if skill not found\n */\nexport function getSkill(name: string): LoadedSkill | undefined {\n // Ensure cache is populated\n if (skillsCache === null) {\n loadAllSkills()\n }\n\n return skillsCache?.get(name)\n}\n\n/**\n * Load the full content of a skill\n * Uses caching to avoid repeated file reads\n */\nexport async function loadSkillContent(skill: LoadedSkill): Promise<string> {\n // Check content cache first\n if (contentCache.has(skill.name)) {\n return contentCache.get(skill.name)!\n }\n\n // If content was already loaded in the skill object, use it\n if (skill.config.content) {\n contentCache.set(skill.name, skill.config.content)\n return skill.config.content\n }\n\n // Otherwise, read from file\n try {\n const fileContent = readFileSync(skill.filePath, 'utf-8')\n const { content } = matter(fileContent)\n const trimmedContent = content.trim()\n\n // Cache the content\n contentCache.set(skill.name, trimmedContent)\n\n // Update the skill object\n skill.config.content = trimmedContent\n\n return trimmedContent\n } catch (error) {\n throw new Error(\n `Failed to load skill content for \"${skill.name}\": ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Search skills by name or description\n * Returns skills matching the query (case-insensitive)\n */\nexport function searchSkills(query: string): LoadedSkill[] {\n const allSkills = loadAllSkills()\n const lowerQuery = query.toLowerCase()\n\n return allSkills.filter(\n skill =>\n skill.name.toLowerCase().includes(lowerQuery) ||\n skill.config.description.toLowerCase().includes(lowerQuery) ||\n skill.pluginName.toLowerCase().includes(lowerQuery),\n )\n}\n\n/**\n * Get skills from a specific plugin\n */\nexport function getSkillsByPlugin(pluginName: string): LoadedSkill[] {\n const allSkills = loadAllSkills()\n return allSkills.filter(skill => skill.pluginName === pluginName)\n}\n\n/**\n * Clear the skills cache (useful for hot-reloading)\n */\nexport function clearSkillsCache(): void {\n skillsCache = null\n contentCache.clear()\n}\n\n/**\n * Get count of available skills\n */\nexport function getSkillCount(): number {\n const skills = loadAllSkills()\n return skills.length\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Skill Loader\n *\n * Progressive disclosure system for loading skills from plugins and standalone directories.\n * Implements Claude Code skill specification for plugin and standalone skills.\n *\n * Directory Priority (later overrides earlier):\n * 1. Plugin skills\n * 2. ~/.minto/skills/ (user directory)\n * 3. ./.minto/skills/ (project directory - highest priority)\n *\n * Supports two file patterns:\n * - skill-name/SKILL.md (subdirectory pattern)\n * - skill-name.md (flat file pattern)\n */\n\nimport { existsSync, readFileSync, readdirSync, statSync } from 'fs'\nimport { join, basename, dirname } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { LoadedSkill, SkillConfig, SkillHookDefinition } from '../types/plugin'\nimport { loadAllPlugins } from './pluginLoader'\nimport { getCwd } from './state'\n\n/**\n * In-memory cache for loaded skills\n * Maps skill name to skill object\n */\nlet skillsCache: Map<string, LoadedSkill> | null = null\n\n/**\n * Cache for fully-loaded skill content\n * Maps skill name to full markdown content\n */\nconst contentCache = new Map<string, string>()\n\n/**\n * Parse a skill file and extract configuration\n * Supports Claude Code skill specification frontmatter fields\n */\nfunction parseSkillFile(\n filePath: string,\n source: 'user' | 'project',\n): LoadedSkill | null {\n try {\n if (!existsSync(filePath)) return null\n\n const fileContent = readFileSync(filePath, 'utf-8')\n const { data: frontmatter, content } = matter(fileContent)\n\n // Determine skill name from frontmatter or filename\n const fileName = basename(filePath, '.md')\n const name =\n frontmatter.name ||\n (fileName === 'SKILL' ? basename(dirname(filePath)) : fileName)\n\n // Parse hooks from frontmatter\n const hooks = parseSkillHooks(frontmatter.hooks)\n\n // Parse Claude Code spec fields\n const config: SkillConfig = {\n name,\n description: frontmatter.description || '',\n argumentHint: frontmatter['argument-hint'] || frontmatter.argumentHint,\n disableModelInvocation:\n frontmatter['disable-model-invocation'] ??\n frontmatter.disableModelInvocation,\n userInvocable:\n frontmatter['user-invocable'] ?? frontmatter.userInvocable ?? true,\n allowedTools: parseStringOrArray(\n frontmatter['allowed-tools'] || frontmatter.allowedTools,\n ),\n model: frontmatter.model,\n context: frontmatter.context,\n agent: frontmatter.agent,\n ...(hooks?.length && { hooks }),\n ...(frontmatter.license && { license: frontmatter.license }),\n ...(frontmatter.compatibility && {\n compatibility: frontmatter.compatibility,\n }),\n ...(frontmatter.metadata && { metadata: frontmatter.metadata }),\n content: content.trim(),\n }\n\n return {\n name,\n filePath,\n config,\n pluginName: 'standalone',\n source,\n }\n } catch (error) {\n console.warn(`Failed to parse skill file ${filePath}:`, error)\n return null\n }\n}\n\n/**\n * Parse skill-level hooks from frontmatter\n */\nfunction parseSkillHooks(hooks: unknown): SkillHookDefinition[] | undefined {\n if (!hooks) return undefined\n if (!Array.isArray(hooks)) return undefined\n\n const parsed: SkillHookDefinition[] = []\n for (const h of hooks) {\n if (!h || typeof h !== 'object') continue\n if (!h.event) continue\n parsed.push({\n event: h.event,\n ...(h.matcher && { matcher: h.matcher }),\n ...(h.type && { type: h.type }),\n ...(h.command && { command: h.command }),\n ...(h.prompt && { prompt: h.prompt }),\n ...(h.timeout && { timeout: Number(h.timeout) }),\n })\n }\n return parsed.length > 0 ? parsed : undefined\n}\n\n/**\n * Parse a value that could be a string, array, or comma-separated string\n */\nfunction parseStringOrArray(value: unknown): string[] | undefined {\n if (!value) return undefined\n if (Array.isArray(value)) return value.map(String)\n if (typeof value === 'string') {\n return value.split(',').map(s => s.trim())\n }\n return undefined\n}\n\n/**\n * Scan a standalone skills directory\n * Supports both patterns:\n * - skill-name/SKILL.md (subdirectory pattern)\n * - skill-name.md (flat file pattern)\n */\nfunction scanStandaloneSkillsDirectory(\n dirPath: string,\n source: 'user' | 'project',\n): LoadedSkill[] {\n const skills: LoadedSkill[] = []\n\n if (!existsSync(dirPath)) return skills\n\n try {\n const entries = readdirSync(dirPath, { withFileTypes: true })\n\n for (const entry of entries) {\n const entryPath = join(dirPath, entry.name)\n\n if (entry.isDirectory()) {\n // Pattern 1: skill-name/SKILL.md\n const skillMdPath = join(entryPath, 'SKILL.md')\n if (existsSync(skillMdPath)) {\n const skill = parseSkillFile(skillMdPath, source)\n if (skill) skills.push(skill)\n }\n } else if (entry.name.endsWith('.md') && entry.name !== 'README.md') {\n // Pattern 2: skill-name.md\n const skill = parseSkillFile(entryPath, source)\n if (skill) skills.push(skill)\n }\n }\n } catch (error) {\n console.warn(`Failed to scan skills directory ${dirPath}:`, error)\n }\n\n return skills\n}\n\n/**\n * Load all standalone skills from user and project directories\n */\nfunction loadStandaloneSkills(): LoadedSkill[] {\n const home = homedir()\n const cwd = getCwd()\n\n // .claude/ dirs are legacy fallbacks, .minto/ dirs take precedence\n const userClaudeDir = join(home, '.claude', 'skills')\n const userMintoDir = join(home, '.minto', 'skills')\n const projectClaudeDir = join(cwd, '.claude', 'skills')\n const projectMintoDir = join(cwd, '.minto', 'skills')\n\n const userClaudeSkills = scanStandaloneSkillsDirectory(userClaudeDir, 'user')\n const userMintoSkills = scanStandaloneSkillsDirectory(userMintoDir, 'user')\n const projectClaudeSkills = scanStandaloneSkillsDirectory(\n projectClaudeDir,\n 'project',\n )\n const projectMintoSkills = scanStandaloneSkillsDirectory(\n projectMintoDir,\n 'project',\n )\n\n return [\n ...userClaudeSkills,\n ...userMintoSkills,\n ...projectClaudeSkills,\n ...projectMintoSkills,\n ]\n}\n\n/**\n * Load all skills from plugins and standalone directories\n * Uses progressive disclosure - only loads metadata (name, description)\n * Content is lazy-loaded when needed\n *\n * Priority: plugin < user < project (later overrides earlier)\n */\nexport function loadAllSkills(): LoadedSkill[] {\n // Return cached skills if available\n if (skillsCache !== null) {\n return Array.from(skillsCache.values())\n }\n\n const pluginSkills: LoadedSkill[] = []\n const plugins = loadAllPlugins()\n\n // Collect all skills from all plugins\n for (const plugin of plugins) {\n if (!plugin.enabled) continue\n\n for (const skill of plugin.skills) {\n // Ensure plugin skills have source field\n pluginSkills.push({\n ...skill,\n source: 'plugin',\n })\n }\n }\n\n // Load standalone skills\n const standaloneSkills = loadStandaloneSkills()\n\n // Build cache map for fast lookups (later entries override earlier ones)\n skillsCache = new Map()\n\n // Add in priority order: plugin < standalone (user < project)\n // Plugin skills are namespaced as \"pluginName:skillName\"\n for (const skill of pluginSkills) {\n if (skill.pluginName && skill.pluginName !== 'standalone') {\n const namespacedKey = `${skill.pluginName}:${skill.name}`\n skillsCache.set(namespacedKey, skill)\n } else {\n skillsCache.set(skill.name, skill)\n }\n }\n // Standalone skills keep their original name (no namespace)\n for (const skill of standaloneSkills) {\n skillsCache.set(skill.name, skill)\n }\n\n return Array.from(skillsCache.values())\n}\n\n/**\n * Get a specific skill by name\n * Supports both namespaced (\"plugin:skill\") and bare (\"skill\") lookups.\n * Bare names match standalone skills first; if not found, searches plugin skills.\n */\nexport function getSkill(name: string): LoadedSkill | undefined {\n // Ensure cache is populated\n if (skillsCache === null) {\n loadAllSkills()\n }\n\n // Direct match (namespaced \"plugin:skill\" or standalone \"skill\")\n const direct = skillsCache?.get(name)\n if (direct) return direct\n\n // If no colon in name, try to find among plugin skills by bare component name\n if (!name.includes(':')) {\n for (const [key, skill] of skillsCache ?? []) {\n if (key.includes(':') && key.split(':').pop() === name) {\n return skill\n }\n }\n }\n\n return undefined\n}\n\n/**\n * Get the cache key for a skill (namespaced if from a plugin)\n */\nfunction getSkillCacheKey(skill: LoadedSkill): string {\n if (skill.pluginName && skill.pluginName !== 'standalone') {\n return `${skill.pluginName}:${skill.name}`\n }\n return skill.name\n}\n\n/**\n * Load the full content of a skill\n * Uses caching to avoid repeated file reads\n */\nexport async function loadSkillContent(skill: LoadedSkill): Promise<string> {\n const cacheKey = getSkillCacheKey(skill)\n\n // Check content cache first\n if (contentCache.has(cacheKey)) {\n return contentCache.get(cacheKey)!\n }\n\n // If content was already loaded in the skill object, use it\n if (skill.config.content) {\n contentCache.set(cacheKey, skill.config.content)\n return skill.config.content\n }\n\n // Otherwise, read from file\n try {\n const fileContent = readFileSync(skill.filePath, 'utf-8')\n const { content } = matter(fileContent)\n const trimmedContent = content.trim()\n\n // Cache the content\n contentCache.set(cacheKey, trimmedContent)\n\n // Update the skill object\n skill.config.content = trimmedContent\n\n return trimmedContent\n } catch (error) {\n throw new Error(\n `Failed to load skill content for \"${skill.name}\": ${\n error instanceof Error ? error.message : String(error)\n }`,\n )\n }\n}\n\n/**\n * Get all skills with their cache keys (may be namespaced)\n * Returns [key, skill] entries from the cache\n */\nexport function getAllSkillEntries(): [string, LoadedSkill][] {\n if (skillsCache === null) {\n loadAllSkills()\n }\n return Array.from(skillsCache?.entries() ?? [])\n}\n\n/**\n * Search skills by name or description\n * Returns skills matching the query (case-insensitive)\n */\nexport function searchSkills(query: string): LoadedSkill[] {\n const allSkills = loadAllSkills()\n const lowerQuery = query.toLowerCase()\n\n return allSkills.filter(\n skill =>\n skill.name.toLowerCase().includes(lowerQuery) ||\n skill.config.description.toLowerCase().includes(lowerQuery) ||\n skill.pluginName.toLowerCase().includes(lowerQuery),\n )\n}\n\n/**\n * Get skills from a specific plugin\n */\nexport function getSkillsByPlugin(pluginName: string): LoadedSkill[] {\n const allSkills = loadAllSkills()\n return allSkills.filter(skill => skill.pluginName === pluginName)\n}\n\n/**\n * Clear the skills cache (useful for hot-reloading)\n */\nexport function clearSkillsCache(): void {\n skillsCache = null\n contentCache.clear()\n}\n\n/**\n * Get count of available skills\n */\nexport function getSkillCount(): number {\n const skills = loadAllSkills()\n return skills.length\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,52 @@
1
+ function createDefaultState() {
2
+ return { phase: "thinking" };
3
+ }
4
+ const streamingStates = /* @__PURE__ */ new Map([
5
+ ["__main__", createDefaultState()]
6
+ ]);
7
+ const agentContextStack = ["__main__"];
8
+ function getCurrentAgentContext() {
9
+ return agentContextStack[agentContextStack.length - 1] ?? "__main__";
10
+ }
11
+ function pushAgentContext(agentId) {
12
+ agentContextStack.push(agentId);
13
+ if (!streamingStates.has(agentId)) {
14
+ streamingStates.set(agentId, createDefaultState());
15
+ }
16
+ }
17
+ function popAgentContext() {
18
+ if (agentContextStack.length > 1) {
19
+ return agentContextStack.pop();
20
+ }
21
+ return void 0;
22
+ }
23
+ function setStreamingState(state, agentId) {
24
+ const targetId = agentId ?? getCurrentAgentContext();
25
+ const current = streamingStates.get(targetId) ?? createDefaultState();
26
+ streamingStates.set(targetId, { ...current, ...state });
27
+ }
28
+ function resetStreamingState(agentId) {
29
+ const targetId = agentId ?? getCurrentAgentContext();
30
+ streamingStates.set(targetId, createDefaultState());
31
+ }
32
+ function getStreamingState(agentId) {
33
+ const targetId = agentId ?? getCurrentAgentContext();
34
+ return streamingStates.get(targetId) ?? createDefaultState();
35
+ }
36
+ function getMainStreamingState() {
37
+ return streamingStates.get("__main__") ?? createDefaultState();
38
+ }
39
+ function cleanupAgentStreamingState(agentId) {
40
+ streamingStates.delete(agentId);
41
+ }
42
+ export {
43
+ cleanupAgentStreamingState,
44
+ getCurrentAgentContext,
45
+ getMainStreamingState,
46
+ getStreamingState,
47
+ popAgentContext,
48
+ pushAgentContext,
49
+ resetStreamingState,
50
+ setStreamingState
51
+ };
52
+ //# sourceMappingURL=streamingState.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/utils/streamingState.ts"],
4
+ "sourcesContent": ["/**\n * Streaming State Management\n *\n * Extracted from Spinner.tsx to break the layer violation where\n * service-layer code (claude.ts, query.ts) imported from a UI component.\n *\n * Provides per-agent streaming state tracking with hierarchical context support.\n */\n\n// Streaming phases for better UX feedback\nexport type StreamingPhase =\n | 'thinking' // Initial thinking phase\n | 'generating' // Generating response content\n | 'tool_use' // Executing a tool\n | 'waiting' // Waiting for API response\n | 'deep_thinking' // Extended thinking mode (Claude thinking blocks)\n | 'retrying' // API retry in progress\n | 'permission' // Waiting for user permission\n | 'compacting' // Compacting conversation context\n | 'concurrent' // Running concurrent tasks\n\n// Streaming state type definition\nexport interface StreamingStateData {\n phase: StreamingPhase\n toolName?: string\n tokenCount?: number\n chunkCount?: number\n // New fields for enhanced feedback\n retryCount?: number\n maxRetries?: number\n errorName?: string\n concurrentCount?: number\n thinkingMaxTokens?: number\n // Token usage from API (real-time streaming)\n inputTokens?: number\n outputTokens?: number\n // Character counts for approximate token estimation\n sentChars?: number // Characters sent to API (input)\n receivedChars?: number // Characters received from API (output)\n // Thinking timing\n thinkingStartTime?: number\n thinkingDurationMs?: number\n}\n\n// Default state factory\nfunction createDefaultState(): StreamingStateData {\n return { phase: 'thinking' }\n}\n\n// Store streaming state per agent (agentId -> state)\n// '__main__' is used for the main/root agent\nconst streamingStates: Map<string, StreamingStateData> = new Map([\n ['__main__', createDefaultState()],\n])\n\n// Current active agent context (stack to support nesting)\nconst agentContextStack: string[] = ['__main__']\n\n/**\n * Get the current active agent ID\n */\nexport function getCurrentAgentContext(): string {\n return agentContextStack[agentContextStack.length - 1] ?? '__main__'\n}\n\n/**\n * Push a new agent context (when entering a subagent)\n */\nexport function pushAgentContext(agentId: string): void {\n agentContextStack.push(agentId)\n if (!streamingStates.has(agentId)) {\n streamingStates.set(agentId, createDefaultState())\n }\n}\n\n/**\n * Pop the current agent context (when exiting a subagent)\n */\nexport function popAgentContext(): string | undefined {\n if (agentContextStack.length > 1) {\n return agentContextStack.pop()\n }\n return undefined\n}\n\n/**\n * Set streaming state for a specific agent (or current context if not specified)\n */\nexport function setStreamingState(\n state: Partial<StreamingStateData>,\n agentId?: string,\n): void {\n const targetId = agentId ?? getCurrentAgentContext()\n const current = streamingStates.get(targetId) ?? createDefaultState()\n streamingStates.set(targetId, { ...current, ...state })\n}\n\n/**\n * Reset streaming state for a specific agent (or current context if not specified)\n */\nexport function resetStreamingState(agentId?: string): void {\n const targetId = agentId ?? getCurrentAgentContext()\n streamingStates.set(targetId, createDefaultState())\n}\n\n/**\n * Get streaming state for a specific agent (or current context if not specified)\n */\nexport function getStreamingState(agentId?: string): StreamingStateData {\n const targetId = agentId ?? getCurrentAgentContext()\n return streamingStates.get(targetId) ?? createDefaultState()\n}\n\n/**\n * Get streaming state for the main/root agent (used by main Spinner)\n */\nexport function getMainStreamingState(): StreamingStateData {\n return streamingStates.get('__main__') ?? createDefaultState()\n}\n\n/**\n * Clean up streaming state for a completed agent\n */\nexport function cleanupAgentStreamingState(agentId: string): void {\n streamingStates.delete(agentId)\n}\n"],
5
+ "mappings": "AA6CA,SAAS,qBAAyC;AAChD,SAAO,EAAE,OAAO,WAAW;AAC7B;AAIA,MAAM,kBAAmD,oBAAI,IAAI;AAAA,EAC/D,CAAC,YAAY,mBAAmB,CAAC;AACnC,CAAC;AAGD,MAAM,oBAA8B,CAAC,UAAU;AAKxC,SAAS,yBAAiC;AAC/C,SAAO,kBAAkB,kBAAkB,SAAS,CAAC,KAAK;AAC5D;AAKO,SAAS,iBAAiB,SAAuB;AACtD,oBAAkB,KAAK,OAAO;AAC9B,MAAI,CAAC,gBAAgB,IAAI,OAAO,GAAG;AACjC,oBAAgB,IAAI,SAAS,mBAAmB,CAAC;AAAA,EACnD;AACF;AAKO,SAAS,kBAAsC;AACpD,MAAI,kBAAkB,SAAS,GAAG;AAChC,WAAO,kBAAkB,IAAI;AAAA,EAC/B;AACA,SAAO;AACT;AAKO,SAAS,kBACd,OACA,SACM;AACN,QAAM,WAAW,WAAW,uBAAuB;AACnD,QAAM,UAAU,gBAAgB,IAAI,QAAQ,KAAK,mBAAmB;AACpE,kBAAgB,IAAI,UAAU,EAAE,GAAG,SAAS,GAAG,MAAM,CAAC;AACxD;AAKO,SAAS,oBAAoB,SAAwB;AAC1D,QAAM,WAAW,WAAW,uBAAuB;AACnD,kBAAgB,IAAI,UAAU,mBAAmB,CAAC;AACpD;AAKO,SAAS,kBAAkB,SAAsC;AACtE,QAAM,WAAW,WAAW,uBAAuB;AACnD,SAAO,gBAAgB,IAAI,QAAQ,KAAK,mBAAmB;AAC7D;AAKO,SAAS,wBAA4C;AAC1D,SAAO,gBAAgB,IAAI,UAAU,KAAK,mBAAmB;AAC/D;AAKO,SAAS,2BAA2B,SAAuB;AAChE,kBAAgB,OAAO,OAAO;AAChC;",
6
+ "names": []
7
+ }
@@ -50,10 +50,7 @@ async function substituteVariables(content, args, context = {}) {
50
50
  }
51
51
  }
52
52
  } else {
53
- result = result.replace(
54
- /!\`([^`]+)\`/g,
55
- "(dynamic commands disabled)"
56
- );
53
+ result = result.replace(/!\`([^`]+)\`/g, "(dynamic commands disabled)");
57
54
  }
58
55
  return result;
59
56
  }
@@ -86,7 +83,9 @@ function extractSubstitutionPatterns(content) {
86
83
  for (const match of cmdMatches) {
87
84
  patterns.commands.push(match[1]);
88
85
  }
89
- patterns.indexedArgs = [...new Set(patterns.indexedArgs)].sort((a, b) => a - b);
86
+ patterns.indexedArgs = [...new Set(patterns.indexedArgs)].sort(
87
+ (a, b) => a - b
88
+ );
90
89
  patterns.variables = [...new Set(patterns.variables)];
91
90
  return patterns;
92
91
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/stringSubstitution.ts"],
4
- "sourcesContent": ["/**\n * String Substitution Engine\n *\n * Implements Claude Code skill specification for variable substitution.\n * Supports the following patterns:\n *\n * - $ARGUMENTS - All arguments as a single string\n * - $ARGUMENTS[N] - Indexed argument (0-based)\n * - $N - Shorthand for $ARGUMENTS[N]\n * - ${VARIABLE_NAME} - Environment variable or context variable\n * - !`command` - Dynamic command execution (with security controls)\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\n\nconst execAsync = promisify(exec)\n\n/**\n * Context for string substitution\n */\nexport interface SubstitutionContext {\n sessionId?: string\n cwd?: string\n env?: Record<string, string>\n /**\n * Allow dynamic command execution (!`command`)\n * Default: false (security consideration)\n */\n allowDynamicCommands?: boolean\n /**\n * Timeout for dynamic command execution in milliseconds\n * Default: 10000 (10 seconds)\n */\n commandTimeout?: number\n}\n\n/**\n * Default substitution context\n */\nconst DEFAULT_CONTEXT: Required<SubstitutionContext> = {\n sessionId: '',\n cwd: process.cwd(),\n env: {},\n allowDynamicCommands: false,\n commandTimeout: 10000,\n}\n\n/**\n * Substitute variables in a string\n *\n * @param content - The content to substitute variables in\n * @param args - Arguments string (space-separated)\n * @param context - Substitution context\n * @returns The content with variables substituted\n */\nexport async function substituteVariables(\n content: string,\n args: string,\n context: SubstitutionContext = {},\n): Promise<string> {\n const ctx = { ...DEFAULT_CONTEXT, ...context }\n let result = content\n const argValues = args.trim() ? args.trim().split(/\\s+/) : []\n\n // 1. $ARGUMENTS - All arguments as a single string\n // Use negative lookahead to avoid matching $ARGUMENTS[N]\n result = result.replace(/\\$ARGUMENTS(?!\\[)/g, args)\n\n // 2. $ARGUMENTS[N] - Indexed argument (0-based)\n result = result.replace(/\\$ARGUMENTS\\[(\\d+)\\]/g, (_, indexStr) => {\n const index = parseInt(indexStr, 10)\n return argValues[index] ?? ''\n })\n\n // 3. $N - Shorthand for indexed argument (0-based)\n // Use negative lookahead to avoid matching multi-digit or $ARGUMENTS\n result = result.replace(/\\$(\\d+)(?!\\d)/g, (_, indexStr) => {\n const index = parseInt(indexStr, 10)\n return argValues[index] ?? ''\n })\n\n // 4. ${VARIABLE_NAME} - Context and environment variables\n result = result.replace(/\\$\\{([A-Z_][A-Z0-9_]*)\\}/gi, (_, varName) => {\n // Built-in context variables (Claude Code spec)\n switch (varName.toUpperCase()) {\n case 'CLAUDE_SESSION_ID':\n case 'SESSION_ID':\n return ctx.sessionId || ''\n case 'CWD':\n case 'PWD':\n return ctx.cwd\n default:\n // Check custom context env first, then process.env\n return ctx.env[varName] ?? process.env[varName] ?? ''\n }\n })\n\n // 5. !`command` - Dynamic command execution\n // Only execute if explicitly allowed (security consideration)\n if (ctx.allowDynamicCommands) {\n const commandPattern = /!\\`([^`]+)\\`/g\n const matches = [...result.matchAll(commandPattern)]\n\n for (const match of matches) {\n const command = match[1]\n try {\n const { stdout } = await execAsync(command, {\n timeout: ctx.commandTimeout,\n cwd: ctx.cwd,\n })\n result = result.replace(match[0], stdout.trim())\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n result = result.replace(match[0], `(error: ${errorMessage})`)\n }\n }\n } else {\n // Replace !`command` with placeholder when not allowed\n result = result.replace(\n /!\\`([^`]+)\\`/g,\n '(dynamic commands disabled)',\n )\n }\n\n return result\n}\n\n/**\n * Check if a string contains substitution patterns\n * Useful for optimization - skip substitution if no patterns present\n */\nexport function hasSubstitutionPatterns(content: string): boolean {\n return /\\$(?:ARGUMENTS|\\d+|\\{[A-Z_][A-Z0-9_]*\\})|!\\`/.test(content)\n}\n\n/**\n * Extract all substitution patterns from a string\n * Useful for validation and documentation\n */\nexport function extractSubstitutionPatterns(\n content: string,\n): {\n arguments: string[]\n indexedArgs: number[]\n variables: string[]\n commands: string[]\n} {\n const patterns = {\n arguments: [] as string[],\n indexedArgs: [] as number[],\n variables: [] as string[],\n commands: [] as string[],\n }\n\n // $ARGUMENTS\n if (/\\$ARGUMENTS(?!\\[)/.test(content)) {\n patterns.arguments.push('$ARGUMENTS')\n }\n\n // $ARGUMENTS[N]\n const argIndexMatches = content.matchAll(/\\$ARGUMENTS\\[(\\d+)\\]/g)\n for (const match of argIndexMatches) {\n patterns.indexedArgs.push(parseInt(match[1], 10))\n }\n\n // $N\n const shortIndexMatches = content.matchAll(/\\$(\\d+)(?!\\d)/g)\n for (const match of shortIndexMatches) {\n patterns.indexedArgs.push(parseInt(match[1], 10))\n }\n\n // ${VARIABLE}\n const varMatches = content.matchAll(/\\$\\{([A-Z_][A-Z0-9_]*)\\}/gi)\n for (const match of varMatches) {\n patterns.variables.push(match[1])\n }\n\n // !`command`\n const cmdMatches = content.matchAll(/!\\`([^`]+)\\`/g)\n for (const match of cmdMatches) {\n patterns.commands.push(match[1])\n }\n\n // Deduplicate indexed args\n patterns.indexedArgs = [...new Set(patterns.indexedArgs)].sort((a, b) => a - b)\n patterns.variables = [...new Set(patterns.variables)]\n\n return patterns\n}\n\n/**\n * Validate arguments against expected patterns\n * Returns error message if validation fails, null if valid\n */\nexport function validateArguments(\n args: string,\n patterns: ReturnType<typeof extractSubstitutionPatterns>,\n): string | null {\n const argValues = args.trim() ? args.trim().split(/\\s+/) : []\n const maxIndex = Math.max(...patterns.indexedArgs, -1)\n\n if (maxIndex >= 0 && argValues.length <= maxIndex) {\n return `Expected at least ${maxIndex + 1} argument(s), got ${argValues.length}`\n }\n\n return null\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * String Substitution Engine\n *\n * Implements Claude Code skill specification for variable substitution.\n * Supports the following patterns:\n *\n * - $ARGUMENTS - All arguments as a single string\n * - $ARGUMENTS[N] - Indexed argument (0-based)\n * - $N - Shorthand for $ARGUMENTS[N]\n * - ${VARIABLE_NAME} - Environment variable or context variable\n * - !`command` - Dynamic command execution (with security controls)\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\n\nconst execAsync = promisify(exec)\n\n/**\n * Context for string substitution\n */\nexport interface SubstitutionContext {\n sessionId?: string\n cwd?: string\n env?: Record<string, string>\n /**\n * Allow dynamic command execution (!`command`)\n * Default: false (security consideration)\n */\n allowDynamicCommands?: boolean\n /**\n * Timeout for dynamic command execution in milliseconds\n * Default: 10000 (10 seconds)\n */\n commandTimeout?: number\n}\n\n/**\n * Default substitution context\n */\nconst DEFAULT_CONTEXT: Required<SubstitutionContext> = {\n sessionId: '',\n cwd: process.cwd(),\n env: {},\n allowDynamicCommands: false,\n commandTimeout: 10000,\n}\n\n/**\n * Substitute variables in a string\n *\n * @param content - The content to substitute variables in\n * @param args - Arguments string (space-separated)\n * @param context - Substitution context\n * @returns The content with variables substituted\n */\nexport async function substituteVariables(\n content: string,\n args: string,\n context: SubstitutionContext = {},\n): Promise<string> {\n const ctx = { ...DEFAULT_CONTEXT, ...context }\n let result = content\n const argValues = args.trim() ? args.trim().split(/\\s+/) : []\n\n // 1. $ARGUMENTS - All arguments as a single string\n // Use negative lookahead to avoid matching $ARGUMENTS[N]\n result = result.replace(/\\$ARGUMENTS(?!\\[)/g, args)\n\n // 2. $ARGUMENTS[N] - Indexed argument (0-based)\n result = result.replace(/\\$ARGUMENTS\\[(\\d+)\\]/g, (_, indexStr) => {\n const index = parseInt(indexStr, 10)\n return argValues[index] ?? ''\n })\n\n // 3. $N - Shorthand for indexed argument (0-based)\n // Use negative lookahead to avoid matching multi-digit or $ARGUMENTS\n result = result.replace(/\\$(\\d+)(?!\\d)/g, (_, indexStr) => {\n const index = parseInt(indexStr, 10)\n return argValues[index] ?? ''\n })\n\n // 4. ${VARIABLE_NAME} - Context and environment variables\n result = result.replace(/\\$\\{([A-Z_][A-Z0-9_]*)\\}/gi, (_, varName) => {\n // Built-in context variables (Claude Code spec)\n switch (varName.toUpperCase()) {\n case 'CLAUDE_SESSION_ID':\n case 'SESSION_ID':\n return ctx.sessionId || ''\n case 'CWD':\n case 'PWD':\n return ctx.cwd\n default:\n // Check custom context env first, then process.env\n return ctx.env[varName] ?? process.env[varName] ?? ''\n }\n })\n\n // 5. !`command` - Dynamic command execution\n // Only execute if explicitly allowed (security consideration)\n if (ctx.allowDynamicCommands) {\n const commandPattern = /!\\`([^`]+)\\`/g\n const matches = [...result.matchAll(commandPattern)]\n\n for (const match of matches) {\n const command = match[1]\n try {\n const { stdout } = await execAsync(command, {\n timeout: ctx.commandTimeout,\n cwd: ctx.cwd,\n })\n result = result.replace(match[0], stdout.trim())\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error)\n result = result.replace(match[0], `(error: ${errorMessage})`)\n }\n }\n } else {\n // Replace !`command` with placeholder when not allowed\n result = result.replace(/!\\`([^`]+)\\`/g, '(dynamic commands disabled)')\n }\n\n return result\n}\n\n/**\n * Check if a string contains substitution patterns\n * Useful for optimization - skip substitution if no patterns present\n */\nexport function hasSubstitutionPatterns(content: string): boolean {\n return /\\$(?:ARGUMENTS|\\d+|\\{[A-Z_][A-Z0-9_]*\\})|!\\`/.test(content)\n}\n\n/**\n * Extract all substitution patterns from a string\n * Useful for validation and documentation\n */\nexport function extractSubstitutionPatterns(content: string): {\n arguments: string[]\n indexedArgs: number[]\n variables: string[]\n commands: string[]\n} {\n const patterns = {\n arguments: [] as string[],\n indexedArgs: [] as number[],\n variables: [] as string[],\n commands: [] as string[],\n }\n\n // $ARGUMENTS\n if (/\\$ARGUMENTS(?!\\[)/.test(content)) {\n patterns.arguments.push('$ARGUMENTS')\n }\n\n // $ARGUMENTS[N]\n const argIndexMatches = content.matchAll(/\\$ARGUMENTS\\[(\\d+)\\]/g)\n for (const match of argIndexMatches) {\n patterns.indexedArgs.push(parseInt(match[1], 10))\n }\n\n // $N\n const shortIndexMatches = content.matchAll(/\\$(\\d+)(?!\\d)/g)\n for (const match of shortIndexMatches) {\n patterns.indexedArgs.push(parseInt(match[1], 10))\n }\n\n // ${VARIABLE}\n const varMatches = content.matchAll(/\\$\\{([A-Z_][A-Z0-9_]*)\\}/gi)\n for (const match of varMatches) {\n patterns.variables.push(match[1])\n }\n\n // !`command`\n const cmdMatches = content.matchAll(/!\\`([^`]+)\\`/g)\n for (const match of cmdMatches) {\n patterns.commands.push(match[1])\n }\n\n // Deduplicate indexed args\n patterns.indexedArgs = [...new Set(patterns.indexedArgs)].sort(\n (a, b) => a - b,\n )\n patterns.variables = [...new Set(patterns.variables)]\n\n return patterns\n}\n\n/**\n * Validate arguments against expected patterns\n * Returns error message if validation fails, null if valid\n */\nexport function validateArguments(\n args: string,\n patterns: ReturnType<typeof extractSubstitutionPatterns>,\n): string | null {\n const argValues = args.trim() ? args.trim().split(/\\s+/) : []\n const maxIndex = Math.max(...patterns.indexedArgs, -1)\n\n if (maxIndex >= 0 && argValues.length <= maxIndex) {\n return `Expected at least ${maxIndex + 1} argument(s), got ${argValues.length}`\n }\n\n return null\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -9,11 +9,14 @@ const getCodeStyle = memoize(() => {
9
9
  let currentDir = getCwd();
10
10
  while (currentDir !== parse(currentDir).root) {
11
11
  const stylePath = join(currentDir, PROJECT_FILE);
12
- if (existsSync(stylePath)) {
12
+ const agentsStylePath = join(currentDir, "AGENTS.md");
13
+ const claudeStylePath = join(currentDir, "CLAUDE.md");
14
+ const foundPath = existsSync(stylePath) ? stylePath : existsSync(agentsStylePath) ? agentsStylePath : existsSync(claudeStylePath) ? claudeStylePath : null;
15
+ if (foundPath) {
13
16
  styles.push(
14
- `Contents of ${stylePath}:
17
+ `Contents of ${foundPath}:
15
18
 
16
- ${readFileSync(stylePath, "utf-8")}`
19
+ ${readFileSync(foundPath, "utf-8")}`
17
20
  );
18
21
  }
19
22
  currentDir = dirname(currentDir);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/style.ts"],
4
- "sourcesContent": ["import { existsSync, readFileSync } from 'fs'\nimport { join, parse, dirname } from 'path'\nimport { memoize } from 'lodash-es'\nimport { getCwd } from './state'\nimport { PROJECT_FILE } from '@constants/product'\n\nconst STYLE_PROMPT =\n 'The codebase follows strict style guidelines shown below. All code changes must strictly adhere to these guidelines to maintain consistency and quality.'\n\nexport const getCodeStyle = memoize((): string => {\n const styles: string[] = []\n let currentDir = getCwd()\n\n while (currentDir !== parse(currentDir).root) {\n const stylePath = join(currentDir, PROJECT_FILE)\n if (existsSync(stylePath)) {\n styles.push(\n `Contents of ${stylePath}:\\n\\n${readFileSync(stylePath, 'utf-8')}`,\n )\n }\n currentDir = dirname(currentDir)\n }\n\n if (styles.length === 0) {\n return ''\n }\n\n return `${STYLE_PROMPT}\\n\\n${styles.reverse().join('\\n\\n')}`\n})\n"],
5
- "mappings": "AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,MAAM,OAAO,eAAe;AACrC,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAE7B,MAAM,eACJ;AAEK,MAAM,eAAe,QAAQ,MAAc;AAChD,QAAM,SAAmB,CAAC;AAC1B,MAAI,aAAa,OAAO;AAExB,SAAO,eAAe,MAAM,UAAU,EAAE,MAAM;AAC5C,UAAM,YAAY,KAAK,YAAY,YAAY;AAC/C,QAAI,WAAW,SAAS,GAAG;AACzB,aAAO;AAAA,QACL,eAAe,SAAS;AAAA;AAAA,EAAQ,aAAa,WAAW,OAAO,CAAC;AAAA,MAClE;AAAA,IACF;AACA,iBAAa,QAAQ,UAAU;AAAA,EACjC;AAEA,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,YAAY;AAAA;AAAA,EAAO,OAAO,QAAQ,EAAE,KAAK,MAAM,CAAC;AAC5D,CAAC;",
4
+ "sourcesContent": ["import { existsSync, readFileSync } from 'fs'\nimport { join, parse, dirname } from 'path'\nimport { memoize } from 'lodash-es'\nimport { getCwd } from './state'\nimport { PROJECT_FILE } from '@constants/product'\n\nconst STYLE_PROMPT =\n 'The codebase follows strict style guidelines shown below. All code changes must strictly adhere to these guidelines to maintain consistency and quality.'\n\nexport const getCodeStyle = memoize((): string => {\n const styles: string[] = []\n let currentDir = getCwd()\n\n while (currentDir !== parse(currentDir).root) {\n const stylePath = join(currentDir, PROJECT_FILE)\n const agentsStylePath = join(currentDir, 'AGENTS.md')\n const claudeStylePath = join(currentDir, 'CLAUDE.md')\n const foundPath = existsSync(stylePath)\n ? stylePath\n : existsSync(agentsStylePath)\n ? agentsStylePath\n : existsSync(claudeStylePath)\n ? claudeStylePath\n : null\n if (foundPath) {\n styles.push(\n `Contents of ${foundPath}:\\n\\n${readFileSync(foundPath, 'utf-8')}`,\n )\n }\n currentDir = dirname(currentDir)\n }\n\n if (styles.length === 0) {\n return ''\n }\n\n return `${STYLE_PROMPT}\\n\\n${styles.reverse().join('\\n\\n')}`\n})\n"],
5
+ "mappings": "AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,MAAM,OAAO,eAAe;AACrC,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAE7B,MAAM,eACJ;AAEK,MAAM,eAAe,QAAQ,MAAc;AAChD,QAAM,SAAmB,CAAC;AAC1B,MAAI,aAAa,OAAO;AAExB,SAAO,eAAe,MAAM,UAAU,EAAE,MAAM;AAC5C,UAAM,YAAY,KAAK,YAAY,YAAY;AAC/C,UAAM,kBAAkB,KAAK,YAAY,WAAW;AACpD,UAAM,kBAAkB,KAAK,YAAY,WAAW;AACpD,UAAM,YAAY,WAAW,SAAS,IAClC,YACA,WAAW,eAAe,IACxB,kBACA,WAAW,eAAe,IACxB,kBACA;AACR,QAAI,WAAW;AACb,aAAO;AAAA,QACL,eAAe,SAAS;AAAA;AAAA,EAAQ,aAAa,WAAW,OAAO,CAAC;AAAA,MAClE;AAAA,IACF;AACA,iBAAa,QAAQ,UAAU;AAAA,EACjC;AAEA,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,EACT;AAEA,SAAO,GAAG,YAAY;AAAA;AAAA,EAAO,OAAO,QAAQ,EAAE,KAAK,MAAM,CAAC;AAC5D,CAAC;",
6
6
  "names": []
7
7
  }
@@ -5,6 +5,7 @@ import {
5
5
  } from "./config.js";
6
6
  import { debug as debugLogger } from "./debugLogger.js";
7
7
  import { safeParseJSON } from "./json.js";
8
+ import { ensureProxyBypass, hasSystemProxy } from "./envConfig.js";
8
9
  function interpolateEnvVars(value) {
9
10
  return value.replace(/\$\{([^}]+)\}/g, (match, varName) => {
10
11
  const envValue = process.env[varName.trim()];
@@ -58,18 +59,21 @@ function convertTeamMcpConfig(teamConfig) {
58
59
  enabled: teamConfig.enabled ?? true
59
60
  };
60
61
  }
62
+ const env = teamConfig.env ? ensureProxyBypass(interpolateEnvVarsInObject(teamConfig.env)) : hasSystemProxy() ? { no_proxy: "*", NO_PROXY: "*" } : void 0;
61
63
  return {
62
64
  type: "stdio",
63
65
  command: interpolateEnvVars(teamConfig.command || ""),
64
66
  args: (teamConfig.args || []).map((arg) => interpolateEnvVars(arg)),
65
- env: teamConfig.env ? interpolateEnvVarsInObject(teamConfig.env) : void 0,
67
+ env,
66
68
  enabled: teamConfig.enabled ?? true
67
69
  };
68
70
  }
69
71
  async function fetchTeamConfig(url) {
70
72
  debugLogger.state("TEAM_CONFIG_FETCH_START", { url });
71
73
  try {
72
- const response = await fetch(url);
74
+ const response = await fetch(url, {
75
+ signal: AbortSignal.timeout(3e4)
76
+ });
73
77
  if (!response.ok) {
74
78
  throw new Error(
75
79
  `Failed to fetch config: ${response.status} ${response.statusText}`
@@ -288,16 +292,19 @@ async function installPlugins(pluginNames, targetDir) {
288
292
  const { join } = await import("path");
289
293
  const { homedir } = await import("os");
290
294
  const installDir = targetDir || join(homedir(), ".minto", "plugins");
291
- for (const pluginName of pluginNames) {
295
+ for (const pluginSpec of pluginNames) {
296
+ const atIndex = pluginSpec.indexOf("@");
297
+ const pluginName = atIndex !== -1 ? pluginSpec.slice(0, atIndex) : pluginSpec;
298
+ const marketplaceName = atIndex !== -1 ? pluginSpec.slice(atIndex + 1) : void 0;
292
299
  try {
293
300
  debugLogger.state("TEAM_CONFIG_INSTALL_PLUGIN", {
294
301
  pluginName,
302
+ marketplace: marketplaceName,
295
303
  targetDir: installDir
296
304
  });
297
305
  await installPluginFromMarketplace(
298
306
  pluginName,
299
- void 0,
300
- // Search all marketplaces
307
+ marketplaceName,
301
308
  join(installDir, pluginName)
302
309
  );
303
310
  installed++;
@@ -314,21 +321,23 @@ async function installPlugins(pluginNames, targetDir) {
314
321
  }
315
322
  return { installed, failed, errors };
316
323
  }
317
- async function installRemoteAgents(agentUrls) {
324
+ async function installRemoteAgents(agentUrls, targetDir) {
318
325
  let installed = 0;
319
326
  let failed = 0;
320
327
  const errors = [];
321
328
  const { join } = await import("path");
322
329
  const { homedir } = await import("os");
323
330
  const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
324
- const agentsDir = join(homedir(), ".minto", "agents");
331
+ const agentsDir = targetDir || join(homedir(), ".minto", "agents");
325
332
  if (!existsSync2(agentsDir)) {
326
333
  mkdirSync(agentsDir, { recursive: true });
327
334
  }
328
335
  for (const url of agentUrls) {
329
336
  try {
330
337
  debugLogger.state("TEAM_CONFIG_DOWNLOAD_AGENT", { url });
331
- const response = await fetch(url);
338
+ const response = await fetch(url, {
339
+ signal: AbortSignal.timeout(3e4)
340
+ });
332
341
  if (!response.ok) {
333
342
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
334
343
  }
@@ -353,14 +362,14 @@ async function installRemoteAgents(agentUrls) {
353
362
  }
354
363
  return { installed, failed, errors };
355
364
  }
356
- async function installInlineAgents(agents) {
365
+ async function installInlineAgents(agents, targetDir) {
357
366
  let installed = 0;
358
367
  let failed = 0;
359
368
  const errors = [];
360
369
  const { join } = await import("path");
361
370
  const { homedir } = await import("os");
362
371
  const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
363
- const agentsDir = join(homedir(), ".minto", "agents");
372
+ const agentsDir = targetDir || join(homedir(), ".minto", "agents");
364
373
  if (!existsSync2(agentsDir)) {
365
374
  mkdirSync(agentsDir, { recursive: true });
366
375
  }
@@ -400,17 +409,17 @@ ${agent.systemPrompt}
400
409
  }
401
410
  return { installed, failed, errors };
402
411
  }
403
- async function installTeamHooks(hooks) {
404
- const { join } = await import("path");
412
+ async function installTeamHooks(hooks, targetPath) {
413
+ const { join, dirname } = await import("path");
405
414
  const { homedir } = await import("os");
406
415
  const { writeFileSync, mkdirSync, existsSync: existsSync2, readFileSync: readFileSync2 } = await import("fs");
407
416
  try {
408
417
  debugLogger.state("TEAM_CONFIG_INSTALL_HOOKS", {});
409
- const mintoDir = join(homedir(), ".minto");
410
- if (!existsSync2(mintoDir)) {
411
- mkdirSync(mintoDir, { recursive: true });
418
+ const hooksPath = targetPath || join(homedir(), ".minto", "hooks.json");
419
+ const hooksDir = dirname(hooksPath);
420
+ if (!existsSync2(hooksDir)) {
421
+ mkdirSync(hooksDir, { recursive: true });
412
422
  }
413
- const hooksPath = join(mintoDir, "hooks.json");
414
423
  const hooksConfig = {
415
424
  description: "Team-configured hooks",
416
425
  hooks: {}
@@ -461,6 +470,141 @@ async function installTeamHooks(hooks) {
461
470
  return { installed: false, error: errorMsg };
462
471
  }
463
472
  }
473
+ async function installInlineSkills(skills, targetDir) {
474
+ let installed = 0;
475
+ let failed = 0;
476
+ const errors = [];
477
+ const { join } = await import("path");
478
+ const { homedir } = await import("os");
479
+ const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
480
+ const skillsDir = targetDir || join(homedir(), ".minto", "skills");
481
+ if (!existsSync2(skillsDir)) {
482
+ mkdirSync(skillsDir, { recursive: true });
483
+ }
484
+ for (const skill of skills) {
485
+ try {
486
+ debugLogger.state("TEAM_CONFIG_INSTALL_SKILL", { name: skill.name });
487
+ const frontmatterLines = [
488
+ `name: ${skill.name}`,
489
+ `description: "${skill.description.replace(/"/g, '\\"')}"`
490
+ ];
491
+ if (skill.argumentHint) {
492
+ frontmatterLines.push(`argument-hint: "${skill.argumentHint}"`);
493
+ }
494
+ if (skill.disableModelInvocation !== void 0) {
495
+ frontmatterLines.push(
496
+ `disable-model-invocation: ${skill.disableModelInvocation}`
497
+ );
498
+ }
499
+ if (skill.userInvocable !== void 0) {
500
+ frontmatterLines.push(`user-invocable: ${skill.userInvocable}`);
501
+ }
502
+ if (skill.allowedTools && skill.allowedTools.length > 0) {
503
+ frontmatterLines.push(
504
+ `allowed-tools: ${JSON.stringify(skill.allowedTools)}`
505
+ );
506
+ }
507
+ if (skill.model) {
508
+ frontmatterLines.push(`model: ${skill.model}`);
509
+ }
510
+ if (skill.context) {
511
+ frontmatterLines.push(`context: "${skill.context}"`);
512
+ }
513
+ if (skill.agent) {
514
+ frontmatterLines.push(`agent: "${skill.agent}"`);
515
+ }
516
+ const content = `---
517
+ ${frontmatterLines.join("\n")}
518
+ ---
519
+
520
+ ${skill.content}
521
+ `;
522
+ const filename = `${skill.name}.md`;
523
+ const targetPath = join(skillsDir, filename);
524
+ writeFileSync(targetPath, content, "utf-8");
525
+ installed++;
526
+ debugLogger.state("TEAM_CONFIG_INSTALL_SKILL_SUCCESS", {
527
+ name: skill.name,
528
+ targetPath
529
+ });
530
+ } catch (error) {
531
+ failed++;
532
+ const errorMsg = error instanceof Error ? error.message : String(error);
533
+ errors.push(`${skill.name}: ${errorMsg}`);
534
+ debugLogger.error("TEAM_CONFIG_INSTALL_SKILL_ERROR", {
535
+ name: skill.name,
536
+ error: errorMsg
537
+ });
538
+ }
539
+ }
540
+ return { installed, failed, errors };
541
+ }
542
+ async function installInlineCommands(commands, targetDir) {
543
+ let installed = 0;
544
+ let failed = 0;
545
+ const errors = [];
546
+ const { join } = await import("path");
547
+ const { homedir } = await import("os");
548
+ const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
549
+ const commandsDir = targetDir || join(homedir(), ".minto", "commands");
550
+ if (!existsSync2(commandsDir)) {
551
+ mkdirSync(commandsDir, { recursive: true });
552
+ }
553
+ for (const cmd of commands) {
554
+ try {
555
+ debugLogger.state("TEAM_CONFIG_INSTALL_COMMAND", { name: cmd.name });
556
+ const frontmatterLines = [`name: ${cmd.name}`];
557
+ if (cmd.description) {
558
+ frontmatterLines.push(
559
+ `description: "${cmd.description.replace(/"/g, '\\"')}"`
560
+ );
561
+ }
562
+ if (cmd.aliases && cmd.aliases.length > 0) {
563
+ frontmatterLines.push(`aliases: ${JSON.stringify(cmd.aliases)}`);
564
+ }
565
+ if (cmd.enabled !== void 0) {
566
+ frontmatterLines.push(`enabled: ${cmd.enabled}`);
567
+ }
568
+ if (cmd.hidden !== void 0) {
569
+ frontmatterLines.push(`hidden: ${cmd.hidden}`);
570
+ }
571
+ if (cmd.progressMessage) {
572
+ frontmatterLines.push(`progressMessage: "${cmd.progressMessage}"`);
573
+ }
574
+ if (cmd.argNames && cmd.argNames.length > 0) {
575
+ frontmatterLines.push(`argNames: ${JSON.stringify(cmd.argNames)}`);
576
+ }
577
+ if (cmd.allowedTools && cmd.allowedTools.length > 0) {
578
+ frontmatterLines.push(
579
+ `allowed-tools: ${JSON.stringify(cmd.allowedTools)}`
580
+ );
581
+ }
582
+ const content = `---
583
+ ${frontmatterLines.join("\n")}
584
+ ---
585
+
586
+ ${cmd.content}
587
+ `;
588
+ const filename = `${cmd.name}.md`;
589
+ const targetPath = join(commandsDir, filename);
590
+ writeFileSync(targetPath, content, "utf-8");
591
+ installed++;
592
+ debugLogger.state("TEAM_CONFIG_INSTALL_COMMAND_SUCCESS", {
593
+ name: cmd.name,
594
+ targetPath
595
+ });
596
+ } catch (error) {
597
+ failed++;
598
+ const errorMsg = error instanceof Error ? error.message : String(error);
599
+ errors.push(`${cmd.name}: ${errorMsg}`);
600
+ debugLogger.error("TEAM_CONFIG_INSTALL_COMMAND_ERROR", {
601
+ name: cmd.name,
602
+ error: errorMsg
603
+ });
604
+ }
605
+ }
606
+ return { installed, failed, errors };
607
+ }
464
608
  export {
465
609
  addMarketplaces,
466
610
  applyTeamConfig,
@@ -468,6 +612,8 @@ export {
468
612
  convertTeamModelProfile,
469
613
  fetchTeamConfig,
470
614
  installInlineAgents,
615
+ installInlineCommands,
616
+ installInlineSkills,
471
617
  installPlugins,
472
618
  installRemoteAgents,
473
619
  installTeamHooks,