@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.
- package/{cli.js → cli.cjs} +25 -23
- package/dist/commands/agents/AgentsCommand.js +459 -655
- package/dist/commands/agents/AgentsCommand.js.map +2 -2
- package/dist/commands/agents/types.js +1 -0
- package/dist/commands/agents/types.js.map +2 -2
- package/dist/commands/agents/utils/fileOperations.js +96 -36
- package/dist/commands/agents/utils/fileOperations.js.map +3 -3
- package/dist/commands/agents/utils/index.js +3 -1
- package/dist/commands/agents/utils/index.js.map +2 -2
- package/dist/commands/context.js +54 -23
- package/dist/commands/context.js.map +2 -2
- package/dist/commands/export.js +673 -93
- package/dist/commands/export.js.map +2 -2
- package/dist/commands/language.js +110 -0
- package/dist/commands/language.js.map +7 -0
- package/dist/commands/mcp-interactive.js +419 -217
- package/dist/commands/mcp-interactive.js.map +2 -2
- package/dist/commands/model.js +415 -66
- package/dist/commands/model.js.map +2 -2
- package/dist/commands/new.js +56 -0
- package/dist/commands/new.js.map +7 -0
- package/dist/commands/permissions.js +75 -49
- package/dist/commands/permissions.js.map +2 -2
- package/dist/commands/plugin.js +882 -185
- package/dist/commands/plugin.js.map +3 -3
- package/dist/commands/resume.js +251 -16
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/sandbox.js +168 -70
- package/dist/commands/sandbox.js.map +2 -2
- package/dist/commands/sessions.js +224 -0
- package/dist/commands/sessions.js.map +7 -0
- package/dist/commands/setup.js +596 -109
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/stats.js +292 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/status.js +75 -7
- package/dist/commands/status.js.map +2 -2
- package/dist/commands/undo.js +154 -180
- package/dist/commands/undo.js.map +2 -2
- package/dist/commands.js +6 -0
- package/dist/commands.js.map +2 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js +3 -2
- package/dist/components/AskUserQuestionDialog/AskUserQuestionDialog.js.map +2 -2
- package/dist/components/Config.js +9 -8
- package/dist/components/Config.js.map +2 -2
- package/dist/components/HeaderBar.js +2 -1
- package/dist/components/HeaderBar.js.map +2 -2
- package/dist/components/Help.js +166 -32
- package/dist/components/Help.js.map +2 -2
- package/dist/components/HotkeyHelpPanel.js +46 -44
- package/dist/components/HotkeyHelpPanel.js.map +2 -2
- package/dist/components/InfoPanel/InfoPanel.js +123 -0
- package/dist/components/InfoPanel/InfoPanel.js.map +7 -0
- package/dist/components/InfoPanel/index.js +5 -0
- package/dist/components/InfoPanel/index.js.map +7 -0
- package/dist/components/InfoPanel/types.js +1 -0
- package/dist/components/InfoPanel/types.js.map +7 -0
- package/dist/components/Logo.js +5 -2
- package/dist/components/Logo.js.map +2 -2
- package/dist/components/MCPServerApprovalDialog.js +6 -5
- package/dist/components/MCPServerApprovalDialog.js.map +2 -2
- package/dist/components/MCPServerMultiselectDialog.js +5 -4
- package/dist/components/MCPServerMultiselectDialog.js.map +2 -2
- package/dist/components/MessageSelector.js +4 -3
- package/dist/components/MessageSelector.js.map +2 -2
- package/dist/components/ModelConfig.js +13 -12
- package/dist/components/ModelConfig.js.map +2 -2
- package/dist/components/ModelListManager.js +4 -3
- package/dist/components/ModelListManager.js.map +2 -2
- package/dist/components/ModelSelector/BrandTextInput.js +43 -0
- package/dist/components/ModelSelector/BrandTextInput.js.map +7 -0
- package/dist/components/ModelSelector/ModelSelector.js +419 -501
- package/dist/components/ModelSelector/ModelSelector.js.map +2 -2
- package/dist/components/ModelSelector/WizardContainer.js +45 -0
- package/dist/components/ModelSelector/WizardContainer.js.map +7 -0
- package/dist/components/ModelSelector/index.js +1 -3
- package/dist/components/ModelSelector/index.js.map +2 -2
- package/dist/components/PromptInput.js +77 -44
- package/dist/components/PromptInput.js.map +2 -2
- package/dist/components/SensitiveFileWarning.js +12 -8
- package/dist/components/SensitiveFileWarning.js.map +2 -2
- package/dist/components/SimpleSelector/SimpleSelector.js +154 -0
- package/dist/components/SimpleSelector/SimpleSelector.js.map +7 -0
- package/dist/components/SimpleSelector/index.js +5 -0
- package/dist/components/SimpleSelector/index.js.map +7 -0
- package/dist/components/SimpleSelector/types.js +1 -0
- package/dist/components/SimpleSelector/types.js.map +7 -0
- package/dist/components/StatusOverlayContent.js +21 -0
- package/dist/components/StatusOverlayContent.js.map +7 -0
- package/dist/components/TabbedListView/ScrollableList.js +117 -0
- package/dist/components/TabbedListView/ScrollableList.js.map +7 -0
- package/dist/components/TabbedListView/SearchInput.js +23 -0
- package/dist/components/TabbedListView/SearchInput.js.map +7 -0
- package/dist/components/TabbedListView/TabBar.js +20 -0
- package/dist/components/TabbedListView/TabBar.js.map +7 -0
- package/dist/components/TabbedListView/TabbedListView.js +246 -0
- package/dist/components/TabbedListView/TabbedListView.js.map +7 -0
- package/dist/components/TabbedListView/index.js +11 -0
- package/dist/components/TabbedListView/index.js.map +7 -0
- package/dist/components/TabbedListView/types.js +1 -0
- package/dist/components/TabbedListView/types.js.map +7 -0
- package/dist/components/TodoChangeBlock.js +6 -5
- package/dist/components/TodoChangeBlock.js.map +3 -3
- package/dist/components/TodoPanel.js +6 -3
- package/dist/components/TodoPanel.js.map +3 -3
- package/dist/components/TrustDialog.js +6 -5
- package/dist/components/TrustDialog.js.map +2 -2
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js +2 -1
- package/dist/components/messages/UserToolResultMessage/UserToolCanceledMessage.js.map +2 -2
- package/dist/constants/macros.js +1 -1
- package/dist/constants/macros.js.map +1 -1
- package/dist/constants/product.js +2 -2
- package/dist/constants/product.js.map +1 -1
- package/dist/constants/prompts.js +17 -0
- package/dist/constants/prompts.js.map +2 -2
- package/dist/constants/toolInputExamples.js +5 -1
- package/dist/constants/toolInputExamples.js.map +2 -2
- package/dist/core/backupHook.js +29 -0
- package/dist/core/backupHook.js.map +7 -0
- package/dist/core/config/defaults.js +8 -2
- package/dist/core/config/defaults.js.map +2 -2
- package/dist/core/config/schema.js +14 -2
- package/dist/core/config/schema.js.map +2 -2
- package/dist/core/costTracker.js +0 -16
- package/dist/core/costTracker.js.map +2 -2
- package/dist/core/tokenStatsManager.js +5 -0
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/cost-tracker.js +0 -16
- package/dist/cost-tracker.js.map +2 -2
- package/dist/entrypoints/bootstrap.js +56 -0
- package/dist/entrypoints/bootstrap.js.map +7 -0
- package/dist/entrypoints/cli.js +164 -23
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/history.js +75 -15
- package/dist/history.js.map +2 -2
- package/dist/i18n/index.js +2 -2
- package/dist/i18n/index.js.map +2 -2
- package/dist/i18n/locales/en.js +582 -1
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +582 -1
- package/dist/i18n/locales/zh-CN.js.map +2 -2
- package/dist/i18n/types.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +2 -2
- package/dist/messages.js +11 -0
- package/dist/messages.js.map +2 -2
- package/dist/permissions.js.map +2 -2
- package/dist/query.js +9 -0
- package/dist/query.js.map +2 -2
- package/dist/screens/REPL.js +45 -7
- package/dist/screens/REPL.js.map +2 -2
- package/dist/services/customCommands.js +44 -16
- package/dist/services/customCommands.js.map +2 -2
- package/dist/services/plugins/lspServers.js +1 -1
- package/dist/services/plugins/lspServers.js.map +2 -2
- package/dist/services/plugins/pluginRuntime.js +2 -1
- package/dist/services/plugins/pluginRuntime.js.map +2 -2
- package/dist/services/plugins/pluginValidation.js +10 -3
- package/dist/services/plugins/pluginValidation.js.map +2 -2
- package/dist/services/plugins/skillMarketplace.js +16 -8
- package/dist/services/plugins/skillMarketplace.js.map +2 -2
- package/dist/services/systemReminder.js +17 -6
- package/dist/services/systemReminder.js.map +2 -2
- package/dist/tools/FileEditTool/FileEditTool.js +7 -0
- package/dist/tools/FileEditTool/FileEditTool.js.map +2 -2
- package/dist/tools/FileWriteTool/FileWriteTool.js +7 -0
- package/dist/tools/FileWriteTool/FileWriteTool.js.map +2 -2
- package/dist/tools/MultiEditTool/MultiEditTool.js +7 -0
- package/dist/tools/MultiEditTool/MultiEditTool.js.map +2 -2
- package/dist/tools/NotebookEditTool/NotebookEditTool.js +2 -0
- package/dist/tools/NotebookEditTool/NotebookEditTool.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +179 -1
- package/dist/tools/TaskTool/TaskTool.js.map +2 -2
- package/dist/tools/TodoWriteTool/prompt.js +21 -0
- package/dist/tools/TodoWriteTool/prompt.js.map +2 -2
- package/dist/tools/URLFetcherTool/prompt.js +14 -9
- package/dist/tools/URLFetcherTool/prompt.js.map +2 -2
- package/dist/tools/WebSearchTool/prompt.js +12 -6
- package/dist/tools/WebSearchTool/prompt.js.map +2 -2
- package/dist/types/PermissionMode.js +30 -1
- package/dist/types/PermissionMode.js.map +2 -2
- package/dist/types/plugin.js +2 -4
- package/dist/types/plugin.js.map +2 -2
- package/dist/utils/agentHookExecutor.js +103 -0
- package/dist/utils/agentHookExecutor.js.map +7 -0
- package/dist/utils/agentLoader.js +272 -32
- package/dist/utils/agentLoader.js.map +2 -2
- package/dist/utils/agentMemory.js +134 -0
- package/dist/utils/agentMemory.js.map +7 -0
- package/dist/utils/claudeCodeSync.js +439 -0
- package/dist/utils/claudeCodeSync.js.map +7 -0
- package/dist/utils/config.js +52 -24
- package/dist/utils/config.js.map +2 -2
- package/dist/utils/configPaths.js +199 -0
- package/dist/utils/configPaths.js.map +7 -0
- package/dist/utils/execFileNoThrow.js +2 -1
- package/dist/utils/execFileNoThrow.js.map +2 -2
- package/dist/utils/historyManager.js +234 -0
- package/dist/utils/historyManager.js.map +7 -0
- package/dist/utils/marketplaceManager.js +80 -43
- package/dist/utils/marketplaceManager.js.map +2 -2
- package/dist/utils/messages.js +13 -8
- package/dist/utils/messages.js.map +2 -2
- package/dist/utils/migration/index.js +37 -0
- package/dist/utils/migration/index.js.map +7 -0
- package/dist/utils/migration/migrateHistory.js +273 -0
- package/dist/utils/migration/migrateHistory.js.map +7 -0
- package/dist/utils/migration/migrateTodos.js +323 -0
- package/dist/utils/migration/migrateTodos.js.map +7 -0
- package/dist/utils/pasteCache.js +309 -0
- package/dist/utils/pasteCache.js.map +7 -0
- package/dist/utils/pluginInstaller.js +34 -24
- package/dist/utils/pluginInstaller.js.map +2 -2
- package/dist/utils/pluginLoader.js +54 -28
- package/dist/utils/pluginLoader.js.map +2 -2
- package/dist/utils/repoFetcher.js +110 -0
- package/dist/utils/repoFetcher.js.map +7 -0
- package/dist/utils/sessionIndex.js +192 -0
- package/dist/utils/sessionIndex.js.map +7 -0
- package/dist/utils/sessionTracker.js +170 -0
- package/dist/utils/sessionTracker.js.map +7 -0
- package/dist/utils/skillLoader.js +103 -5
- package/dist/utils/skillLoader.js.map +2 -2
- package/dist/utils/stats.js +417 -0
- package/dist/utils/stats.js.map +7 -0
- package/dist/utils/stringSubstitution.js +106 -0
- package/dist/utils/stringSubstitution.js.map +7 -0
- package/dist/utils/teamConfig.js +156 -14
- package/dist/utils/teamConfig.js.map +2 -2
- package/dist/utils/terminal.js +1 -1
- package/dist/utils/terminal.js.map +2 -2
- package/dist/utils/todoStorage.js +51 -19
- package/dist/utils/todoStorage.js.map +2 -2
- package/dist/utils/tooling/safeRender.js.map +2 -2
- package/dist/version.js +2 -2
- package/dist/version.js.map +1 -1
- package/package.json +71 -28
- package/scripts/{postinstall.js → postinstall.cjs} +1 -1
package/dist/utils/teamConfig.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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", {
|
|
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
|
|
408
|
-
|
|
409
|
-
|
|
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
|
}
|
package/dist/utils/terminal.js
CHANGED
|
@@ -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
|
|
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;
|
|
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
|
|
12
|
-
import {
|
|
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
|
-
|
|
27
|
-
function
|
|
28
|
-
return
|
|
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
|
|
32
|
-
const
|
|
33
|
-
return join(
|
|
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
|
|
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 =
|
|
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(
|
|
56
|
-
|
|
76
|
+
const filePath = getSessionTodoPath(
|
|
77
|
+
sessionId,
|
|
78
|
+
currentProjectPath || void 0
|
|
79
|
+
);
|
|
57
80
|
try {
|
|
58
|
-
|
|
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
|
|
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(
|
|
77
|
-
unlinkSync(
|
|
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,
|