@within-7/minto 0.3.6 → 0.3.10

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 (238) hide show
  1. package/{cli.js → cli.cjs} +25 -23
  2. package/dist/commands/agents/AgentsCommand.js +459 -655
  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/export.js +673 -93
  13. package/dist/commands/export.js.map +2 -2
  14. package/dist/commands/language.js +110 -0
  15. package/dist/commands/language.js.map +7 -0
  16. package/dist/commands/mcp-interactive.js +419 -217
  17. package/dist/commands/mcp-interactive.js.map +2 -2
  18. package/dist/commands/model.js +415 -66
  19. package/dist/commands/model.js.map +2 -2
  20. package/dist/commands/new.js +56 -0
  21. package/dist/commands/new.js.map +7 -0
  22. package/dist/commands/permissions.js +75 -49
  23. package/dist/commands/permissions.js.map +2 -2
  24. package/dist/commands/plugin.js +882 -185
  25. package/dist/commands/plugin.js.map +3 -3
  26. package/dist/commands/resume.js +251 -16
  27. package/dist/commands/resume.js.map +2 -2
  28. package/dist/commands/sandbox.js +168 -70
  29. package/dist/commands/sandbox.js.map +2 -2
  30. package/dist/commands/sessions.js +224 -0
  31. package/dist/commands/sessions.js.map +7 -0
  32. package/dist/commands/setup.js +596 -109
  33. package/dist/commands/setup.js.map +2 -2
  34. package/dist/commands/stats.js +292 -0
  35. package/dist/commands/stats.js.map +7 -0
  36. package/dist/commands/status.js +75 -7
  37. package/dist/commands/status.js.map +2 -2
  38. package/dist/commands/undo.js +154 -180
  39. package/dist/commands/undo.js.map +2 -2
  40. package/dist/commands.js +6 -0
  41. package/dist/commands.js.map +2 -2
  42. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
  43. package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
  44. package/dist/components/Config.js +9 -8
  45. package/dist/components/Config.js.map +2 -2
  46. package/dist/components/HeaderBar.js +2 -1
  47. package/dist/components/HeaderBar.js.map +2 -2
  48. package/dist/components/Help.js +166 -32
  49. package/dist/components/Help.js.map +2 -2
  50. package/dist/components/HotkeyHelpPanel.js +46 -44
  51. package/dist/components/HotkeyHelpPanel.js.map +2 -2
  52. package/dist/components/InfoPanel/InfoPanel.js +123 -0
  53. package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
  54. package/dist/components/InfoPanel/index.js +5 -0
  55. package/dist/components/InfoPanel/index.js.map +7 -0
  56. package/dist/components/InfoPanel/types.js +1 -0
  57. package/dist/components/InfoPanel/types.js.map +7 -0
  58. package/dist/components/Logo.js +5 -2
  59. package/dist/components/Logo.js.map +2 -2
  60. package/dist/components/MCPServerApprovalDialog.js +6 -5
  61. package/dist/components/MCPServerApprovalDialog.js.map +2 -2
  62. package/dist/components/MCPServerMultiselectDialog.js +5 -4
  63. package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
  64. package/dist/components/MessageSelector.js +4 -3
  65. package/dist/components/MessageSelector.js.map +2 -2
  66. package/dist/components/ModelConfig.js +13 -12
  67. package/dist/components/ModelConfig.js.map +2 -2
  68. package/dist/components/ModelListManager.js +4 -3
  69. package/dist/components/ModelListManager.js.map +2 -2
  70. package/dist/components/ModelSelector/BrandTextInput.js +43 -0
  71. package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
  72. package/dist/components/ModelSelector/ModelSelector.js +419 -501
  73. package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
  74. package/dist/components/ModelSelector/WizardContainer.js +45 -0
  75. package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
  76. package/dist/components/ModelSelector/index.js +1 -3
  77. package/dist/components/ModelSelector/index.js.map +2 -2
  78. package/dist/components/PromptInput.js +77 -44
  79. package/dist/components/PromptInput.js.map +2 -2
  80. package/dist/components/SensitiveFileWarning.js +12 -8
  81. package/dist/components/SensitiveFileWarning.js.map +2 -2
  82. package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
  83. package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
  84. package/dist/components/SimpleSelector/index.js +5 -0
  85. package/dist/components/SimpleSelector/index.js.map +7 -0
  86. package/dist/components/SimpleSelector/types.js +1 -0
  87. package/dist/components/SimpleSelector/types.js.map +7 -0
  88. package/dist/components/StatusOverlayContent.js +21 -0
  89. package/dist/components/StatusOverlayContent.js.map +7 -0
  90. package/dist/components/TabbedListView/ScrollableList.js +117 -0
  91. package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
  92. package/dist/components/TabbedListView/SearchInput.js +23 -0
  93. package/dist/components/TabbedListView/SearchInput.js.map +7 -0
  94. package/dist/components/TabbedListView/TabBar.js +20 -0
  95. package/dist/components/TabbedListView/TabBar.js.map +7 -0
  96. package/dist/components/TabbedListView/TabbedListView.js +246 -0
  97. package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
  98. package/dist/components/TabbedListView/index.js +11 -0
  99. package/dist/components/TabbedListView/index.js.map +7 -0
  100. package/dist/components/TabbedListView/types.js +1 -0
  101. package/dist/components/TabbedListView/types.js.map +7 -0
  102. package/dist/components/TodoChangeBlock.js +6 -5
  103. package/dist/components/TodoChangeBlock.js.map +3 -3
  104. package/dist/components/TodoPanel.js +6 -3
  105. package/dist/components/TodoPanel.js.map +3 -3
  106. package/dist/components/TrustDialog.js +6 -5
  107. package/dist/components/TrustDialog.js.map +2 -2
  108. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
  109. package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
  110. package/dist/constants/macros.js +1 -1
  111. package/dist/constants/macros.js.map +1 -1
  112. package/dist/constants/product.js +2 -2
  113. package/dist/constants/product.js.map +1 -1
  114. package/dist/constants/prompts.js +17 -0
  115. package/dist/constants/prompts.js.map +2 -2
  116. package/dist/constants/toolInputExamples.js +5 -1
  117. package/dist/constants/toolInputExamples.js.map +2 -2
  118. package/dist/core/backupHook.js +29 -0
  119. package/dist/core/backupHook.js.map +7 -0
  120. package/dist/core/config/defaults.js +8 -2
  121. package/dist/core/config/defaults.js.map +2 -2
  122. package/dist/core/config/schema.js +14 -2
  123. package/dist/core/config/schema.js.map +2 -2
  124. package/dist/core/costTracker.js +0 -16
  125. package/dist/core/costTracker.js.map +2 -2
  126. package/dist/core/tokenStatsManager.js +5 -0
  127. package/dist/core/tokenStatsManager.js.map +2 -2
  128. package/dist/cost-tracker.js +0 -16
  129. package/dist/cost-tracker.js.map +2 -2
  130. package/dist/entrypoints/bootstrap.js +56 -0
  131. package/dist/entrypoints/bootstrap.js.map +7 -0
  132. package/dist/entrypoints/cli.js +164 -23
  133. package/dist/entrypoints/cli.js.map +3 -3
  134. package/dist/history.js +75 -15
  135. package/dist/history.js.map +2 -2
  136. package/dist/i18n/index.js +2 -2
  137. package/dist/i18n/index.js.map +2 -2
  138. package/dist/i18n/locales/en.js +582 -1
  139. package/dist/i18n/locales/en.js.map +2 -2
  140. package/dist/i18n/locales/zh-CN.js +582 -1
  141. package/dist/i18n/locales/zh-CN.js.map +2 -2
  142. package/dist/i18n/types.js.map +1 -1
  143. package/dist/index.js +1 -1
  144. package/dist/index.js.map +2 -2
  145. package/dist/messages.js +11 -0
  146. package/dist/messages.js.map +2 -2
  147. package/dist/permissions.js.map +2 -2
  148. package/dist/query.js +9 -0
  149. package/dist/query.js.map +2 -2
  150. package/dist/screens/REPL.js +45 -7
  151. package/dist/screens/REPL.js.map +2 -2
  152. package/dist/services/customCommands.js +44 -16
  153. package/dist/services/customCommands.js.map +2 -2
  154. package/dist/services/plugins/lspServers.js +1 -1
  155. package/dist/services/plugins/lspServers.js.map +2 -2
  156. package/dist/services/plugins/pluginRuntime.js +2 -1
  157. package/dist/services/plugins/pluginRuntime.js.map +2 -2
  158. package/dist/services/plugins/pluginValidation.js +10 -3
  159. package/dist/services/plugins/pluginValidation.js.map +2 -2
  160. package/dist/services/plugins/skillMarketplace.js +16 -8
  161. package/dist/services/plugins/skillMarketplace.js.map +2 -2
  162. package/dist/services/systemReminder.js +17 -6
  163. package/dist/services/systemReminder.js.map +2 -2
  164. package/dist/tools/FileEditTool/FileEditTool.js +7 -0
  165. package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
  166. package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
  167. package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
  168. package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
  169. package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
  170. package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
  171. package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
  172. package/dist/tools/TaskTool/TaskTool.js +179 -1
  173. package/dist/tools/TaskTool/TaskTool.js.map +2 -2
  174. package/dist/tools/TodoWriteTool/prompt.js +21 -0
  175. package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
  176. package/dist/tools/URLFetcherTool/prompt.js +14 -9
  177. package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
  178. package/dist/tools/WebSearchTool/prompt.js +12 -6
  179. package/dist/tools/WebSearchTool/prompt.js.map +2 -2
  180. package/dist/types/PermissionMode.js +30 -1
  181. package/dist/types/PermissionMode.js.map +2 -2
  182. package/dist/types/plugin.js +2 -4
  183. package/dist/types/plugin.js.map +2 -2
  184. package/dist/utils/agentHookExecutor.js +103 -0
  185. package/dist/utils/agentHookExecutor.js.map +7 -0
  186. package/dist/utils/agentLoader.js +272 -32
  187. package/dist/utils/agentLoader.js.map +2 -2
  188. package/dist/utils/agentMemory.js +134 -0
  189. package/dist/utils/agentMemory.js.map +7 -0
  190. package/dist/utils/claudeCodeSync.js +439 -0
  191. package/dist/utils/claudeCodeSync.js.map +7 -0
  192. package/dist/utils/config.js +52 -24
  193. package/dist/utils/config.js.map +2 -2
  194. package/dist/utils/configPaths.js +199 -0
  195. package/dist/utils/configPaths.js.map +7 -0
  196. package/dist/utils/execFileNoThrow.js +2 -1
  197. package/dist/utils/execFileNoThrow.js.map +2 -2
  198. package/dist/utils/historyManager.js +234 -0
  199. package/dist/utils/historyManager.js.map +7 -0
  200. package/dist/utils/marketplaceManager.js +80 -43
  201. package/dist/utils/marketplaceManager.js.map +2 -2
  202. package/dist/utils/messages.js +13 -8
  203. package/dist/utils/messages.js.map +2 -2
  204. package/dist/utils/migration/index.js +37 -0
  205. package/dist/utils/migration/index.js.map +7 -0
  206. package/dist/utils/migration/migrateHistory.js +273 -0
  207. package/dist/utils/migration/migrateHistory.js.map +7 -0
  208. package/dist/utils/migration/migrateTodos.js +323 -0
  209. package/dist/utils/migration/migrateTodos.js.map +7 -0
  210. package/dist/utils/pasteCache.js +309 -0
  211. package/dist/utils/pasteCache.js.map +7 -0
  212. package/dist/utils/pluginInstaller.js +34 -24
  213. package/dist/utils/pluginInstaller.js.map +2 -2
  214. package/dist/utils/pluginLoader.js +54 -28
  215. package/dist/utils/pluginLoader.js.map +2 -2
  216. package/dist/utils/repoFetcher.js +110 -0
  217. package/dist/utils/repoFetcher.js.map +7 -0
  218. package/dist/utils/sessionIndex.js +192 -0
  219. package/dist/utils/sessionIndex.js.map +7 -0
  220. package/dist/utils/sessionTracker.js +170 -0
  221. package/dist/utils/sessionTracker.js.map +7 -0
  222. package/dist/utils/skillLoader.js +103 -5
  223. package/dist/utils/skillLoader.js.map +2 -2
  224. package/dist/utils/stats.js +417 -0
  225. package/dist/utils/stats.js.map +7 -0
  226. package/dist/utils/stringSubstitution.js +106 -0
  227. package/dist/utils/stringSubstitution.js.map +7 -0
  228. package/dist/utils/teamConfig.js +156 -14
  229. package/dist/utils/teamConfig.js.map +2 -2
  230. package/dist/utils/terminal.js +1 -1
  231. package/dist/utils/terminal.js.map +2 -2
  232. package/dist/utils/todoStorage.js +51 -19
  233. package/dist/utils/todoStorage.js.map +2 -2
  234. package/dist/utils/tooling/safeRender.js.map +2 -2
  235. package/dist/version.js +2 -2
  236. package/dist/version.js.map +1 -1
  237. package/package.json +71 -28
  238. package/scripts/{postinstall.js → postinstall.cjs} +1 -1
@@ -288,16 +288,19 @@ async function installPlugins(pluginNames, targetDir) {
288
288
  const { join } = await import("path");
289
289
  const { homedir } = await import("os");
290
290
  const installDir = targetDir || join(homedir(), ".minto", "plugins");
291
- for (const pluginName of pluginNames) {
291
+ for (const pluginSpec of pluginNames) {
292
+ const atIndex = pluginSpec.indexOf("@");
293
+ const pluginName = atIndex !== -1 ? pluginSpec.slice(0, atIndex) : pluginSpec;
294
+ const marketplaceName = atIndex !== -1 ? pluginSpec.slice(atIndex + 1) : void 0;
292
295
  try {
293
296
  debugLogger.state("TEAM_CONFIG_INSTALL_PLUGIN", {
294
297
  pluginName,
298
+ marketplace: marketplaceName,
295
299
  targetDir: installDir
296
300
  });
297
301
  await installPluginFromMarketplace(
298
302
  pluginName,
299
- void 0,
300
- // Search all marketplaces
303
+ marketplaceName,
301
304
  join(installDir, pluginName)
302
305
  );
303
306
  installed++;
@@ -314,14 +317,14 @@ async function installPlugins(pluginNames, targetDir) {
314
317
  }
315
318
  return { installed, failed, errors };
316
319
  }
317
- async function installRemoteAgents(agentUrls) {
320
+ async function installRemoteAgents(agentUrls, targetDir) {
318
321
  let installed = 0;
319
322
  let failed = 0;
320
323
  const errors = [];
321
324
  const { join } = await import("path");
322
325
  const { homedir } = await import("os");
323
326
  const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
324
- const agentsDir = join(homedir(), ".minto", "agents");
327
+ const agentsDir = targetDir || join(homedir(), ".minto", "agents");
325
328
  if (!existsSync2(agentsDir)) {
326
329
  mkdirSync(agentsDir, { recursive: true });
327
330
  }
@@ -353,20 +356,22 @@ async function installRemoteAgents(agentUrls) {
353
356
  }
354
357
  return { installed, failed, errors };
355
358
  }
356
- async function installInlineAgents(agents) {
359
+ async function installInlineAgents(agents, targetDir) {
357
360
  let installed = 0;
358
361
  let failed = 0;
359
362
  const errors = [];
360
363
  const { join } = await import("path");
361
364
  const { homedir } = await import("os");
362
365
  const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
363
- const agentsDir = join(homedir(), ".minto", "agents");
366
+ const agentsDir = targetDir || join(homedir(), ".minto", "agents");
364
367
  if (!existsSync2(agentsDir)) {
365
368
  mkdirSync(agentsDir, { recursive: true });
366
369
  }
367
370
  for (const agent of agents) {
368
371
  try {
369
- debugLogger.state("TEAM_CONFIG_INSTALL_INLINE_AGENT", { name: agent.name });
372
+ debugLogger.state("TEAM_CONFIG_INSTALL_INLINE_AGENT", {
373
+ name: agent.name
374
+ });
370
375
  const tools = agent.tools === "*" ? "*" : JSON.stringify(agent.tools);
371
376
  const content = `---
372
377
  name: ${agent.name}
@@ -398,17 +403,17 @@ ${agent.systemPrompt}
398
403
  }
399
404
  return { installed, failed, errors };
400
405
  }
401
- async function installTeamHooks(hooks) {
402
- const { join } = await import("path");
406
+ async function installTeamHooks(hooks, targetPath) {
407
+ const { join, dirname } = await import("path");
403
408
  const { homedir } = await import("os");
404
409
  const { writeFileSync, mkdirSync, existsSync: existsSync2, readFileSync: readFileSync2 } = await import("fs");
405
410
  try {
406
411
  debugLogger.state("TEAM_CONFIG_INSTALL_HOOKS", {});
407
- const mintoDir = join(homedir(), ".minto");
408
- if (!existsSync2(mintoDir)) {
409
- mkdirSync(mintoDir, { recursive: true });
412
+ const hooksPath = targetPath || join(homedir(), ".minto", "hooks.json");
413
+ const hooksDir = dirname(hooksPath);
414
+ if (!existsSync2(hooksDir)) {
415
+ mkdirSync(hooksDir, { recursive: true });
410
416
  }
411
- const hooksPath = join(mintoDir, "hooks.json");
412
417
  const hooksConfig = {
413
418
  description: "Team-configured hooks",
414
419
  hooks: {}
@@ -459,6 +464,141 @@ async function installTeamHooks(hooks) {
459
464
  return { installed: false, error: errorMsg };
460
465
  }
461
466
  }
467
+ async function installInlineSkills(skills, targetDir) {
468
+ let installed = 0;
469
+ let failed = 0;
470
+ const errors = [];
471
+ const { join } = await import("path");
472
+ const { homedir } = await import("os");
473
+ const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
474
+ const skillsDir = targetDir || join(homedir(), ".minto", "skills");
475
+ if (!existsSync2(skillsDir)) {
476
+ mkdirSync(skillsDir, { recursive: true });
477
+ }
478
+ for (const skill of skills) {
479
+ try {
480
+ debugLogger.state("TEAM_CONFIG_INSTALL_SKILL", { name: skill.name });
481
+ const frontmatterLines = [
482
+ `name: ${skill.name}`,
483
+ `description: "${skill.description.replace(/"/g, '\\"')}"`
484
+ ];
485
+ if (skill.argumentHint) {
486
+ frontmatterLines.push(`argument-hint: "${skill.argumentHint}"`);
487
+ }
488
+ if (skill.disableModelInvocation !== void 0) {
489
+ frontmatterLines.push(
490
+ `disable-model-invocation: ${skill.disableModelInvocation}`
491
+ );
492
+ }
493
+ if (skill.userInvocable !== void 0) {
494
+ frontmatterLines.push(`user-invocable: ${skill.userInvocable}`);
495
+ }
496
+ if (skill.allowedTools && skill.allowedTools.length > 0) {
497
+ frontmatterLines.push(
498
+ `allowed-tools: ${JSON.stringify(skill.allowedTools)}`
499
+ );
500
+ }
501
+ if (skill.model) {
502
+ frontmatterLines.push(`model: ${skill.model}`);
503
+ }
504
+ if (skill.context) {
505
+ frontmatterLines.push(`context: "${skill.context}"`);
506
+ }
507
+ if (skill.agent) {
508
+ frontmatterLines.push(`agent: "${skill.agent}"`);
509
+ }
510
+ const content = `---
511
+ ${frontmatterLines.join("\n")}
512
+ ---
513
+
514
+ ${skill.content}
515
+ `;
516
+ const filename = `${skill.name}.md`;
517
+ const targetPath = join(skillsDir, filename);
518
+ writeFileSync(targetPath, content, "utf-8");
519
+ installed++;
520
+ debugLogger.state("TEAM_CONFIG_INSTALL_SKILL_SUCCESS", {
521
+ name: skill.name,
522
+ targetPath
523
+ });
524
+ } catch (error) {
525
+ failed++;
526
+ const errorMsg = error instanceof Error ? error.message : String(error);
527
+ errors.push(`${skill.name}: ${errorMsg}`);
528
+ debugLogger.error("TEAM_CONFIG_INSTALL_SKILL_ERROR", {
529
+ name: skill.name,
530
+ error: errorMsg
531
+ });
532
+ }
533
+ }
534
+ return { installed, failed, errors };
535
+ }
536
+ async function installInlineCommands(commands, targetDir) {
537
+ let installed = 0;
538
+ let failed = 0;
539
+ const errors = [];
540
+ const { join } = await import("path");
541
+ const { homedir } = await import("os");
542
+ const { writeFileSync, mkdirSync, existsSync: existsSync2 } = await import("fs");
543
+ const commandsDir = targetDir || join(homedir(), ".minto", "commands");
544
+ if (!existsSync2(commandsDir)) {
545
+ mkdirSync(commandsDir, { recursive: true });
546
+ }
547
+ for (const cmd of commands) {
548
+ try {
549
+ debugLogger.state("TEAM_CONFIG_INSTALL_COMMAND", { name: cmd.name });
550
+ const frontmatterLines = [`name: ${cmd.name}`];
551
+ if (cmd.description) {
552
+ frontmatterLines.push(
553
+ `description: "${cmd.description.replace(/"/g, '\\"')}"`
554
+ );
555
+ }
556
+ if (cmd.aliases && cmd.aliases.length > 0) {
557
+ frontmatterLines.push(`aliases: ${JSON.stringify(cmd.aliases)}`);
558
+ }
559
+ if (cmd.enabled !== void 0) {
560
+ frontmatterLines.push(`enabled: ${cmd.enabled}`);
561
+ }
562
+ if (cmd.hidden !== void 0) {
563
+ frontmatterLines.push(`hidden: ${cmd.hidden}`);
564
+ }
565
+ if (cmd.progressMessage) {
566
+ frontmatterLines.push(`progressMessage: "${cmd.progressMessage}"`);
567
+ }
568
+ if (cmd.argNames && cmd.argNames.length > 0) {
569
+ frontmatterLines.push(`argNames: ${JSON.stringify(cmd.argNames)}`);
570
+ }
571
+ if (cmd.allowedTools && cmd.allowedTools.length > 0) {
572
+ frontmatterLines.push(
573
+ `allowed-tools: ${JSON.stringify(cmd.allowedTools)}`
574
+ );
575
+ }
576
+ const content = `---
577
+ ${frontmatterLines.join("\n")}
578
+ ---
579
+
580
+ ${cmd.content}
581
+ `;
582
+ const filename = `${cmd.name}.md`;
583
+ const targetPath = join(commandsDir, filename);
584
+ writeFileSync(targetPath, content, "utf-8");
585
+ installed++;
586
+ debugLogger.state("TEAM_CONFIG_INSTALL_COMMAND_SUCCESS", {
587
+ name: cmd.name,
588
+ targetPath
589
+ });
590
+ } catch (error) {
591
+ failed++;
592
+ const errorMsg = error instanceof Error ? error.message : String(error);
593
+ errors.push(`${cmd.name}: ${errorMsg}`);
594
+ debugLogger.error("TEAM_CONFIG_INSTALL_COMMAND_ERROR", {
595
+ name: cmd.name,
596
+ error: errorMsg
597
+ });
598
+ }
599
+ }
600
+ return { installed, failed, errors };
601
+ }
462
602
  export {
463
603
  addMarketplaces,
464
604
  applyTeamConfig,
@@ -466,6 +606,8 @@ export {
466
606
  convertTeamModelProfile,
467
607
  fetchTeamConfig,
468
608
  installInlineAgents,
609
+ installInlineCommands,
610
+ installInlineSkills,
469
611
  installPlugins,
470
612
  installRemoteAgents,
471
613
  installTeamHooks,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/teamConfig.ts"],
4
- "sourcesContent": ["/**\n * Team Configuration System\n *\n * Enables teams to share a unified Minto configuration via remote URLs.\n * Supports environment variable interpolation and flexible configuration merging.\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport {\n getGlobalConfig,\n saveGlobalConfig,\n ModelProfile,\n ModelPointers,\n McpServerConfig,\n ProviderType,\n} from './config'\nimport { debug as debugLogger } from './debugLogger'\nimport { safeParseJSON } from './json'\n\n/**\n * Team configuration schema\n * Represents a shareable configuration template for teams\n */\nexport type TeamConfig = {\n version: '1.0'\n name: string // Configuration name (e.g., \"Acme Inc. Default Config\")\n description?: string // Optional description\n\n // Model Configuration\n models?: {\n profiles?: TeamModelProfile[]\n pointers?: Partial<ModelPointers> // Default model pointers\n defaultModel?: string // Default model name\n }\n\n // MCP Server Configuration\n mcpServers?: Record<string, TeamMcpServerConfig>\n\n // Plugin Marketplace Configuration\n plugins?: {\n // Plugin marketplace URLs (marketplace.json)\n marketplaces?: string[]\n // Specific plugins to install from marketplaces\n install?: string[] // Plugin names to install\n }\n\n // Global Settings\n settings?: {\n theme?: 'dark' | 'light'\n verbose?: boolean\n compressionMode?: 'business' | 'code'\n thinking?: boolean\n proxy?: string\n stream?: boolean\n // \u65B0\u589E\u8BBE\u7F6E\u9879\n language?: 'en' | 'zh-CN'\n safetyMode?: 'yolo' | 'smart' | 'strict' | 'free'\n skipOnboarding?: boolean // \u8DF3\u8FC7\u5165\u95E8\u6D41\u7A0B\n }\n\n // Agent \u914D\u7F6E\uFF08\u5185\u8054\u6216\u8FDC\u7A0B URL\uFF09\n agents?: {\n // \u8FDC\u7A0B agent \u6587\u4EF6 URL \u5217\u8868\n remoteAgents?: string[]\n // \u5185\u8054 agent \u5B9A\u4E49\n inlineAgents?: TeamAgentConfig[]\n }\n\n // Hook \u914D\u7F6E\n hooks?: TeamHooksConfig\n\n // Instructions for users\n postInstallInstructions?: string\n}\n\n/**\n * Model profile template with environment variable support\n */\nexport type TeamModelProfile = {\n name: string\n provider: ProviderType\n modelName: string\n baseURL?: string\n apiKey: string // Can be env var like \"${ANTHROPIC_API_KEY}\"\n maxTokens: number\n contextLength: number\n reasoningEffort?: 'low' | 'medium' | 'high' | 'minimal'\n isActive?: boolean\n}\n\n/**\n * Inline agent configuration for team config\n */\nexport type TeamAgentConfig = {\n name: string // Agent identifier (e.g., \"research-analyst\")\n description: string // When to use this agent\n tools: string[] | '*' // Tool permissions\n systemPrompt: string // System prompt content\n model?: string // Optional model override\n color?: string // Optional UI color\n}\n\n/**\n * Hook configuration for team config\n */\nexport type TeamHooksConfig = {\n // Session lifecycle hooks\n sessionStart?: TeamHookDefinition[]\n sessionEnd?: TeamHookDefinition[]\n // User input hooks\n userPromptSubmit?: TeamHookDefinition[]\n // Tool lifecycle hooks\n preToolUse?: TeamToolHook[]\n postToolUse?: TeamToolHook[]\n}\n\nexport type TeamHookDefinition = {\n type: 'command' | 'prompt'\n command?: string\n prompt?: string\n timeout?: number\n description?: string\n}\n\nexport type TeamToolHook = {\n matcher: string // Tool name regex or \"*\"\n hooks: TeamHookDefinition[]\n}\n\n/**\n * MCP server config with env var support\n */\nexport type TeamMcpServerConfig = {\n type?: 'stdio' | 'sse'\n command?: string // For stdio\n args?: string[] // For stdio, supports env vars like \"${HOME}/.local/bin/mcp-server\"\n url?: string // For SSE\n env?: Record<string, string> // Env vars, supports interpolation\n enabled?: boolean\n}\n\n/**\n * Interpolate environment variables in a string\n * Supports ${VAR_NAME} syntax\n */\nexport function interpolateEnvVars(value: string): string {\n return value.replace(/\\$\\{([^}]+)\\}/g, (match, varName) => {\n const envValue = process.env[varName.trim()]\n if (envValue === undefined) {\n debugLogger.warn('ENV_VAR_NOT_FOUND', {\n varName,\n original: match,\n })\n // Keep the placeholder if env var not found\n return match\n }\n return envValue\n })\n}\n\n/**\n * Recursively interpolate env vars in an object\n */\nexport function interpolateEnvVarsInObject<T>(obj: T): T {\n if (typeof obj === 'string') {\n return interpolateEnvVars(obj) as T\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => interpolateEnvVarsInObject(item)) as T\n }\n\n if (obj && typeof obj === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj)) {\n result[key] = interpolateEnvVarsInObject(value)\n }\n return result as T\n }\n\n return obj\n}\n\n/**\n * Convert team model profile to runtime model profile\n */\nexport function convertTeamModelProfile(\n teamProfile: TeamModelProfile,\n): ModelProfile {\n const now = Date.now()\n\n return {\n name: teamProfile.name,\n provider: teamProfile.provider,\n modelName: teamProfile.modelName,\n baseURL: teamProfile.baseURL,\n apiKey: interpolateEnvVars(teamProfile.apiKey),\n maxTokens: teamProfile.maxTokens,\n contextLength: teamProfile.contextLength,\n reasoningEffort: teamProfile.reasoningEffort,\n isActive: teamProfile.isActive ?? true,\n createdAt: now,\n lastUsed: now,\n }\n}\n\n/**\n * Convert team MCP config to runtime MCP config\n */\nexport function convertTeamMcpConfig(\n teamConfig: TeamMcpServerConfig,\n): McpServerConfig {\n if (teamConfig.type === 'sse') {\n return {\n type: 'sse',\n url: interpolateEnvVars(teamConfig.url || ''),\n enabled: teamConfig.enabled ?? true,\n }\n }\n\n // Default to stdio\n return {\n type: 'stdio',\n command: interpolateEnvVars(teamConfig.command || ''),\n args: (teamConfig.args || []).map(arg => interpolateEnvVars(arg)),\n env: teamConfig.env\n ? interpolateEnvVarsInObject(teamConfig.env)\n : undefined,\n enabled: teamConfig.enabled ?? true,\n }\n}\n\n/**\n * Fetch team configuration from a URL\n */\nexport async function fetchTeamConfig(url: string): Promise<TeamConfig> {\n debugLogger.state('TEAM_CONFIG_FETCH_START', { url })\n\n try {\n const response = await fetch(url)\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch config: ${response.status} ${response.statusText}`,\n )\n }\n\n const configText = await response.text()\n const config = JSON.parse(configText) as TeamConfig\n\n // Validate version\n if (config.version !== '1.0') {\n throw new Error(\n `Unsupported config version: ${config.version}. Expected 1.0`,\n )\n }\n\n debugLogger.state('TEAM_CONFIG_FETCH_SUCCESS', {\n url,\n configName: config.name,\n hasModels: !!config.models,\n hasMcpServers: !!config.mcpServers,\n })\n\n return config\n } catch (error) {\n debugLogger.error('TEAM_CONFIG_FETCH_ERROR', {\n url,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n}\n\n/**\n * Load team configuration from a local file\n */\nexport function loadTeamConfigFromFile(filePath: string): TeamConfig {\n debugLogger.state('TEAM_CONFIG_LOAD_FILE', { filePath })\n\n if (!existsSync(filePath)) {\n throw new Error(`Configuration file not found: ${filePath}`)\n }\n\n try {\n const configText = readFileSync(filePath, 'utf-8')\n const config = safeParseJSON(configText) as TeamConfig\n\n if (!config) {\n throw new Error('Invalid JSON in configuration file')\n }\n\n if (config.version !== '1.0') {\n throw new Error(\n `Unsupported config version: ${config.version}. Expected 1.0`,\n )\n }\n\n debugLogger.state('TEAM_CONFIG_LOAD_FILE_SUCCESS', {\n filePath,\n configName: config.name,\n })\n\n return config\n } catch (error) {\n debugLogger.error('TEAM_CONFIG_LOAD_FILE_ERROR', {\n filePath,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n}\n\n/**\n * Merge strategy for configuration\n */\nexport type MergeStrategy = 'replace' | 'merge' | 'skip-existing'\n\n/**\n * Apply team configuration to global config\n */\nexport function applyTeamConfig(\n teamConfig: TeamConfig,\n strategy: MergeStrategy = 'merge',\n): {\n applied: boolean\n modelsAdded: number\n mcpServersAdded: number\n settingsUpdated: string[]\n} {\n debugLogger.state('TEAM_CONFIG_APPLY_START', {\n configName: teamConfig.name,\n strategy,\n })\n\n const globalConfig = getGlobalConfig()\n let modelsAdded = 0\n let mcpServersAdded = 0\n const settingsUpdated: string[] = []\n\n // Apply model profiles\n if (teamConfig.models?.profiles) {\n const existingProfiles = globalConfig.modelProfiles || []\n const existingModelNames = new Set(existingProfiles.map(p => p.modelName))\n\n for (const teamProfile of teamConfig.models.profiles) {\n const runtimeProfile = convertTeamModelProfile(teamProfile)\n\n if (\n strategy === 'skip-existing' &&\n existingModelNames.has(runtimeProfile.modelName)\n ) {\n debugLogger.state('TEAM_CONFIG_SKIP_MODEL', {\n modelName: runtimeProfile.modelName,\n reason: 'already_exists',\n })\n continue\n }\n\n if (strategy === 'replace') {\n // Remove existing profile with same modelName\n const index = existingProfiles.findIndex(\n p => p.modelName === runtimeProfile.modelName,\n )\n if (index !== -1) {\n existingProfiles.splice(index, 1)\n }\n }\n\n existingProfiles.push(runtimeProfile)\n modelsAdded++\n\n debugLogger.state('TEAM_CONFIG_ADD_MODEL', {\n modelName: runtimeProfile.modelName,\n provider: runtimeProfile.provider,\n })\n }\n\n globalConfig.modelProfiles = existingProfiles\n }\n\n // Apply model pointers\n if (teamConfig.models?.pointers) {\n globalConfig.modelPointers = {\n ...(globalConfig.modelPointers || {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }),\n ...teamConfig.models.pointers,\n }\n settingsUpdated.push('modelPointers')\n }\n\n // Apply default model\n if (teamConfig.models?.defaultModel) {\n globalConfig.defaultModelName = teamConfig.models.defaultModel\n settingsUpdated.push('defaultModelName')\n }\n\n // Apply MCP servers\n if (teamConfig.mcpServers) {\n const existingMcpServers = globalConfig.mcpServers || {}\n const existingServerNames = new Set(Object.keys(existingMcpServers))\n\n for (const [serverName, teamMcpConfig] of Object.entries(\n teamConfig.mcpServers,\n )) {\n if (strategy === 'skip-existing' && existingServerNames.has(serverName)) {\n debugLogger.state('TEAM_CONFIG_SKIP_MCP', {\n serverName,\n reason: 'already_exists',\n })\n continue\n }\n\n const runtimeMcpConfig = convertTeamMcpConfig(teamMcpConfig)\n existingMcpServers[serverName] = runtimeMcpConfig\n mcpServersAdded++\n\n debugLogger.state('TEAM_CONFIG_ADD_MCP', {\n serverName,\n type: runtimeMcpConfig.type || 'stdio',\n })\n }\n\n globalConfig.mcpServers = existingMcpServers\n }\n\n // Apply global settings\n if (teamConfig.settings) {\n const { settings } = teamConfig\n\n if (settings.theme !== undefined) {\n globalConfig.theme = settings.theme\n settingsUpdated.push('theme')\n }\n\n if (settings.verbose !== undefined) {\n globalConfig.verbose = settings.verbose\n settingsUpdated.push('verbose')\n }\n\n if (settings.compressionMode !== undefined) {\n globalConfig.compressionMode = settings.compressionMode\n settingsUpdated.push('compressionMode')\n }\n\n if (settings.thinking !== undefined) {\n globalConfig.thinking = settings.thinking\n settingsUpdated.push('thinking')\n }\n\n if (settings.proxy !== undefined) {\n globalConfig.proxy = settings.proxy\n settingsUpdated.push('proxy')\n }\n\n if (settings.stream !== undefined) {\n globalConfig.stream = settings.stream\n settingsUpdated.push('stream')\n }\n\n if (settings.language !== undefined) {\n globalConfig.language = settings.language\n settingsUpdated.push('language')\n }\n\n if (settings.safetyMode !== undefined) {\n globalConfig.safetyMode = settings.safetyMode\n settingsUpdated.push('safetyMode')\n }\n\n if (settings.skipOnboarding) {\n globalConfig.hasCompletedOnboarding = true\n settingsUpdated.push('hasCompletedOnboarding')\n }\n }\n\n // Save updated config\n saveGlobalConfig(globalConfig)\n\n debugLogger.state('TEAM_CONFIG_APPLY_SUCCESS', {\n configName: teamConfig.name,\n modelsAdded,\n mcpServersAdded,\n settingsUpdated: settingsUpdated.join(', '),\n })\n\n return {\n applied: true,\n modelsAdded,\n mcpServersAdded,\n settingsUpdated,\n }\n}\n\n/**\n * Add marketplaces from URLs\n */\nexport async function addMarketplaces(\n marketplaceUrls: string[],\n): Promise<{ added: number; failed: number; errors: string[] }> {\n let added = 0\n let failed = 0\n const errors: string[] = []\n\n // Import marketplace manager\n const { addMarketplace } = await import('./marketplaceManager')\n\n for (const url of marketplaceUrls) {\n try {\n debugLogger.state('TEAM_CONFIG_ADD_MARKETPLACE', { url })\n\n await addMarketplace(url)\n added++\n\n debugLogger.state('TEAM_CONFIG_ADD_MARKETPLACE_SUCCESS', { url })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${url}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_ADD_MARKETPLACE_ERROR', {\n url,\n error: errorMsg,\n })\n }\n }\n\n return { added, failed, errors }\n}\n\n/**\n * Install plugins from marketplaces\n */\nexport async function installPlugins(\n pluginNames: string[],\n targetDir?: string,\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n // Import marketplace manager and path utilities\n const { installPluginFromMarketplace } = await import('./marketplaceManager')\n const { join } = await import('path')\n const { homedir } = await import('os')\n\n // Default target: ~/.minto/plugins\n const installDir = targetDir || join(homedir(), '.minto', 'plugins')\n\n for (const pluginName of pluginNames) {\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_PLUGIN', {\n pluginName,\n targetDir: installDir,\n })\n\n await installPluginFromMarketplace(\n pluginName,\n undefined, // Search all marketplaces\n join(installDir, pluginName),\n )\n\n installed++\n debugLogger.state('TEAM_CONFIG_INSTALL_PLUGIN_SUCCESS', { pluginName })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${pluginName}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_INSTALL_PLUGIN_ERROR', {\n pluginName,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Download and install remote agents\n */\nexport async function installRemoteAgents(\n agentUrls: string[],\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync } = await import('fs')\n\n // Target: ~/.minto/agents\n const agentsDir = join(homedir(), '.minto', 'agents')\n if (!existsSync(agentsDir)) {\n mkdirSync(agentsDir, { recursive: true })\n }\n\n for (const url of agentUrls) {\n try {\n debugLogger.state('TEAM_CONFIG_DOWNLOAD_AGENT', { url })\n\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const content = await response.text()\n\n // Extract filename from URL\n const filename = url.split('/').pop() || 'agent.md'\n const targetPath = join(agentsDir, filename)\n\n writeFileSync(targetPath, content, 'utf-8')\n installed++\n\n debugLogger.state('TEAM_CONFIG_DOWNLOAD_AGENT_SUCCESS', {\n url,\n targetPath,\n })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${url}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_DOWNLOAD_AGENT_ERROR', {\n url,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Install inline agents from team config\n */\nexport async function installInlineAgents(\n agents: TeamAgentConfig[],\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync } = await import('fs')\n\n // Target: ~/.minto/agents\n const agentsDir = join(homedir(), '.minto', 'agents')\n if (!existsSync(agentsDir)) {\n mkdirSync(agentsDir, { recursive: true })\n }\n\n for (const agent of agents) {\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_INLINE_AGENT', { name: agent.name })\n\n // Generate agent markdown file\n const tools =\n agent.tools === '*' ? '*' : JSON.stringify(agent.tools)\n\n const content = `---\nname: ${agent.name}\ndescription: \"${agent.description.replace(/\"/g, '\\\\\"')}\"\ntools: ${tools}${agent.model ? `\\nmodel_name: ${agent.model}` : ''}${agent.color ? `\\ncolor: \"${agent.color}\"` : ''}\n---\n\n${agent.systemPrompt}\n`\n\n const filename = `${agent.name}.md`\n const targetPath = join(agentsDir, filename)\n\n writeFileSync(targetPath, content, 'utf-8')\n installed++\n\n debugLogger.state('TEAM_CONFIG_INSTALL_INLINE_AGENT_SUCCESS', {\n name: agent.name,\n targetPath,\n })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${agent.name}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_INSTALL_INLINE_AGENT_ERROR', {\n name: agent.name,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Install hooks from team config\n */\nexport async function installTeamHooks(\n hooks: TeamHooksConfig,\n): Promise<{ installed: boolean; error?: string }> {\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync, readFileSync } = await import(\n 'fs'\n )\n\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_HOOKS', {})\n\n // Target: ~/.minto/hooks.json\n const mintoDir = join(homedir(), '.minto')\n if (!existsSync(mintoDir)) {\n mkdirSync(mintoDir, { recursive: true })\n }\n\n const hooksPath = join(mintoDir, 'hooks.json')\n\n // Convert TeamHooksConfig to standard hooks format\n const hooksConfig: Record<string, unknown> = {\n description: 'Team-configured hooks',\n hooks: {} as Record<string, unknown>,\n }\n\n const hooksObj = hooksConfig.hooks as Record<string, unknown>\n\n if (hooks.sessionStart) {\n hooksObj.SessionStart = [{ matcher: '*', hooks: hooks.sessionStart }]\n }\n if (hooks.sessionEnd) {\n hooksObj.SessionEnd = [{ matcher: '*', hooks: hooks.sessionEnd }]\n }\n if (hooks.userPromptSubmit) {\n hooksObj.UserPromptSubmit = [\n { matcher: '*', hooks: hooks.userPromptSubmit },\n ]\n }\n if (hooks.preToolUse) {\n hooksObj.PreToolUse = hooks.preToolUse\n }\n if (hooks.postToolUse) {\n hooksObj.PostToolUse = hooks.postToolUse\n }\n\n // Merge with existing hooks if present\n if (existsSync(hooksPath)) {\n try {\n const existingContent = readFileSync(hooksPath, 'utf-8')\n const existingHooks = JSON.parse(existingContent)\n // Deep merge\n for (const [event, matchers] of Object.entries(hooksObj)) {\n if (existingHooks.hooks?.[event]) {\n existingHooks.hooks[event] = [\n ...existingHooks.hooks[event],\n ...(matchers as unknown[]),\n ]\n } else {\n existingHooks.hooks = existingHooks.hooks || {}\n existingHooks.hooks[event] = matchers\n }\n }\n hooksConfig.hooks = existingHooks.hooks\n } catch {\n // If parsing fails, overwrite\n }\n }\n\n writeFileSync(hooksPath, JSON.stringify(hooksConfig, null, 2), 'utf-8')\n\n debugLogger.state('TEAM_CONFIG_INSTALL_HOOKS_SUCCESS', { hooksPath })\n\n return { installed: true }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error)\n debugLogger.error('TEAM_CONFIG_INSTALL_HOOKS_ERROR', { error: errorMsg })\n return { installed: false, error: errorMsg }\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Team Configuration System\n *\n * Enables teams to share a unified Minto configuration via remote URLs.\n * Supports environment variable interpolation and flexible configuration merging.\n */\n\nimport { existsSync, readFileSync } from 'fs'\nimport {\n getGlobalConfig,\n saveGlobalConfig,\n ModelProfile,\n ModelPointers,\n McpServerConfig,\n ProviderType,\n} from './config'\nimport { debug as debugLogger } from './debugLogger'\nimport { safeParseJSON } from './json'\n\n/**\n * Scope for team config export/import\n */\nexport type TeamConfigScope = 'user' | 'project' | 'all'\n\n/**\n * Standalone skill configuration for team config\n */\nexport type TeamSkillConfig = {\n name: string\n description: string\n content: string // markdown body\n argumentHint?: string\n disableModelInvocation?: boolean\n userInvocable?: boolean\n allowedTools?: string[]\n model?: string\n context?: string\n agent?: string\n}\n\n/**\n * Standalone command configuration for team config\n */\nexport type TeamCommandConfig = {\n name: string\n description?: string\n content: string // markdown body\n aliases?: string[]\n enabled?: boolean\n hidden?: boolean\n progressMessage?: string\n argNames?: string[]\n allowedTools?: string[]\n}\n\n/**\n * Team configuration schema\n * Represents a shareable configuration template for teams\n */\nexport type TeamConfig = {\n version: '1.0'\n name: string // Configuration name (e.g., \"Acme Inc. Default Config\")\n description?: string // Optional description\n scope?: TeamConfigScope // Scope that was used during export\n\n // Model Configuration\n models?: {\n profiles?: TeamModelProfile[]\n pointers?: Partial<ModelPointers> // Default model pointers\n defaultModel?: string // Default model name\n }\n\n // MCP Server Configuration\n mcpServers?: Record<string, TeamMcpServerConfig>\n\n // Plugin Marketplace Configuration\n plugins?: {\n // Plugin marketplace URLs (marketplace.json)\n marketplaces?: string[]\n // Specific plugins to install from marketplaces\n install?: string[] // v1.0 compat: no scope, defaults to user\n userInstall?: string[] // User-scope plugins\n projectInstall?: string[] // Project-scope plugins\n }\n\n // Global Settings\n settings?: {\n theme?: 'dark' | 'light'\n verbose?: boolean\n compressionMode?: 'business' | 'code'\n thinking?: boolean\n proxy?: string\n stream?: boolean\n // \u65B0\u589E\u8BBE\u7F6E\u9879\n language?: 'en' | 'zh-CN'\n safetyMode?: 'yolo' | 'smart' | 'strict' | 'free'\n skipOnboarding?: boolean // \u8DF3\u8FC7\u5165\u95E8\u6D41\u7A0B\n }\n\n // Agent \u914D\u7F6E\uFF08\u5185\u8054\u6216\u8FDC\u7A0B URL\uFF09\n agents?: {\n // \u8FDC\u7A0B agent \u6587\u4EF6 URL \u5217\u8868\n remoteAgents?: string[]\n // \u5185\u8054 agent \u5B9A\u4E49\n inlineAgents?: TeamAgentConfig[] // v1.0 compat: no scope, defaults to user\n userAgents?: TeamAgentConfig[]\n projectAgents?: TeamAgentConfig[]\n }\n\n // Skill \u914D\u7F6E\uFF08standalone skills\uFF09\n skills?: {\n userSkills?: TeamSkillConfig[]\n projectSkills?: TeamSkillConfig[]\n }\n\n // Command \u914D\u7F6E\uFF08standalone commands\uFF09\n commands?: {\n userCommands?: TeamCommandConfig[]\n projectCommands?: TeamCommandConfig[]\n }\n\n // Hook \u914D\u7F6E\n hooks?: TeamHooksConfig // User-scope hooks\n projectHooks?: TeamHooksConfig // Project-scope hooks\n\n // Instructions for users\n postInstallInstructions?: string\n}\n\n/**\n * Model profile template with environment variable support\n */\nexport type TeamModelProfile = {\n name: string\n provider: ProviderType\n modelName: string\n baseURL?: string\n apiKey: string // Can be env var like \"${ANTHROPIC_API_KEY}\"\n maxTokens: number\n contextLength: number\n reasoningEffort?: 'low' | 'medium' | 'high' | 'minimal'\n isActive?: boolean\n}\n\n/**\n * Inline agent configuration for team config\n */\nexport type TeamAgentConfig = {\n name: string // Agent identifier (e.g., \"research-analyst\")\n description: string // When to use this agent\n tools: string[] | '*' // Tool permissions\n systemPrompt: string // System prompt content\n model?: string // Optional model override\n color?: string // Optional UI color\n}\n\n/**\n * Hook configuration for team config\n */\nexport type TeamHooksConfig = {\n // Session lifecycle hooks\n sessionStart?: TeamHookDefinition[]\n sessionEnd?: TeamHookDefinition[]\n // User input hooks\n userPromptSubmit?: TeamHookDefinition[]\n // Tool lifecycle hooks\n preToolUse?: TeamToolHook[]\n postToolUse?: TeamToolHook[]\n}\n\nexport type TeamHookDefinition = {\n type: 'command' | 'prompt'\n command?: string\n prompt?: string\n timeout?: number\n description?: string\n}\n\nexport type TeamToolHook = {\n matcher: string // Tool name regex or \"*\"\n hooks: TeamHookDefinition[]\n}\n\n/**\n * MCP server config with env var support\n */\nexport type TeamMcpServerConfig = {\n type?: 'stdio' | 'sse'\n command?: string // For stdio\n args?: string[] // For stdio, supports env vars like \"${HOME}/.local/bin/mcp-server\"\n url?: string // For SSE\n env?: Record<string, string> // Env vars, supports interpolation\n enabled?: boolean\n}\n\n/**\n * Interpolate environment variables in a string\n * Supports ${VAR_NAME} syntax\n */\nexport function interpolateEnvVars(value: string): string {\n return value.replace(/\\$\\{([^}]+)\\}/g, (match, varName) => {\n const envValue = process.env[varName.trim()]\n if (envValue === undefined) {\n debugLogger.warn('ENV_VAR_NOT_FOUND', {\n varName,\n original: match,\n })\n // Keep the placeholder if env var not found\n return match\n }\n return envValue\n })\n}\n\n/**\n * Recursively interpolate env vars in an object\n */\nexport function interpolateEnvVarsInObject<T>(obj: T): T {\n if (typeof obj === 'string') {\n return interpolateEnvVars(obj) as T\n }\n\n if (Array.isArray(obj)) {\n return obj.map(item => interpolateEnvVarsInObject(item)) as T\n }\n\n if (obj && typeof obj === 'object') {\n const result: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(obj)) {\n result[key] = interpolateEnvVarsInObject(value)\n }\n return result as T\n }\n\n return obj\n}\n\n/**\n * Convert team model profile to runtime model profile\n */\nexport function convertTeamModelProfile(\n teamProfile: TeamModelProfile,\n): ModelProfile {\n const now = Date.now()\n\n return {\n name: teamProfile.name,\n provider: teamProfile.provider,\n modelName: teamProfile.modelName,\n baseURL: teamProfile.baseURL,\n apiKey: interpolateEnvVars(teamProfile.apiKey),\n maxTokens: teamProfile.maxTokens,\n contextLength: teamProfile.contextLength,\n reasoningEffort: teamProfile.reasoningEffort,\n isActive: teamProfile.isActive ?? true,\n createdAt: now,\n lastUsed: now,\n }\n}\n\n/**\n * Convert team MCP config to runtime MCP config\n */\nexport function convertTeamMcpConfig(\n teamConfig: TeamMcpServerConfig,\n): McpServerConfig {\n if (teamConfig.type === 'sse') {\n return {\n type: 'sse',\n url: interpolateEnvVars(teamConfig.url || ''),\n enabled: teamConfig.enabled ?? true,\n }\n }\n\n // Default to stdio\n return {\n type: 'stdio',\n command: interpolateEnvVars(teamConfig.command || ''),\n args: (teamConfig.args || []).map(arg => interpolateEnvVars(arg)),\n env: teamConfig.env\n ? interpolateEnvVarsInObject(teamConfig.env)\n : undefined,\n enabled: teamConfig.enabled ?? true,\n }\n}\n\n/**\n * Fetch team configuration from a URL\n */\nexport async function fetchTeamConfig(url: string): Promise<TeamConfig> {\n debugLogger.state('TEAM_CONFIG_FETCH_START', { url })\n\n try {\n const response = await fetch(url)\n\n if (!response.ok) {\n throw new Error(\n `Failed to fetch config: ${response.status} ${response.statusText}`,\n )\n }\n\n const configText = await response.text()\n const config = JSON.parse(configText) as TeamConfig\n\n // Validate version\n if (config.version !== '1.0') {\n throw new Error(\n `Unsupported config version: ${config.version}. Expected 1.0`,\n )\n }\n\n debugLogger.state('TEAM_CONFIG_FETCH_SUCCESS', {\n url,\n configName: config.name,\n hasModels: !!config.models,\n hasMcpServers: !!config.mcpServers,\n })\n\n return config\n } catch (error) {\n debugLogger.error('TEAM_CONFIG_FETCH_ERROR', {\n url,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n}\n\n/**\n * Load team configuration from a local file\n */\nexport function loadTeamConfigFromFile(filePath: string): TeamConfig {\n debugLogger.state('TEAM_CONFIG_LOAD_FILE', { filePath })\n\n if (!existsSync(filePath)) {\n throw new Error(`Configuration file not found: ${filePath}`)\n }\n\n try {\n const configText = readFileSync(filePath, 'utf-8')\n const config = safeParseJSON(configText) as TeamConfig\n\n if (!config) {\n throw new Error('Invalid JSON in configuration file')\n }\n\n if (config.version !== '1.0') {\n throw new Error(\n `Unsupported config version: ${config.version}. Expected 1.0`,\n )\n }\n\n debugLogger.state('TEAM_CONFIG_LOAD_FILE_SUCCESS', {\n filePath,\n configName: config.name,\n })\n\n return config\n } catch (error) {\n debugLogger.error('TEAM_CONFIG_LOAD_FILE_ERROR', {\n filePath,\n error: error instanceof Error ? error.message : String(error),\n })\n throw error\n }\n}\n\n/**\n * Merge strategy for configuration\n */\nexport type MergeStrategy = 'replace' | 'merge' | 'skip-existing'\n\n/**\n * Apply team configuration to global config\n */\nexport function applyTeamConfig(\n teamConfig: TeamConfig,\n strategy: MergeStrategy = 'merge',\n): {\n applied: boolean\n modelsAdded: number\n mcpServersAdded: number\n settingsUpdated: string[]\n} {\n debugLogger.state('TEAM_CONFIG_APPLY_START', {\n configName: teamConfig.name,\n strategy,\n })\n\n const globalConfig = getGlobalConfig()\n let modelsAdded = 0\n let mcpServersAdded = 0\n const settingsUpdated: string[] = []\n\n // Apply model profiles\n if (teamConfig.models?.profiles) {\n const existingProfiles = globalConfig.modelProfiles || []\n const existingModelNames = new Set(existingProfiles.map(p => p.modelName))\n\n for (const teamProfile of teamConfig.models.profiles) {\n const runtimeProfile = convertTeamModelProfile(teamProfile)\n\n if (\n strategy === 'skip-existing' &&\n existingModelNames.has(runtimeProfile.modelName)\n ) {\n debugLogger.state('TEAM_CONFIG_SKIP_MODEL', {\n modelName: runtimeProfile.modelName,\n reason: 'already_exists',\n })\n continue\n }\n\n if (strategy === 'replace') {\n // Remove existing profile with same modelName\n const index = existingProfiles.findIndex(\n p => p.modelName === runtimeProfile.modelName,\n )\n if (index !== -1) {\n existingProfiles.splice(index, 1)\n }\n }\n\n existingProfiles.push(runtimeProfile)\n modelsAdded++\n\n debugLogger.state('TEAM_CONFIG_ADD_MODEL', {\n modelName: runtimeProfile.modelName,\n provider: runtimeProfile.provider,\n })\n }\n\n globalConfig.modelProfiles = existingProfiles\n }\n\n // Apply model pointers\n if (teamConfig.models?.pointers) {\n globalConfig.modelPointers = {\n ...(globalConfig.modelPointers || {\n main: '',\n task: '',\n reasoning: '',\n quick: '',\n compact: '',\n }),\n ...teamConfig.models.pointers,\n }\n settingsUpdated.push('modelPointers')\n }\n\n // Apply default model\n if (teamConfig.models?.defaultModel) {\n globalConfig.defaultModelName = teamConfig.models.defaultModel\n settingsUpdated.push('defaultModelName')\n }\n\n // Apply MCP servers\n if (teamConfig.mcpServers) {\n const existingMcpServers = globalConfig.mcpServers || {}\n const existingServerNames = new Set(Object.keys(existingMcpServers))\n\n for (const [serverName, teamMcpConfig] of Object.entries(\n teamConfig.mcpServers,\n )) {\n if (strategy === 'skip-existing' && existingServerNames.has(serverName)) {\n debugLogger.state('TEAM_CONFIG_SKIP_MCP', {\n serverName,\n reason: 'already_exists',\n })\n continue\n }\n\n const runtimeMcpConfig = convertTeamMcpConfig(teamMcpConfig)\n existingMcpServers[serverName] = runtimeMcpConfig\n mcpServersAdded++\n\n debugLogger.state('TEAM_CONFIG_ADD_MCP', {\n serverName,\n type: runtimeMcpConfig.type || 'stdio',\n })\n }\n\n globalConfig.mcpServers = existingMcpServers\n }\n\n // Apply global settings\n if (teamConfig.settings) {\n const { settings } = teamConfig\n\n if (settings.theme !== undefined) {\n globalConfig.theme = settings.theme\n settingsUpdated.push('theme')\n }\n\n if (settings.verbose !== undefined) {\n globalConfig.verbose = settings.verbose\n settingsUpdated.push('verbose')\n }\n\n if (settings.compressionMode !== undefined) {\n globalConfig.compressionMode = settings.compressionMode\n settingsUpdated.push('compressionMode')\n }\n\n if (settings.thinking !== undefined) {\n globalConfig.thinking = settings.thinking\n settingsUpdated.push('thinking')\n }\n\n if (settings.proxy !== undefined) {\n globalConfig.proxy = settings.proxy\n settingsUpdated.push('proxy')\n }\n\n if (settings.stream !== undefined) {\n globalConfig.stream = settings.stream\n settingsUpdated.push('stream')\n }\n\n if (settings.language !== undefined) {\n globalConfig.language = settings.language\n settingsUpdated.push('language')\n }\n\n if (settings.safetyMode !== undefined) {\n globalConfig.safetyMode = settings.safetyMode\n settingsUpdated.push('safetyMode')\n }\n\n if (settings.skipOnboarding) {\n globalConfig.hasCompletedOnboarding = true\n settingsUpdated.push('hasCompletedOnboarding')\n }\n }\n\n // Save updated config\n saveGlobalConfig(globalConfig)\n\n debugLogger.state('TEAM_CONFIG_APPLY_SUCCESS', {\n configName: teamConfig.name,\n modelsAdded,\n mcpServersAdded,\n settingsUpdated: settingsUpdated.join(', '),\n })\n\n return {\n applied: true,\n modelsAdded,\n mcpServersAdded,\n settingsUpdated,\n }\n}\n\n/**\n * Add marketplaces from URLs\n */\nexport async function addMarketplaces(\n marketplaceUrls: string[],\n): Promise<{ added: number; failed: number; errors: string[] }> {\n let added = 0\n let failed = 0\n const errors: string[] = []\n\n // Import marketplace manager\n const { addMarketplace } = await import('./marketplaceManager')\n\n for (const url of marketplaceUrls) {\n try {\n debugLogger.state('TEAM_CONFIG_ADD_MARKETPLACE', { url })\n\n await addMarketplace(url)\n added++\n\n debugLogger.state('TEAM_CONFIG_ADD_MARKETPLACE_SUCCESS', { url })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${url}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_ADD_MARKETPLACE_ERROR', {\n url,\n error: errorMsg,\n })\n }\n }\n\n return { added, failed, errors }\n}\n\n/**\n * Install plugins from marketplaces\n */\nexport async function installPlugins(\n pluginNames: string[],\n targetDir?: string,\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n // Import marketplace manager and path utilities\n const { installPluginFromMarketplace } = await import('./marketplaceManager')\n const { join } = await import('path')\n const { homedir } = await import('os')\n\n // Default target: ~/.minto/plugins\n const installDir = targetDir || join(homedir(), '.minto', 'plugins')\n\n for (const pluginSpec of pluginNames) {\n // Parse name@marketplace format (e.g., \"backend-development@claude-code-workflows\")\n const atIndex = pluginSpec.indexOf('@')\n const pluginName =\n atIndex !== -1 ? pluginSpec.slice(0, atIndex) : pluginSpec\n const marketplaceName =\n atIndex !== -1 ? pluginSpec.slice(atIndex + 1) : undefined\n\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_PLUGIN', {\n pluginName,\n marketplace: marketplaceName,\n targetDir: installDir,\n })\n\n await installPluginFromMarketplace(\n pluginName,\n marketplaceName,\n join(installDir, pluginName),\n )\n\n installed++\n debugLogger.state('TEAM_CONFIG_INSTALL_PLUGIN_SUCCESS', { pluginName })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${pluginName}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_INSTALL_PLUGIN_ERROR', {\n pluginName,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Download and install remote agents\n */\nexport async function installRemoteAgents(\n agentUrls: string[],\n targetDir?: string,\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync } = await import('fs')\n\n // Target: specified dir or ~/.minto/agents\n const agentsDir = targetDir || join(homedir(), '.minto', 'agents')\n if (!existsSync(agentsDir)) {\n mkdirSync(agentsDir, { recursive: true })\n }\n\n for (const url of agentUrls) {\n try {\n debugLogger.state('TEAM_CONFIG_DOWNLOAD_AGENT', { url })\n\n const response = await fetch(url)\n if (!response.ok) {\n throw new Error(`HTTP ${response.status}: ${response.statusText}`)\n }\n\n const content = await response.text()\n\n // Extract filename from URL\n const filename = url.split('/').pop() || 'agent.md'\n const targetPath = join(agentsDir, filename)\n\n writeFileSync(targetPath, content, 'utf-8')\n installed++\n\n debugLogger.state('TEAM_CONFIG_DOWNLOAD_AGENT_SUCCESS', {\n url,\n targetPath,\n })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${url}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_DOWNLOAD_AGENT_ERROR', {\n url,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Install inline agents from team config\n */\nexport async function installInlineAgents(\n agents: TeamAgentConfig[],\n targetDir?: string,\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync } = await import('fs')\n\n // Target: specified dir or ~/.minto/agents\n const agentsDir = targetDir || join(homedir(), '.minto', 'agents')\n if (!existsSync(agentsDir)) {\n mkdirSync(agentsDir, { recursive: true })\n }\n\n for (const agent of agents) {\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_INLINE_AGENT', {\n name: agent.name,\n })\n\n // Generate agent markdown file\n const tools = agent.tools === '*' ? '*' : JSON.stringify(agent.tools)\n\n const content = `---\nname: ${agent.name}\ndescription: \"${agent.description.replace(/\"/g, '\\\\\"')}\"\ntools: ${tools}${agent.model ? `\\nmodel_name: ${agent.model}` : ''}${agent.color ? `\\ncolor: \"${agent.color}\"` : ''}\n---\n\n${agent.systemPrompt}\n`\n\n const filename = `${agent.name}.md`\n const targetPath = join(agentsDir, filename)\n\n writeFileSync(targetPath, content, 'utf-8')\n installed++\n\n debugLogger.state('TEAM_CONFIG_INSTALL_INLINE_AGENT_SUCCESS', {\n name: agent.name,\n targetPath,\n })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${agent.name}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_INSTALL_INLINE_AGENT_ERROR', {\n name: agent.name,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Install hooks from team config\n */\nexport async function installTeamHooks(\n hooks: TeamHooksConfig,\n targetPath?: string,\n): Promise<{ installed: boolean; error?: string }> {\n const { join, dirname } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync, readFileSync } = await import(\n 'fs'\n )\n\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_HOOKS', {})\n\n // Target: specified path or ~/.minto/hooks.json\n const hooksPath = targetPath || join(homedir(), '.minto', 'hooks.json')\n const hooksDir = dirname(hooksPath)\n if (!existsSync(hooksDir)) {\n mkdirSync(hooksDir, { recursive: true })\n }\n\n // Convert TeamHooksConfig to standard hooks format\n const hooksConfig: Record<string, unknown> = {\n description: 'Team-configured hooks',\n hooks: {} as Record<string, unknown>,\n }\n\n const hooksObj = hooksConfig.hooks as Record<string, unknown>\n\n if (hooks.sessionStart) {\n hooksObj.SessionStart = [{ matcher: '*', hooks: hooks.sessionStart }]\n }\n if (hooks.sessionEnd) {\n hooksObj.SessionEnd = [{ matcher: '*', hooks: hooks.sessionEnd }]\n }\n if (hooks.userPromptSubmit) {\n hooksObj.UserPromptSubmit = [\n { matcher: '*', hooks: hooks.userPromptSubmit },\n ]\n }\n if (hooks.preToolUse) {\n hooksObj.PreToolUse = hooks.preToolUse\n }\n if (hooks.postToolUse) {\n hooksObj.PostToolUse = hooks.postToolUse\n }\n\n // Merge with existing hooks if present\n if (existsSync(hooksPath)) {\n try {\n const existingContent = readFileSync(hooksPath, 'utf-8')\n const existingHooks = JSON.parse(existingContent)\n // Deep merge\n for (const [event, matchers] of Object.entries(hooksObj)) {\n if (existingHooks.hooks?.[event]) {\n existingHooks.hooks[event] = [\n ...existingHooks.hooks[event],\n ...(matchers as unknown[]),\n ]\n } else {\n existingHooks.hooks = existingHooks.hooks || {}\n existingHooks.hooks[event] = matchers\n }\n }\n hooksConfig.hooks = existingHooks.hooks\n } catch {\n // If parsing fails, overwrite\n }\n }\n\n writeFileSync(hooksPath, JSON.stringify(hooksConfig, null, 2), 'utf-8')\n\n debugLogger.state('TEAM_CONFIG_INSTALL_HOOKS_SUCCESS', { hooksPath })\n\n return { installed: true }\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error)\n debugLogger.error('TEAM_CONFIG_INSTALL_HOOKS_ERROR', { error: errorMsg })\n return { installed: false, error: errorMsg }\n }\n}\n\n/**\n * Install standalone skills from team config\n */\nexport async function installInlineSkills(\n skills: TeamSkillConfig[],\n targetDir?: string,\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync } = await import('fs')\n\n // Target: specified dir or ~/.minto/skills\n const skillsDir = targetDir || join(homedir(), '.minto', 'skills')\n if (!existsSync(skillsDir)) {\n mkdirSync(skillsDir, { recursive: true })\n }\n\n for (const skill of skills) {\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_SKILL', { name: skill.name })\n\n // Build frontmatter\n const frontmatterLines: string[] = [\n `name: ${skill.name}`,\n `description: \"${skill.description.replace(/\"/g, '\\\\\"')}\"`,\n ]\n if (skill.argumentHint) {\n frontmatterLines.push(`argument-hint: \"${skill.argumentHint}\"`)\n }\n if (skill.disableModelInvocation !== undefined) {\n frontmatterLines.push(\n `disable-model-invocation: ${skill.disableModelInvocation}`,\n )\n }\n if (skill.userInvocable !== undefined) {\n frontmatterLines.push(`user-invocable: ${skill.userInvocable}`)\n }\n if (skill.allowedTools && skill.allowedTools.length > 0) {\n frontmatterLines.push(\n `allowed-tools: ${JSON.stringify(skill.allowedTools)}`,\n )\n }\n if (skill.model) {\n frontmatterLines.push(`model: ${skill.model}`)\n }\n if (skill.context) {\n frontmatterLines.push(`context: \"${skill.context}\"`)\n }\n if (skill.agent) {\n frontmatterLines.push(`agent: \"${skill.agent}\"`)\n }\n\n const content = `---\\n${frontmatterLines.join('\\n')}\\n---\\n\\n${skill.content}\\n`\n\n const filename = `${skill.name}.md`\n const targetPath = join(skillsDir, filename)\n\n writeFileSync(targetPath, content, 'utf-8')\n installed++\n\n debugLogger.state('TEAM_CONFIG_INSTALL_SKILL_SUCCESS', {\n name: skill.name,\n targetPath,\n })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${skill.name}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_INSTALL_SKILL_ERROR', {\n name: skill.name,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n\n/**\n * Install standalone commands from team config\n */\nexport async function installInlineCommands(\n commands: TeamCommandConfig[],\n targetDir?: string,\n): Promise<{ installed: number; failed: number; errors: string[] }> {\n let installed = 0\n let failed = 0\n const errors: string[] = []\n\n const { join } = await import('path')\n const { homedir } = await import('os')\n const { writeFileSync, mkdirSync, existsSync } = await import('fs')\n\n // Target: specified dir or ~/.minto/commands\n const commandsDir = targetDir || join(homedir(), '.minto', 'commands')\n if (!existsSync(commandsDir)) {\n mkdirSync(commandsDir, { recursive: true })\n }\n\n for (const cmd of commands) {\n try {\n debugLogger.state('TEAM_CONFIG_INSTALL_COMMAND', { name: cmd.name })\n\n // Build frontmatter\n const frontmatterLines: string[] = [`name: ${cmd.name}`]\n if (cmd.description) {\n frontmatterLines.push(\n `description: \"${cmd.description.replace(/\"/g, '\\\\\"')}\"`,\n )\n }\n if (cmd.aliases && cmd.aliases.length > 0) {\n frontmatterLines.push(`aliases: ${JSON.stringify(cmd.aliases)}`)\n }\n if (cmd.enabled !== undefined) {\n frontmatterLines.push(`enabled: ${cmd.enabled}`)\n }\n if (cmd.hidden !== undefined) {\n frontmatterLines.push(`hidden: ${cmd.hidden}`)\n }\n if (cmd.progressMessage) {\n frontmatterLines.push(`progressMessage: \"${cmd.progressMessage}\"`)\n }\n if (cmd.argNames && cmd.argNames.length > 0) {\n frontmatterLines.push(`argNames: ${JSON.stringify(cmd.argNames)}`)\n }\n if (cmd.allowedTools && cmd.allowedTools.length > 0) {\n frontmatterLines.push(\n `allowed-tools: ${JSON.stringify(cmd.allowedTools)}`,\n )\n }\n\n const content = `---\\n${frontmatterLines.join('\\n')}\\n---\\n\\n${cmd.content}\\n`\n\n const filename = `${cmd.name}.md`\n const targetPath = join(commandsDir, filename)\n\n writeFileSync(targetPath, content, 'utf-8')\n installed++\n\n debugLogger.state('TEAM_CONFIG_INSTALL_COMMAND_SUCCESS', {\n name: cmd.name,\n targetPath,\n })\n } catch (error) {\n failed++\n const errorMsg = error instanceof Error ? error.message : String(error)\n errors.push(`${cmd.name}: ${errorMsg}`)\n\n debugLogger.error('TEAM_CONFIG_INSTALL_COMMAND_ERROR', {\n name: cmd.name,\n error: errorMsg,\n })\n }\n }\n\n return { installed, failed, errors }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["existsSync", "readFileSync"]
7
7
  }
@@ -36,7 +36,7 @@ function clearTerminal() {
36
36
  });
37
37
  }
38
38
  function clearScreen() {
39
- process.stdout.write("\x1B[2J\x1B[H");
39
+ process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
40
40
  }
41
41
  function prepareTerminalForREPL() {
42
42
  return new Promise((resolve) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/utils/terminal.ts"],
4
- "sourcesContent": ["import { safeParseJSON } from './json'\nimport { logError } from './log'\nimport { queryQuick } from '@services/claude'\n\nexport function setTerminalTitle(title: string): void {\n if (process.platform === 'win32') {\n process.title = title ? `\u2733 ${title}` : title\n } else {\n process.stdout.write(`\\x1b]0;${title ? `\u2733 ${title}` : ''}\\x07`)\n }\n}\n\nexport async function updateTerminalTitle(message: string): Promise<void> {\n try {\n const result = await queryQuick({\n systemPrompt: [\n \"Analyze if this message indicates a new conversation topic. If it does, extract a 2-3 word title that captures the new topic. Format your response as a JSON object with two fields: 'isNewTopic' (boolean) and 'title' (string, or null if isNewTopic is false). Only include these fields, no other text.\",\n ],\n userPrompt: message,\n enablePromptCaching: true,\n })\n\n const content = result.message.content\n .filter(_ => _.type === 'text')\n .map(_ => _.text)\n .join('')\n\n const response = safeParseJSON(content)\n if (\n response &&\n typeof response === 'object' &&\n 'isNewTopic' in response &&\n 'title' in response\n ) {\n if (response.isNewTopic && response.title) {\n setTerminalTitle(response.title as string)\n }\n }\n } catch (error) {\n logError(error)\n }\n}\n\nexport function clearTerminal(): Promise<void> {\n return new Promise(resolve => {\n process.stdout.write('\\x1b[2J\\x1b[3J\\x1b[H', () => {\n resolve()\n })\n })\n}\n\n/**\n * Synchronous clear screen (for immediate feedback with hotkeys like Ctrl-L)\n * Uses ANSI escape sequences: \\x1b[2J clears screen, \\x1b[H moves cursor to home\n */\nexport function clearScreen(): void {\n process.stdout.write('\\x1b[2J\\x1b[H')\n}\n\n/**\n * Prepare terminal for REPL rendering\n * Clears screen and normalizes terminal state before Ink starts rendering\n *\n * This ensures a clean slate for the REPL interface:\n * - \\x1b[2J - Clear entire screen\n * - \\x1b[3J - Clear scrollback buffer (provides fresh start)\n * - \\x1b[H - Move cursor to home position (0,0)\n * - \\x1b[?25h - Show cursor (in case it was hidden)\n *\n * @returns Promise that resolves when terminal is ready\n */\nexport function prepareTerminalForREPL(): Promise<void> {\n return new Promise(resolve => {\n if (!process.stdout.isTTY) {\n resolve()\n return\n }\n\n // Clear screen, scrollback, move cursor home, show cursor\n process.stdout.write('\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25h', () => {\n resolve()\n })\n })\n}\n"],
5
- "mappings": "AAAA,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAEpB,SAAS,iBAAiB,OAAqB;AACpD,MAAI,QAAQ,aAAa,SAAS;AAChC,YAAQ,QAAQ,QAAQ,UAAK,KAAK,KAAK;AAAA,EACzC,OAAO;AACL,YAAQ,OAAO,MAAM,UAAU,QAAQ,UAAK,KAAK,KAAK,EAAE,MAAM;AAAA,EAChE;AACF;AAEA,eAAsB,oBAAoB,SAAgC;AACxE,MAAI;AACF,UAAM,SAAS,MAAM,WAAW;AAAA,MAC9B,cAAc;AAAA,QACZ;AAAA,MACF;AAAA,MACA,YAAY;AAAA,MACZ,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,UAAU,OAAO,QAAQ,QAC5B,OAAO,OAAK,EAAE,SAAS,MAAM,EAC7B,IAAI,OAAK,EAAE,IAAI,EACf,KAAK,EAAE;AAEV,UAAM,WAAW,cAAc,OAAO;AACtC,QACE,YACA,OAAO,aAAa,YACpB,gBAAgB,YAChB,WAAW,UACX;AACA,UAAI,SAAS,cAAc,SAAS,OAAO;AACzC,yBAAiB,SAAS,KAAe;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,aAAS,KAAK;AAAA,EAChB;AACF;AAEO,SAAS,gBAA+B;AAC7C,SAAO,IAAI,QAAQ,aAAW;AAC5B,YAAQ,OAAO,MAAM,wBAAwB,MAAM;AACjD,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;AAMO,SAAS,cAAoB;AAClC,UAAQ,OAAO,MAAM,eAAe;AACtC;AAcO,SAAS,yBAAwC;AACtD,SAAO,IAAI,QAAQ,aAAW;AAC5B,QAAI,CAAC,QAAQ,OAAO,OAAO;AACzB,cAAQ;AACR;AAAA,IACF;AAGA,YAAQ,OAAO,MAAM,iCAAiC,MAAM;AAC1D,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;",
4
+ "sourcesContent": ["import { safeParseJSON } from './json'\nimport { logError } from './log'\nimport { queryQuick } from '@services/claude'\n\nexport function setTerminalTitle(title: string): void {\n if (process.platform === 'win32') {\n process.title = title ? `\u2733 ${title}` : title\n } else {\n process.stdout.write(`\\x1b]0;${title ? `\u2733 ${title}` : ''}\\x07`)\n }\n}\n\nexport async function updateTerminalTitle(message: string): Promise<void> {\n try {\n const result = await queryQuick({\n systemPrompt: [\n \"Analyze if this message indicates a new conversation topic. If it does, extract a 2-3 word title that captures the new topic. Format your response as a JSON object with two fields: 'isNewTopic' (boolean) and 'title' (string, or null if isNewTopic is false). Only include these fields, no other text.\",\n ],\n userPrompt: message,\n enablePromptCaching: true,\n })\n\n const content = result.message.content\n .filter(_ => _.type === 'text')\n .map(_ => _.text)\n .join('')\n\n const response = safeParseJSON(content)\n if (\n response &&\n typeof response === 'object' &&\n 'isNewTopic' in response &&\n 'title' in response\n ) {\n if (response.isNewTopic && response.title) {\n setTerminalTitle(response.title as string)\n }\n }\n } catch (error) {\n logError(error)\n }\n}\n\nexport function clearTerminal(): Promise<void> {\n return new Promise(resolve => {\n process.stdout.write('\\x1b[2J\\x1b[3J\\x1b[H', () => {\n resolve()\n })\n })\n}\n\n/**\n * Synchronous clear screen + scrollback (for immediate feedback with hotkeys like Ctrl-L)\n * Uses ANSI escape sequences:\n * \\x1b[2J - Clear entire visible screen\n * \\x1b[3J - Clear scrollback buffer (prevents tall-component remnants)\n * \\x1b[H - Move cursor to home position (0,0)\n */\nexport function clearScreen(): void {\n process.stdout.write('\\x1b[2J\\x1b[3J\\x1b[H')\n}\n\n/**\n * Prepare terminal for REPL rendering\n * Clears screen and normalizes terminal state before Ink starts rendering\n *\n * This ensures a clean slate for the REPL interface:\n * - \\x1b[2J - Clear entire screen\n * - \\x1b[3J - Clear scrollback buffer (provides fresh start)\n * - \\x1b[H - Move cursor to home position (0,0)\n * - \\x1b[?25h - Show cursor (in case it was hidden)\n *\n * @returns Promise that resolves when terminal is ready\n */\nexport function prepareTerminalForREPL(): Promise<void> {\n return new Promise(resolve => {\n if (!process.stdout.isTTY) {\n resolve()\n return\n }\n\n // Clear screen, scrollback, move cursor home, show cursor\n process.stdout.write('\\x1b[2J\\x1b[3J\\x1b[H\\x1b[?25h', () => {\n resolve()\n })\n })\n}\n"],
5
+ "mappings": "AAAA,SAAS,qBAAqB;AAC9B,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAEpB,SAAS,iBAAiB,OAAqB;AACpD,MAAI,QAAQ,aAAa,SAAS;AAChC,YAAQ,QAAQ,QAAQ,UAAK,KAAK,KAAK;AAAA,EACzC,OAAO;AACL,YAAQ,OAAO,MAAM,UAAU,QAAQ,UAAK,KAAK,KAAK,EAAE,MAAM;AAAA,EAChE;AACF;AAEA,eAAsB,oBAAoB,SAAgC;AACxE,MAAI;AACF,UAAM,SAAS,MAAM,WAAW;AAAA,MAC9B,cAAc;AAAA,QACZ;AAAA,MACF;AAAA,MACA,YAAY;AAAA,MACZ,qBAAqB;AAAA,IACvB,CAAC;AAED,UAAM,UAAU,OAAO,QAAQ,QAC5B,OAAO,OAAK,EAAE,SAAS,MAAM,EAC7B,IAAI,OAAK,EAAE,IAAI,EACf,KAAK,EAAE;AAEV,UAAM,WAAW,cAAc,OAAO;AACtC,QACE,YACA,OAAO,aAAa,YACpB,gBAAgB,YAChB,WAAW,UACX;AACA,UAAI,SAAS,cAAc,SAAS,OAAO;AACzC,yBAAiB,SAAS,KAAe;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AACd,aAAS,KAAK;AAAA,EAChB;AACF;AAEO,SAAS,gBAA+B;AAC7C,SAAO,IAAI,QAAQ,aAAW;AAC5B,YAAQ,OAAO,MAAM,wBAAwB,MAAM;AACjD,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;AASO,SAAS,cAAoB;AAClC,UAAQ,OAAO,MAAM,sBAAsB;AAC7C;AAcO,SAAS,yBAAwC;AACtD,SAAO,IAAI,QAAQ,aAAW;AAC5B,QAAI,CAAC,QAAQ,OAAO,OAAO;AACzB,cAAQ;AACR;AAAA,IACF;AAGA,YAAQ,OAAO,MAAM,iCAAiC,MAAM;AAC1D,cAAQ;AAAA,IACV,CAAC;AAAA,EACH,CAAC;AACH;",
6
6
  "names": []
7
7
  }
@@ -8,8 +8,8 @@ import {
8
8
  unlinkSync
9
9
  } from "fs";
10
10
  import { join } from "path";
11
- import envPaths from "env-paths";
12
- import { PRODUCT_COMMAND } from "../constants/product.js";
11
+ import { CONFIG_PATHS } from "./configPaths.js";
12
+ import { getProjectHash } from "./sessionIndex.js";
13
13
  const TODO_STORAGE_KEY = "todos";
14
14
  const TODO_CONFIG_KEY = "todoConfig";
15
15
  const DEFAULT_CONFIG = {
@@ -23,24 +23,45 @@ let todoCache = null;
23
23
  let cacheTimestamp = 0;
24
24
  const CACHE_TTL = 5e3;
25
25
  let currentSessionId = null;
26
- const paths = envPaths(PRODUCT_COMMAND);
27
- function getProjectDir(cwd) {
28
- return cwd.replace(/[^a-zA-Z0-9]/g, "-");
26
+ let currentProjectPath = null;
27
+ function getLegacyTodoPath(sessionId) {
28
+ return join(CONFIG_PATHS.base, `default-session-agent-${sessionId}.json`);
29
29
  }
30
- function getSessionTodoPath(sessionId) {
31
- const projectDir = getProjectDir(process.cwd());
32
- const todosDir = join(paths.cache, projectDir, "todos");
33
- return join(todosDir, `${sessionId}.json`);
30
+ function getSessionTodoPath(sessionId, projectPath) {
31
+ const effectiveProjectPath = projectPath || currentProjectPath || process.cwd();
32
+ const projectHash = getProjectHash(effectiveProjectPath);
33
+ return join(CONFIG_PATHS.sessions, projectHash, sessionId, "todos.json");
34
34
  }
35
- function initTodoSession(sessionId) {
35
+ function getTodoFilePath(sessionId, projectPath) {
36
+ const newPath = getSessionTodoPath(sessionId, projectPath);
37
+ if (existsSync(newPath)) {
38
+ return newPath;
39
+ }
40
+ const legacyPath = getLegacyTodoPath(sessionId);
41
+ if (existsSync(legacyPath)) {
42
+ return legacyPath;
43
+ }
44
+ return newPath;
45
+ }
46
+ function ensureTodoDirectory(filePath) {
47
+ const dir = join(filePath, "..");
48
+ if (!existsSync(dir)) {
49
+ mkdirSync(dir, { recursive: true });
50
+ }
51
+ }
52
+ function initTodoSession(sessionId, projectPath) {
36
53
  currentSessionId = sessionId;
54
+ currentProjectPath = projectPath || process.cwd();
37
55
  invalidateCache();
38
56
  }
39
57
  function getCurrentTodoSessionId() {
40
58
  return currentSessionId;
41
59
  }
60
+ function getCurrentProjectPath() {
61
+ return currentProjectPath;
62
+ }
42
63
  function readSessionTodos(sessionId) {
43
- const filePath = getSessionTodoPath(sessionId);
64
+ const filePath = getTodoFilePath(sessionId, currentProjectPath || void 0);
44
65
  if (!existsSync(filePath)) {
45
66
  return [];
46
67
  }
@@ -52,12 +73,12 @@ function readSessionTodos(sessionId) {
52
73
  }
53
74
  }
54
75
  function writeSessionTodos(sessionId, todos) {
55
- const filePath = getSessionTodoPath(sessionId);
56
- const todosDir = join(paths.cache, getProjectDir(process.cwd()), "todos");
76
+ const filePath = getSessionTodoPath(
77
+ sessionId,
78
+ currentProjectPath || void 0
79
+ );
57
80
  try {
58
- if (!existsSync(todosDir)) {
59
- mkdirSync(todosDir, { recursive: true });
60
- }
81
+ ensureTodoDirectory(filePath);
61
82
  if (todos.length === 0) {
62
83
  if (existsSync(filePath)) {
63
84
  unlinkSync(filePath);
@@ -71,10 +92,20 @@ function writeSessionTodos(sessionId, todos) {
71
92
  function deleteSessionTodos(sessionId) {
72
93
  const targetSessionId = sessionId || currentSessionId;
73
94
  if (!targetSessionId) return;
74
- const filePath = getSessionTodoPath(targetSessionId);
95
+ const newPath = getSessionTodoPath(
96
+ targetSessionId,
97
+ currentProjectPath || void 0
98
+ );
99
+ try {
100
+ if (existsSync(newPath)) {
101
+ unlinkSync(newPath);
102
+ }
103
+ } catch {
104
+ }
105
+ const legacyPath = getLegacyTodoPath(targetSessionId);
75
106
  try {
76
- if (existsSync(filePath)) {
77
- unlinkSync(filePath);
107
+ if (existsSync(legacyPath)) {
108
+ unlinkSync(legacyPath);
78
109
  }
79
110
  } catch {
80
111
  }
@@ -363,6 +394,7 @@ export {
363
394
  clearTodos,
364
395
  deleteSessionTodos,
365
396
  deleteTodo,
397
+ getCurrentProjectPath,
366
398
  getCurrentTodoSessionId,
367
399
  getTodoById,
368
400
  getTodoConfig,