@within-7/minto 0.3.5 → 0.3.9
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/language.js +137 -0
- package/dist/commands/language.js.map +7 -0
- package/dist/commands/new.js +56 -0
- package/dist/commands/new.js.map +7 -0
- package/dist/commands/resume.js +251 -16
- package/dist/commands/resume.js.map +2 -2
- package/dist/commands/sessions.js +224 -0
- package/dist/commands/sessions.js.map +7 -0
- package/dist/commands/setup.js +3 -2
- package/dist/commands/setup.js.map +2 -2
- package/dist/commands/stats.js +235 -0
- package/dist/commands/stats.js.map +7 -0
- package/dist/commands/status.js +11 -5
- package/dist/commands/status.js.map +2 -2
- package/dist/commands/undo.js +26 -16
- 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 +2 -1
- 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/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/PromptInput.js +72 -39
- 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/TabbedListView/ScrollableList.js +91 -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 +171 -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/tokenStatsManager.js +5 -0
- package/dist/core/tokenStatsManager.js.map +2 -2
- package/dist/entrypoints/bootstrap.js +54 -0
- package/dist/entrypoints/bootstrap.js.map +7 -0
- package/dist/entrypoints/cli.js +132 -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 +283 -1
- package/dist/i18n/locales/en.js.map +2 -2
- package/dist/i18n/locales/zh-CN.js +283 -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 +14 -8
- package/dist/services/customCommands.js.map +2 -2
- package/dist/tools/TaskTool/TaskTool.js +176 -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.map +2 -2
- package/dist/utils/agentHookExecutor.js +106 -0
- package/dist/utils/agentHookExecutor.js.map +7 -0
- package/dist/utils/agentLoader.js +212 -26
- 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/config.js +51 -1
- 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/historyManager.js +234 -0
- package/dist/utils/historyManager.js.map +7 -0
- 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/pluginLoader.js +6 -3
- package/dist/utils/pluginLoader.js.map +2 -2
- 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 +91 -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 +107 -0
- package/dist/utils/stringSubstitution.js.map +7 -0
- package/dist/utils/teamConfig.js +3 -1
- package/dist/utils/teamConfig.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
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import { promisify } from "util";
|
|
3
|
+
import { getCwd } from "./state.js";
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
const DEFAULT_HOOK_TIMEOUT = 6e4;
|
|
6
|
+
async function executeHook(hook, context) {
|
|
7
|
+
const startTime = Date.now();
|
|
8
|
+
const timeout = (hook.timeout ?? 60) * 1e3;
|
|
9
|
+
try {
|
|
10
|
+
if (hook.type === "command" && hook.command) {
|
|
11
|
+
const { stdout, stderr } = await execAsync(hook.command, {
|
|
12
|
+
timeout: Math.min(timeout, DEFAULT_HOOK_TIMEOUT),
|
|
13
|
+
cwd: context.cwd,
|
|
14
|
+
env: {
|
|
15
|
+
...process.env,
|
|
16
|
+
...context.env,
|
|
17
|
+
AGENT_ID: context.agentId,
|
|
18
|
+
AGENT_TYPE: context.agentType,
|
|
19
|
+
SESSION_ID: context.sessionId,
|
|
20
|
+
HOOK_CWD: context.cwd
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
let parsedOutput = null;
|
|
24
|
+
try {
|
|
25
|
+
if (stdout.trim().startsWith("{")) {
|
|
26
|
+
parsedOutput = JSON.parse(stdout.trim());
|
|
27
|
+
}
|
|
28
|
+
} catch {
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
success: true,
|
|
32
|
+
continue: parsedOutput?.continue !== false,
|
|
33
|
+
reason: parsedOutput?.stopReason,
|
|
34
|
+
output: stdout,
|
|
35
|
+
executionTime: Date.now() - startTime
|
|
36
|
+
};
|
|
37
|
+
} else if (hook.type === "prompt" && hook.prompt) {
|
|
38
|
+
return {
|
|
39
|
+
success: true,
|
|
40
|
+
continue: true,
|
|
41
|
+
output: hook.prompt,
|
|
42
|
+
executionTime: Date.now() - startTime
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
success: false,
|
|
47
|
+
continue: true,
|
|
48
|
+
reason: "Invalid hook configuration: missing command or prompt",
|
|
49
|
+
executionTime: Date.now() - startTime
|
|
50
|
+
};
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return {
|
|
53
|
+
success: false,
|
|
54
|
+
continue: true,
|
|
55
|
+
// Default to continue on error
|
|
56
|
+
error: error instanceof Error ? error : new Error(String(error)),
|
|
57
|
+
executionTime: Date.now() - startTime
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function executeAgentHooks(event, agentConfig, context) {
|
|
62
|
+
const hooks = agentConfig.hooks?.[event];
|
|
63
|
+
if (!hooks || hooks.length === 0) {
|
|
64
|
+
return { continue: true, outputs: [] };
|
|
65
|
+
}
|
|
66
|
+
const outputs = [];
|
|
67
|
+
let shouldContinue = true;
|
|
68
|
+
let stopReason;
|
|
69
|
+
for (const hook of hooks) {
|
|
70
|
+
const result = await executeHook(hook, context);
|
|
71
|
+
if (result.output) {
|
|
72
|
+
outputs.push(result.output);
|
|
73
|
+
}
|
|
74
|
+
if (!result.continue) {
|
|
75
|
+
shouldContinue = false;
|
|
76
|
+
stopReason = result.reason || "Hook requested stop";
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
if (!result.success && result.error) {
|
|
80
|
+
console.warn(
|
|
81
|
+
`Hook ${event} execution failed:`,
|
|
82
|
+
result.error.message
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return {
|
|
87
|
+
continue: shouldContinue,
|
|
88
|
+
reason: stopReason,
|
|
89
|
+
outputs
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function createHookContext(params) {
|
|
93
|
+
return {
|
|
94
|
+
sessionId: params.sessionId,
|
|
95
|
+
agentId: params.agentId,
|
|
96
|
+
agentType: params.agentType,
|
|
97
|
+
cwd: getCwd(),
|
|
98
|
+
error: params.error,
|
|
99
|
+
result: params.result
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export {
|
|
103
|
+
createHookContext,
|
|
104
|
+
executeAgentHooks
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=agentHookExecutor.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/utils/agentHookExecutor.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Agent Hook Executor\n *\n * Executes lifecycle hooks for agents as defined in Claude Code specification.\n * Supports onStart, onComplete, and onError hooks with security controls.\n */\n\nimport { exec } from 'child_process'\nimport { promisify } from 'util'\nimport type { HookDefinition } from '@minto-types/hooks'\nimport type { AgentConfig, AgentHooks } from './agentLoader'\nimport { getCwd } from './state'\n\nconst execAsync = promisify(exec)\n\n/**\n * Hook execution context\n */\nexport interface HookExecutionContext {\n sessionId: string\n agentId: string\n agentType: string\n cwd: string\n env?: Record<string, string>\n error?: Error // For onError hooks\n result?: string // For onComplete hooks\n}\n\n/**\n * Hook execution result\n */\nexport interface HookExecutionResult {\n success: boolean\n continue: boolean\n reason?: string\n output?: string\n error?: Error\n executionTime: number\n}\n\n/**\n * Default hook timeout in milliseconds\n */\nconst DEFAULT_HOOK_TIMEOUT = 60000 // 60 seconds\n\n/**\n * Execute a single hook\n */\nasync function executeHook(\n hook: HookDefinition,\n context: HookExecutionContext,\n): Promise<HookExecutionResult> {\n const startTime = Date.now()\n const timeout = (hook.timeout ?? 60) * 1000 // Convert seconds to milliseconds\n\n try {\n if (hook.type === 'command' && hook.command) {\n // Execute shell command\n const { stdout, stderr } = await execAsync(hook.command, {\n timeout: Math.min(timeout, DEFAULT_HOOK_TIMEOUT),\n cwd: context.cwd,\n env: {\n ...process.env,\n ...context.env,\n AGENT_ID: context.agentId,\n AGENT_TYPE: context.agentType,\n SESSION_ID: context.sessionId,\n HOOK_CWD: context.cwd,\n },\n })\n\n // Try to parse JSON output for hook control\n let parsedOutput: any = null\n try {\n if (stdout.trim().startsWith('{')) {\n parsedOutput = JSON.parse(stdout.trim())\n }\n } catch {\n // Not JSON, that's fine\n }\n\n return {\n success: true,\n continue: parsedOutput?.continue !== false,\n reason: parsedOutput?.stopReason,\n output: stdout,\n executionTime: Date.now() - startTime,\n }\n } else if (hook.type === 'prompt' && hook.prompt) {\n // Prompt hooks are handled by the agent system\n // For now, we just return success and let the caller handle the prompt\n return {\n success: true,\n continue: true,\n output: hook.prompt,\n executionTime: Date.now() - startTime,\n }\n }\n\n // Invalid hook configuration\n return {\n success: false,\n continue: true,\n reason: 'Invalid hook configuration: missing command or prompt',\n executionTime: Date.now() - startTime,\n }\n } catch (error) {\n return {\n success: false,\n continue: true, // Default to continue on error\n error: error instanceof Error ? error : new Error(String(error)),\n executionTime: Date.now() - startTime,\n }\n }\n}\n\n/**\n * Execute agent lifecycle hooks\n *\n * @param event - The lifecycle event (onStart, onComplete, onError)\n * @param agentConfig - The agent configuration containing hooks\n * @param context - The execution context\n * @returns Combined result of all hook executions\n */\nexport async function executeAgentHooks(\n event: keyof AgentHooks,\n agentConfig: AgentConfig,\n context: HookExecutionContext,\n): Promise<{ continue: boolean; reason?: string; outputs: string[] }> {\n const hooks = agentConfig.hooks?.[event]\n\n if (!hooks || hooks.length === 0) {\n return { continue: true, outputs: [] }\n }\n\n const outputs: string[] = []\n let shouldContinue = true\n let stopReason: string | undefined\n\n for (const hook of hooks) {\n const result = await executeHook(hook, context)\n\n if (result.output) {\n outputs.push(result.output)\n }\n\n if (!result.continue) {\n shouldContinue = false\n stopReason = result.reason || 'Hook requested stop'\n break // Stop executing further hooks\n }\n\n if (!result.success && result.error) {\n console.warn(\n `Hook ${event} execution failed:`,\n result.error.message,\n )\n // Continue to next hook on error by default\n }\n }\n\n return {\n continue: shouldContinue,\n reason: stopReason,\n outputs,\n }\n}\n\n/**\n * Create hook execution context from agent execution state\n */\nexport function createHookContext(params: {\n sessionId: string\n agentId: string\n agentType: string\n error?: Error\n result?: string\n}): HookExecutionContext {\n return {\n sessionId: params.sessionId,\n agentId: params.agentId,\n agentType: params.agentType,\n cwd: getCwd(),\n error: params.error,\n result: params.result,\n }\n}\n"],
|
|
5
|
+
"mappings": "AAOA,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAG1B,SAAS,cAAc;AAEvB,MAAM,YAAY,UAAU,IAAI;AA8BhC,MAAM,uBAAuB;AAK7B,eAAe,YACb,MACA,SAC8B;AAC9B,QAAM,YAAY,KAAK,IAAI;AAC3B,QAAM,WAAW,KAAK,WAAW,MAAM;AAEvC,MAAI;AACF,QAAI,KAAK,SAAS,aAAa,KAAK,SAAS;AAE3C,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU,KAAK,SAAS;AAAA,QACvD,SAAS,KAAK,IAAI,SAAS,oBAAoB;AAAA,QAC/C,KAAK,QAAQ;AAAA,QACb,KAAK;AAAA,UACH,GAAG,QAAQ;AAAA,UACX,GAAG,QAAQ;AAAA,UACX,UAAU,QAAQ;AAAA,UAClB,YAAY,QAAQ;AAAA,UACpB,YAAY,QAAQ;AAAA,UACpB,UAAU,QAAQ;AAAA,QACpB;AAAA,MACF,CAAC;AAGD,UAAI,eAAoB;AACxB,UAAI;AACF,YAAI,OAAO,KAAK,EAAE,WAAW,GAAG,GAAG;AACjC,yBAAe,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,QACzC;AAAA,MACF,QAAQ;AAAA,MAER;AAEA,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU,cAAc,aAAa;AAAA,QACrC,QAAQ,cAAc;AAAA,QACtB,QAAQ;AAAA,QACR,eAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF,WAAW,KAAK,SAAS,YAAY,KAAK,QAAQ;AAGhD,aAAO;AAAA,QACL,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,KAAK;AAAA,QACb,eAAe,KAAK,IAAI,IAAI;AAAA,MAC9B;AAAA,IACF;AAGA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,eAAe,KAAK,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF,SAAS,OAAO;AACd,WAAO;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA;AAAA,MACV,OAAO,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AAAA,MAC/D,eAAe,KAAK,IAAI,IAAI;AAAA,IAC9B;AAAA,EACF;AACF;AAUA,eAAsB,kBACpB,OACA,aACA,SACoE;AACpE,QAAM,QAAQ,YAAY,QAAQ,KAAK;AAEvC,MAAI,CAAC,SAAS,MAAM,WAAW,GAAG;AAChC,WAAO,EAAE,UAAU,MAAM,SAAS,CAAC,EAAE;AAAA,EACvC;AAEA,QAAM,UAAoB,CAAC;AAC3B,MAAI,iBAAiB;AACrB,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,MAAM,YAAY,MAAM,OAAO;AAE9C,QAAI,OAAO,QAAQ;AACjB,cAAQ,KAAK,OAAO,MAAM;AAAA,IAC5B;AAEA,QAAI,CAAC,OAAO,UAAU;AACpB,uBAAiB;AACjB,mBAAa,OAAO,UAAU;AAC9B;AAAA,IACF;AAEA,QAAI,CAAC,OAAO,WAAW,OAAO,OAAO;AACnC,cAAQ;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,OAAO,MAAM;AAAA,MACf;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU;AAAA,IACV,QAAQ;AAAA,IACR;AAAA,EACF;AACF;AAKO,SAAS,kBAAkB,QAMT;AACvB,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,IAClB,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO;AAAA,IACd,QAAQ,OAAO;AAAA,EACjB;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -12,25 +12,117 @@ import { getCwd } from "./state.js";
|
|
|
12
12
|
import { memoize } from "lodash-es";
|
|
13
13
|
import { loadAllPlugins } from "./pluginLoader.js";
|
|
14
14
|
const warnedAgents = /* @__PURE__ */ new Set();
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
const BUILTIN_AGENTS = [
|
|
16
|
+
// general-purpose: Default agent for multi-step tasks
|
|
17
|
+
{
|
|
18
|
+
agentType: "general-purpose",
|
|
19
|
+
whenToUse: "General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent.",
|
|
20
|
+
tools: "*",
|
|
21
|
+
systemPrompt: `You are a general-purpose agent. Given the user's task, use the tools available to complete it efficiently and thoroughly.
|
|
20
22
|
|
|
21
23
|
When to use your capabilities:
|
|
22
24
|
- Searching for code, configurations, and patterns across large codebases
|
|
23
|
-
- Analyzing multiple files to understand system architecture
|
|
25
|
+
- Analyzing multiple files to understand system architecture
|
|
24
26
|
- Investigating complex questions that require exploring many files
|
|
25
27
|
- Performing multi-step research tasks
|
|
26
28
|
|
|
27
29
|
Guidelines:
|
|
28
|
-
- For file searches: Use Grep or Glob when you need to search broadly. Use
|
|
30
|
+
- For file searches: Use Grep or Glob when you need to search broadly. Use Read when you know the specific file path.
|
|
29
31
|
- For analysis: Start broad and narrow down. Use multiple search strategies if the first doesn't yield results.
|
|
30
32
|
- Be thorough: Check multiple locations, consider different naming conventions, look for related files.
|
|
31
33
|
- Complete tasks directly using your capabilities.`,
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
+
location: "built-in"
|
|
35
|
+
},
|
|
36
|
+
// Explore: Fast read-only codebase exploration (Claude Code spec)
|
|
37
|
+
{
|
|
38
|
+
agentType: "Explore",
|
|
39
|
+
whenToUse: 'Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns, search code for keywords, or answer questions about the codebase. Specify thoroughness: "quick" for basic searches, "medium" for moderate exploration, "very thorough" for comprehensive analysis.',
|
|
40
|
+
tools: ["Read", "Glob", "Grep", "LS", "WebSearch", "WebFetch"],
|
|
41
|
+
disallowedTools: ["Edit", "Write", "Bash", "NotebookEdit"],
|
|
42
|
+
model_name: "quick",
|
|
43
|
+
// Maps to haiku equivalent
|
|
44
|
+
permissionMode: "plan",
|
|
45
|
+
// Read-only mode
|
|
46
|
+
systemPrompt: `You are an exploration agent optimized for fast codebase searches and understanding.
|
|
47
|
+
|
|
48
|
+
Your role:
|
|
49
|
+
- Quickly find files, functions, classes, and patterns
|
|
50
|
+
- Understand code structure and architecture
|
|
51
|
+
- Answer questions about how code works
|
|
52
|
+
- Identify relevant files for a given task
|
|
53
|
+
|
|
54
|
+
Guidelines:
|
|
55
|
+
- Use Glob for finding files by pattern (e.g., "**/*.tsx", "src/**/*.ts")
|
|
56
|
+
- Use Grep for searching code content (e.g., function names, imports, patterns)
|
|
57
|
+
- Use Read to examine specific files you've identified
|
|
58
|
+
- Start broad, then narrow down based on results
|
|
59
|
+
- Report findings with specific file paths and line numbers
|
|
60
|
+
- Be thorough but efficient - check multiple locations and naming conventions
|
|
61
|
+
|
|
62
|
+
You are READ-ONLY. You cannot modify any files.`,
|
|
63
|
+
location: "built-in"
|
|
64
|
+
},
|
|
65
|
+
// Plan: Research and planning agent (Claude Code spec)
|
|
66
|
+
{
|
|
67
|
+
agentType: "Plan",
|
|
68
|
+
whenToUse: "Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs.",
|
|
69
|
+
tools: ["Read", "Glob", "Grep", "LS", "WebSearch", "WebFetch", "Think"],
|
|
70
|
+
disallowedTools: ["Edit", "Write", "Bash", "NotebookEdit"],
|
|
71
|
+
model_name: "inherit",
|
|
72
|
+
// Inherit caller's model
|
|
73
|
+
permissionMode: "plan",
|
|
74
|
+
// Read-only mode
|
|
75
|
+
systemPrompt: `You are a planning agent specialized in analyzing codebases and creating implementation plans.
|
|
76
|
+
|
|
77
|
+
Your role:
|
|
78
|
+
- Understand requirements and constraints
|
|
79
|
+
- Analyze existing code patterns and architecture
|
|
80
|
+
- Create detailed, step-by-step implementation plans
|
|
81
|
+
- Identify potential issues and trade-offs
|
|
82
|
+
- Recommend best approaches based on codebase conventions
|
|
83
|
+
|
|
84
|
+
Guidelines:
|
|
85
|
+
- Read relevant files to understand current patterns
|
|
86
|
+
- Identify all files that will need modification
|
|
87
|
+
- Consider edge cases and error handling
|
|
88
|
+
- Note any dependencies or prerequisites
|
|
89
|
+
- Provide specific, actionable steps
|
|
90
|
+
|
|
91
|
+
Output format:
|
|
92
|
+
1. Summary of the task
|
|
93
|
+
2. Files to modify/create (with paths)
|
|
94
|
+
3. Step-by-step implementation plan
|
|
95
|
+
4. Potential challenges or considerations
|
|
96
|
+
5. Testing approach
|
|
97
|
+
|
|
98
|
+
You are READ-ONLY. You cannot modify any files. Focus on planning, not execution.`,
|
|
99
|
+
location: "built-in"
|
|
100
|
+
},
|
|
101
|
+
// Bash: Shell command execution agent (Claude Code spec)
|
|
102
|
+
{
|
|
103
|
+
agentType: "Bash",
|
|
104
|
+
whenToUse: "Command execution specialist for running bash commands. Use this for git operations, command execution, and other terminal tasks.",
|
|
105
|
+
tools: ["Bash", "Read", "LS"],
|
|
106
|
+
systemPrompt: `You are a bash execution agent specialized in running shell commands.
|
|
107
|
+
|
|
108
|
+
Your role:
|
|
109
|
+
- Execute shell commands safely and effectively
|
|
110
|
+
- Handle build, test, and deployment tasks
|
|
111
|
+
- Manage git operations
|
|
112
|
+
- Run scripts and automation
|
|
113
|
+
|
|
114
|
+
Guidelines:
|
|
115
|
+
- Check command syntax before execution
|
|
116
|
+
- Handle errors gracefully with clear messages
|
|
117
|
+
- Report command output and exit codes
|
|
118
|
+
- Be cautious with destructive commands (rm, git reset, etc.)
|
|
119
|
+
- Use appropriate flags for verbose output when debugging
|
|
120
|
+
- Chain commands with && for dependent operations
|
|
121
|
+
|
|
122
|
+
Always explain what a command will do before running it if it modifies the system.`,
|
|
123
|
+
location: "built-in"
|
|
124
|
+
}
|
|
125
|
+
];
|
|
34
126
|
function parseTools(tools) {
|
|
35
127
|
if (!tools) return "*";
|
|
36
128
|
if (tools === "*") return "*";
|
|
@@ -41,10 +133,76 @@ function parseTools(tools) {
|
|
|
41
133
|
return filteredTools.length > 0 ? filteredTools : "*";
|
|
42
134
|
}
|
|
43
135
|
if (typeof tools === "string") {
|
|
136
|
+
if (tools.includes(",")) {
|
|
137
|
+
return tools.split(",").map((t) => t.trim()).filter(Boolean);
|
|
138
|
+
}
|
|
44
139
|
return [tools];
|
|
45
140
|
}
|
|
46
141
|
return "*";
|
|
47
142
|
}
|
|
143
|
+
function parseDisallowedTools(disallowedTools) {
|
|
144
|
+
if (!disallowedTools) return void 0;
|
|
145
|
+
if (Array.isArray(disallowedTools)) {
|
|
146
|
+
const filtered = disallowedTools.filter(
|
|
147
|
+
(t) => typeof t === "string"
|
|
148
|
+
);
|
|
149
|
+
return filtered.length > 0 ? filtered : void 0;
|
|
150
|
+
}
|
|
151
|
+
if (typeof disallowedTools === "string") {
|
|
152
|
+
if (disallowedTools.includes(",")) {
|
|
153
|
+
return disallowedTools.split(",").map((t) => t.trim()).filter(Boolean);
|
|
154
|
+
}
|
|
155
|
+
return [disallowedTools];
|
|
156
|
+
}
|
|
157
|
+
return void 0;
|
|
158
|
+
}
|
|
159
|
+
function parseSkills(skills) {
|
|
160
|
+
if (!skills) return void 0;
|
|
161
|
+
if (Array.isArray(skills)) {
|
|
162
|
+
const filtered = skills.filter((s) => typeof s === "string");
|
|
163
|
+
return filtered.length > 0 ? filtered : void 0;
|
|
164
|
+
}
|
|
165
|
+
if (typeof skills === "string") {
|
|
166
|
+
if (skills.includes(",")) {
|
|
167
|
+
return skills.split(",").map((s) => s.trim()).filter(Boolean);
|
|
168
|
+
}
|
|
169
|
+
return [skills];
|
|
170
|
+
}
|
|
171
|
+
return void 0;
|
|
172
|
+
}
|
|
173
|
+
function parseMemory(memory) {
|
|
174
|
+
if (!memory) return void 0;
|
|
175
|
+
if (typeof memory === "string") {
|
|
176
|
+
if (["user", "project", "local"].includes(memory)) {
|
|
177
|
+
return { scope: memory };
|
|
178
|
+
}
|
|
179
|
+
return void 0;
|
|
180
|
+
}
|
|
181
|
+
if (typeof memory === "object") {
|
|
182
|
+
const scope = memory.scope;
|
|
183
|
+
if (["user", "project", "local"].includes(scope)) {
|
|
184
|
+
return {
|
|
185
|
+
scope,
|
|
186
|
+
...memory.key && { key: String(memory.key) }
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return void 0;
|
|
191
|
+
}
|
|
192
|
+
function parsePermissionMode(mode) {
|
|
193
|
+
if (!mode) return void 0;
|
|
194
|
+
const validModes = [
|
|
195
|
+
"default",
|
|
196
|
+
"acceptEdits",
|
|
197
|
+
"dontAsk",
|
|
198
|
+
"plan",
|
|
199
|
+
"bypassPermissions"
|
|
200
|
+
];
|
|
201
|
+
if (typeof mode === "string" && validModes.includes(mode)) {
|
|
202
|
+
return mode;
|
|
203
|
+
}
|
|
204
|
+
return void 0;
|
|
205
|
+
}
|
|
48
206
|
async function scanAgentDirectory(dirPath, location) {
|
|
49
207
|
if (!existsSync(dirPath)) {
|
|
50
208
|
return [];
|
|
@@ -72,15 +230,27 @@ async function scanAgentDirectory(dirPath, location) {
|
|
|
72
230
|
);
|
|
73
231
|
warnedAgents.add(frontmatter.name);
|
|
74
232
|
}
|
|
233
|
+
const disallowedTools = parseDisallowedTools(frontmatter.disallowedTools);
|
|
234
|
+
const skills = parseSkills(frontmatter.skills);
|
|
235
|
+
const memory = parseMemory(frontmatter.memory);
|
|
236
|
+
const permissionMode = parsePermissionMode(frontmatter.permissionMode);
|
|
75
237
|
const agent = {
|
|
76
238
|
agentType: frontmatter.name,
|
|
77
239
|
whenToUse: frontmatter.description.replace(/\\n/g, "\n"),
|
|
78
240
|
tools: parseTools(frontmatter.tools),
|
|
79
241
|
systemPrompt: body.trim(),
|
|
80
242
|
location,
|
|
243
|
+
// Optional fields - only include if defined
|
|
81
244
|
...frontmatter.color && { color: frontmatter.color },
|
|
82
|
-
|
|
83
|
-
...
|
|
245
|
+
...frontmatter.model_name && { model_name: frontmatter.model_name },
|
|
246
|
+
...disallowedTools && { disallowedTools },
|
|
247
|
+
...permissionMode && { permissionMode },
|
|
248
|
+
...skills && { skills },
|
|
249
|
+
...memory && { memory },
|
|
250
|
+
...frontmatter.maxThinkingTokens && {
|
|
251
|
+
maxThinkingTokens: Number(frontmatter.maxThinkingTokens)
|
|
252
|
+
},
|
|
253
|
+
...frontmatter.hooks && { hooks: frontmatter.hooks }
|
|
84
254
|
};
|
|
85
255
|
agents.push(agent);
|
|
86
256
|
} catch (error) {
|
|
@@ -114,6 +284,10 @@ async function loadPluginAgents() {
|
|
|
114
284
|
);
|
|
115
285
|
warnedAgents.add(frontmatter.name);
|
|
116
286
|
}
|
|
287
|
+
const disallowedTools = parseDisallowedTools(frontmatter.disallowedTools);
|
|
288
|
+
const skills = parseSkills(frontmatter.skills);
|
|
289
|
+
const memory = parseMemory(frontmatter.memory);
|
|
290
|
+
const permissionMode = parsePermissionMode(frontmatter.permissionMode);
|
|
117
291
|
const agent = {
|
|
118
292
|
agentType: frontmatter.name,
|
|
119
293
|
whenToUse: frontmatter.description.replace(/\\n/g, "\n"),
|
|
@@ -121,11 +295,17 @@ async function loadPluginAgents() {
|
|
|
121
295
|
systemPrompt: body.trim(),
|
|
122
296
|
location: "plugin",
|
|
123
297
|
pluginName: plugin.manifest.name,
|
|
298
|
+
// Optional fields
|
|
124
299
|
...frontmatter.color && { color: frontmatter.color },
|
|
125
|
-
|
|
126
|
-
...
|
|
127
|
-
|
|
128
|
-
}
|
|
300
|
+
...frontmatter.model_name && { model_name: frontmatter.model_name },
|
|
301
|
+
...disallowedTools && { disallowedTools },
|
|
302
|
+
...permissionMode && { permissionMode },
|
|
303
|
+
...skills && { skills },
|
|
304
|
+
...memory && { memory },
|
|
305
|
+
...frontmatter.maxThinkingTokens && {
|
|
306
|
+
maxThinkingTokens: Number(frontmatter.maxThinkingTokens)
|
|
307
|
+
},
|
|
308
|
+
...frontmatter.hooks && { hooks: frontmatter.hooks }
|
|
129
309
|
};
|
|
130
310
|
agents.push(agent);
|
|
131
311
|
} catch (error) {
|
|
@@ -143,16 +323,17 @@ async function loadPluginAgents() {
|
|
|
143
323
|
}
|
|
144
324
|
async function loadAllAgents() {
|
|
145
325
|
try {
|
|
146
|
-
const
|
|
147
|
-
const
|
|
326
|
+
const home = homedir();
|
|
327
|
+
const cwd = getCwd();
|
|
328
|
+
const userMintoDir = join(home, ".minto", "agents");
|
|
329
|
+
const projectMintoDir = join(cwd, ".minto", "agents");
|
|
148
330
|
const [pluginAgents, userMintoAgents, projectMintoAgents] = await Promise.all([
|
|
149
331
|
loadPluginAgents(),
|
|
150
332
|
scanAgentDirectory(userMintoDir, "user"),
|
|
151
333
|
scanAgentDirectory(projectMintoDir, "project")
|
|
152
334
|
]);
|
|
153
|
-
const builtinAgents = [BUILTIN_GENERAL_PURPOSE];
|
|
154
335
|
const agentMap = /* @__PURE__ */ new Map();
|
|
155
|
-
for (const agent of
|
|
336
|
+
for (const agent of BUILTIN_AGENTS) {
|
|
156
337
|
agentMap.set(agent.agentType, agent);
|
|
157
338
|
}
|
|
158
339
|
for (const agent of pluginAgents) {
|
|
@@ -166,7 +347,7 @@ async function loadAllAgents() {
|
|
|
166
347
|
}
|
|
167
348
|
const activeAgents = Array.from(agentMap.values());
|
|
168
349
|
const allAgents = [
|
|
169
|
-
...
|
|
350
|
+
...BUILTIN_AGENTS,
|
|
170
351
|
...pluginAgents,
|
|
171
352
|
...userMintoAgents,
|
|
172
353
|
...projectMintoAgents
|
|
@@ -175,8 +356,8 @@ async function loadAllAgents() {
|
|
|
175
356
|
} catch (error) {
|
|
176
357
|
console.error("Failed to load agents, falling back to built-in:", error);
|
|
177
358
|
return {
|
|
178
|
-
activeAgents: [
|
|
179
|
-
allAgents: [
|
|
359
|
+
activeAgents: [...BUILTIN_AGENTS],
|
|
360
|
+
allAgents: [...BUILTIN_AGENTS]
|
|
180
361
|
};
|
|
181
362
|
}
|
|
182
363
|
}
|
|
@@ -207,8 +388,12 @@ const getAvailableAgentTypes = memoize(async () => {
|
|
|
207
388
|
let watchers = [];
|
|
208
389
|
async function startAgentWatcher(onChange) {
|
|
209
390
|
await stopAgentWatcher();
|
|
210
|
-
const
|
|
211
|
-
const
|
|
391
|
+
const home = homedir();
|
|
392
|
+
const cwd = getCwd();
|
|
393
|
+
const directories = [
|
|
394
|
+
{ path: join(home, ".minto", "agents"), label: "user/.minto" },
|
|
395
|
+
{ path: join(cwd, ".minto", "agents"), label: "project/.minto" }
|
|
396
|
+
];
|
|
212
397
|
const watchDirectory = (dirPath, label) => {
|
|
213
398
|
if (existsSync(dirPath)) {
|
|
214
399
|
const watcher = watch(
|
|
@@ -228,8 +413,9 @@ async function startAgentWatcher(onChange) {
|
|
|
228
413
|
watchers.push(watcher);
|
|
229
414
|
}
|
|
230
415
|
};
|
|
231
|
-
|
|
232
|
-
|
|
416
|
+
for (const { path, label } of directories) {
|
|
417
|
+
watchDirectory(path, label);
|
|
418
|
+
}
|
|
233
419
|
}
|
|
234
420
|
async function stopAgentWatcher() {
|
|
235
421
|
try {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/utils/agentLoader.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Agent configuration loader\n * Loads agent configurations from markdown files with YAML frontmatter.\n * Uses only `.minto` directories for agent configuration.\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n watch,\n FSWatcher,\n} from 'fs'\nimport { join, resolve } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { getCwd } from './state'\nimport { memoize } from 'lodash-es'\nimport { loadAllPlugins } from './pluginLoader'\n\n// Track warned agents to avoid spam\nconst warnedAgents = new Set<string>()\n\nexport interface AgentConfig {\n agentType: string // Agent identifier (matches subagent_type)\n whenToUse: string // Description of when to use this agent\n tools: string[] | '*' // Tool permissions\n systemPrompt: string // System prompt content\n location: 'built-in' | 'user' | 'project' | 'plugin'\n color?: string // Optional UI color\n model_name?: string // Optional model override\n pluginName?: string // Source plugin name (if loaded from plugin)\n}\n\n// Built-in general-purpose agent as fallback\nconst BUILTIN_GENERAL_PURPOSE: AgentConfig = {\n agentType: 'general-purpose',\n whenToUse:\n 'General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks',\n tools: '*',\n systemPrompt: `You are a general-purpose agent. Given the user's task, use the tools available to complete it efficiently and thoroughly.\n\nWhen to use your capabilities:\n- Searching for code, configurations, and patterns across large codebases\n- Analyzing multiple files to understand system architecture \n- Investigating complex questions that require exploring many files\n- Performing multi-step research tasks\n\nGuidelines:\n- For file searches: Use Grep or Glob when you need to search broadly. Use FileRead when you know the specific file path.\n- For analysis: Start broad and narrow down. Use multiple search strategies if the first doesn't yield results.\n- Be thorough: Check multiple locations, consider different naming conventions, look for related files.\n- Complete tasks directly using your capabilities.`,\n location: 'built-in',\n}\n\n/**\n * Parse tools field from frontmatter\n */\nfunction parseTools(tools: any): string[] | '*' {\n if (!tools) return '*'\n if (tools === '*') return '*'\n if (Array.isArray(tools)) {\n // Ensure all items are strings and filter out non-strings\n const filteredTools = tools.filter(\n (t): t is string => typeof t === 'string',\n )\n return filteredTools.length > 0 ? filteredTools : '*'\n }\n if (typeof tools === 'string') {\n return [tools]\n }\n return '*'\n}\n\n/**\n * Scan a directory for agent configuration files\n */\nasync function scanAgentDirectory(\n dirPath: string,\n location: 'user' | 'project',\n): Promise<AgentConfig[]> {\n if (!existsSync(dirPath)) {\n return []\n }\n\n const agents: AgentConfig[] = []\n\n try {\n const files = readdirSync(dirPath)\n\n for (const file of files) {\n if (!file.endsWith('.md')) continue\n\n const filePath = join(dirPath, file)\n const stat = statSync(filePath)\n\n if (!stat.isFile()) continue\n\n try {\n const content = readFileSync(filePath, 'utf-8')\n const { data: frontmatter, content: body } = matter(content)\n\n // Validate required fields\n if (!frontmatter.name || !frontmatter.description) {\n console.warn(\n `Skipping ${filePath}: missing required fields (name, description)`,\n )\n continue\n }\n\n // Silently ignore deprecated 'model' field - no warnings by default\n // Only warn if MINTO_DEBUG_AGENTS environment variable is set\n if (\n frontmatter.model &&\n !frontmatter.model_name &&\n !warnedAgents.has(frontmatter.name) &&\n process.env.MINTO_DEBUG_AGENTS\n ) {\n console.warn(\n `\u26A0\uFE0F Agent ${frontmatter.name}: 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`,\n )\n warnedAgents.add(frontmatter.name)\n }\n\n // Build agent config\n const agent: AgentConfig = {\n agentType: frontmatter.name,\n whenToUse: frontmatter.description.replace(/\\\\n/g, '\\n'),\n tools: parseTools(frontmatter.tools),\n systemPrompt: body.trim(),\n location,\n ...(frontmatter.color && { color: frontmatter.color }),\n // Only use model_name field, ignore deprecated 'model' field\n ...(frontmatter.model_name && { model_name: frontmatter.model_name }),\n }\n\n agents.push(agent)\n } catch (error) {\n console.warn(`Failed to parse agent file ${filePath}:`, error)\n }\n }\n } catch (error) {\n console.warn(`Failed to scan directory ${dirPath}:`, error)\n }\n\n return agents\n}\n\n/**\n * Load agents from installed plugins\n */\nasync function loadPluginAgents(): Promise<AgentConfig[]> {\n const agents: AgentConfig[] = []\n\n try {\n const plugins = loadAllPlugins()\n\n for (const plugin of plugins) {\n // Skip disabled plugins\n if (!plugin.enabled) continue\n\n for (const pluginAgent of plugin.agents) {\n try {\n // Read the agent file to parse frontmatter and content\n const content = readFileSync(pluginAgent.filePath, 'utf-8')\n const { data: frontmatter, content: body } = matter(content)\n\n // Validate required fields\n if (!frontmatter.name || !frontmatter.description) {\n console.warn(\n `Skipping plugin agent ${pluginAgent.filePath}: missing required fields (name, description)`,\n )\n continue\n }\n\n // Warn about deprecated 'model' field if debug mode is enabled\n if (\n frontmatter.model &&\n !frontmatter.model_name &&\n !warnedAgents.has(frontmatter.name) &&\n process.env.MINTO_DEBUG_AGENTS\n ) {\n console.warn(\n `\u26A0\uFE0F Plugin agent ${frontmatter.name} (from ${plugin.manifest.name}): 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`,\n )\n warnedAgents.add(frontmatter.name)\n }\n\n // Build agent config\n const agent: AgentConfig = {\n agentType: frontmatter.name,\n whenToUse: frontmatter.description.replace(/\\\\n/g, '\\n'),\n tools: parseTools(frontmatter.tools),\n systemPrompt: body.trim(),\n location: 'plugin',\n pluginName: plugin.manifest.name,\n ...(frontmatter.color && { color: frontmatter.color }),\n // Only use model_name field, ignore deprecated 'model' field\n ...(frontmatter.model_name && {\n model_name: frontmatter.model_name,\n }),\n }\n\n agents.push(agent)\n } catch (error) {\n console.warn(\n `Failed to load plugin agent ${pluginAgent.name} from ${plugin.manifest.name}:`,\n error,\n )\n }\n }\n }\n } catch (error) {\n console.warn('Failed to load plugin agents:', error)\n }\n\n return agents\n}\n\n/**\n * Load all agent configurations\n *\n * Directory Priority (later overrides earlier):\n * 1. Built-in agents\n * 2. Plugin agents\n * 3. ~/.minto/agents (user directory)\n * 4. ./.minto/agents (project directory - highest priority)\n */\nasync function loadAllAgents(): Promise<{\n activeAgents: AgentConfig[]\n allAgents: AgentConfig[]\n}> {\n try {\n // Define directories in priority order\n const userMintoDir = join(homedir(), '.minto', 'agents')\n const projectMintoDir = join(getCwd(), '.minto', 'agents')\n\n // Load from all sources in parallel\n const [pluginAgents, userMintoAgents, projectMintoAgents] =\n await Promise.all([\n loadPluginAgents(),\n scanAgentDirectory(userMintoDir, 'user'),\n scanAgentDirectory(projectMintoDir, 'project'),\n ])\n\n // Built-in agents (currently just general-purpose)\n const builtinAgents = [BUILTIN_GENERAL_PURPOSE]\n\n // Apply priority override: built-in < plugin < user < project\n // Later entries override earlier ones with the same agentType\n const agentMap = new Map<string, AgentConfig>()\n\n // Add in priority order (later entries override earlier ones)\n for (const agent of builtinAgents) {\n agentMap.set(agent.agentType, agent)\n }\n for (const agent of pluginAgents) {\n agentMap.set(agent.agentType, agent)\n }\n for (const agent of userMintoAgents) {\n agentMap.set(agent.agentType, agent)\n }\n for (const agent of projectMintoAgents) {\n agentMap.set(agent.agentType, agent)\n }\n\n const activeAgents = Array.from(agentMap.values())\n const allAgents = [\n ...builtinAgents,\n ...pluginAgents,\n ...userMintoAgents,\n ...projectMintoAgents,\n ]\n\n return { activeAgents, allAgents }\n } catch (error) {\n console.error('Failed to load agents, falling back to built-in:', error)\n return {\n activeAgents: [BUILTIN_GENERAL_PURPOSE],\n allAgents: [BUILTIN_GENERAL_PURPOSE],\n }\n }\n}\n\n// Memoized version for performance\nexport const getActiveAgents = memoize(async (): Promise<AgentConfig[]> => {\n const { activeAgents } = await loadAllAgents()\n return activeAgents\n})\n\n// Get all agents (both active and overridden)\nexport const getAllAgents = memoize(async (): Promise<AgentConfig[]> => {\n const { allAgents } = await loadAllAgents()\n return allAgents\n})\n\n// Clear cache when needed\nexport function clearAgentCache() {\n getActiveAgents.cache?.clear?.()\n getAllAgents.cache?.clear?.()\n getAgentByType.cache?.clear?.()\n getAvailableAgentTypes.cache?.clear?.()\n}\n\n// Get a specific agent by type\nexport const getAgentByType = memoize(\n async (agentType: string): Promise<AgentConfig | undefined> => {\n const agents = await getActiveAgents()\n return agents.find(agent => agent.agentType === agentType)\n },\n)\n\n// Get all available agent types for validation\nexport const getAvailableAgentTypes = memoize(async (): Promise<string[]> => {\n const agents = await getActiveAgents()\n return agents.map(agent => agent.agentType)\n})\n\n// File watcher for hot reload\nlet watchers: FSWatcher[] = []\n\n/**\n * Start watching agent configuration directories for changes\n */\nexport async function startAgentWatcher(onChange?: () => void): Promise<void> {\n await stopAgentWatcher() // Clean up any existing watchers\n\n // Watch .minto directories only\n const userMintoDir = join(homedir(), '.minto', 'agents')\n const projectMintoDir = join(getCwd(), '.minto', 'agents')\n\n const watchDirectory = (dirPath: string, label: string) => {\n if (existsSync(dirPath)) {\n const watcher = watch(\n dirPath,\n { recursive: false },\n async (eventType, filename) => {\n if (filename && filename.endsWith('.md')) {\n console.log(\n `\uD83D\uDD04 Agent configuration changed in ${label}: ${filename}`,\n )\n clearAgentCache()\n // Also clear any other related caches\n getAllAgents.cache?.clear?.()\n onChange?.()\n }\n },\n )\n watchers.push(watcher)\n }\n }\n\n // Watch directories\n watchDirectory(userMintoDir, 'user/.minto')\n watchDirectory(projectMintoDir, 'project/.minto')\n}\n\n/**\n * Stop watching agent configuration directories\n */\nexport async function stopAgentWatcher(): Promise<void> {\n // FSWatcher.close() is synchronous and does not accept a callback on Node 18/20\n try {\n for (const watcher of watchers) {\n try {\n watcher.close()\n } catch (err) {\n console.error('Failed to close file watcher:', err)\n }\n }\n } finally {\n watchers = []\n }\n}\n"],
|
|
5
|
-
"mappings": "AAMA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP,SAAS,YAAqB;AAC9B,SAAS,eAAe;AACxB,OAAO,YAAY;AACnB,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,sBAAsB;
|
|
4
|
+
"sourcesContent": ["/**\n * Agent configuration loader\n * Loads agent configurations from markdown files with YAML frontmatter.\n * Implements Claude Code Subagent specification for agent configuration.\n */\n\nimport {\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n watch,\n FSWatcher,\n} from 'fs'\nimport { join, resolve } from 'path'\nimport { homedir } from 'os'\nimport matter from 'gray-matter'\nimport { getCwd } from './state'\nimport { memoize } from 'lodash-es'\nimport { loadAllPlugins } from './pluginLoader'\nimport type { PermissionMode } from '@minto-types/PermissionMode'\nimport type { HookDefinition } from '@minto-types/hooks'\n\n// Track warned agents to avoid spam\nconst warnedAgents = new Set<string>()\n\n/**\n * Agent lifecycle hooks configuration\n * Claude Code specification compliant\n */\nexport interface AgentHooks {\n onStart?: HookDefinition[]\n onComplete?: HookDefinition[]\n onError?: HookDefinition[]\n}\n\n/**\n * Agent memory persistence configuration\n * Claude Code specification compliant\n */\nexport interface AgentMemory {\n scope: 'user' | 'project' | 'local'\n key?: string // Optional namespace key for memory storage\n}\n\n/**\n * Agent configuration interface\n * Extended for Claude Code specification compliance\n */\nexport interface AgentConfig {\n // Identity\n agentType: string // Agent identifier (matches subagent_type)\n whenToUse: string // Description of when to use this agent\n systemPrompt: string // System prompt content\n location: 'built-in' | 'user' | 'project' | 'plugin'\n\n // Tool access control\n tools: string[] | '*' // Tool allowlist (or '*' for all)\n disallowedTools?: string[] // Tool denylist (takes precedence over tools)\n\n // Execution configuration\n model_name?: string // Model override (e.g., 'quick', 'main', 'reasoning')\n permissionMode?: PermissionMode // Permission handling mode\n maxThinkingTokens?: number // Extended thinking token limit\n\n // Skill preloading\n skills?: string[] // Skills to preload into agent context\n\n // Lifecycle hooks\n hooks?: AgentHooks // Agent lifecycle hooks\n\n // Memory persistence\n memory?: AgentMemory // Memory configuration for cross-session persistence\n\n // UI/Display\n color?: string // Optional UI color\n pluginName?: string // Source plugin name (if loaded from plugin)\n}\n\n/**\n * Built-in agents for Claude Code specification compliance\n */\nconst BUILTIN_AGENTS: AgentConfig[] = [\n // general-purpose: Default agent for multi-step tasks\n {\n agentType: 'general-purpose',\n whenToUse:\n 'General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent.',\n tools: '*',\n systemPrompt: `You are a general-purpose agent. Given the user's task, use the tools available to complete it efficiently and thoroughly.\n\nWhen to use your capabilities:\n- Searching for code, configurations, and patterns across large codebases\n- Analyzing multiple files to understand system architecture\n- Investigating complex questions that require exploring many files\n- Performing multi-step research tasks\n\nGuidelines:\n- For file searches: Use Grep or Glob when you need to search broadly. Use Read when you know the specific file path.\n- For analysis: Start broad and narrow down. Use multiple search strategies if the first doesn't yield results.\n- Be thorough: Check multiple locations, consider different naming conventions, look for related files.\n- Complete tasks directly using your capabilities.`,\n location: 'built-in',\n },\n\n // Explore: Fast read-only codebase exploration (Claude Code spec)\n {\n agentType: 'Explore',\n whenToUse:\n 'Fast agent specialized for exploring codebases. Use this when you need to quickly find files by patterns, search code for keywords, or answer questions about the codebase. Specify thoroughness: \"quick\" for basic searches, \"medium\" for moderate exploration, \"very thorough\" for comprehensive analysis.',\n tools: ['Read', 'Glob', 'Grep', 'LS', 'WebSearch', 'WebFetch'],\n disallowedTools: ['Edit', 'Write', 'Bash', 'NotebookEdit'],\n model_name: 'quick', // Maps to haiku equivalent\n permissionMode: 'plan', // Read-only mode\n systemPrompt: `You are an exploration agent optimized for fast codebase searches and understanding.\n\nYour role:\n- Quickly find files, functions, classes, and patterns\n- Understand code structure and architecture\n- Answer questions about how code works\n- Identify relevant files for a given task\n\nGuidelines:\n- Use Glob for finding files by pattern (e.g., \"**/*.tsx\", \"src/**/*.ts\")\n- Use Grep for searching code content (e.g., function names, imports, patterns)\n- Use Read to examine specific files you've identified\n- Start broad, then narrow down based on results\n- Report findings with specific file paths and line numbers\n- Be thorough but efficient - check multiple locations and naming conventions\n\nYou are READ-ONLY. You cannot modify any files.`,\n location: 'built-in',\n },\n\n // Plan: Research and planning agent (Claude Code spec)\n {\n agentType: 'Plan',\n whenToUse:\n 'Software architect agent for designing implementation plans. Use this when you need to plan the implementation strategy for a task. Returns step-by-step plans, identifies critical files, and considers architectural trade-offs.',\n tools: ['Read', 'Glob', 'Grep', 'LS', 'WebSearch', 'WebFetch', 'Think'],\n disallowedTools: ['Edit', 'Write', 'Bash', 'NotebookEdit'],\n model_name: 'inherit', // Inherit caller's model\n permissionMode: 'plan', // Read-only mode\n systemPrompt: `You are a planning agent specialized in analyzing codebases and creating implementation plans.\n\nYour role:\n- Understand requirements and constraints\n- Analyze existing code patterns and architecture\n- Create detailed, step-by-step implementation plans\n- Identify potential issues and trade-offs\n- Recommend best approaches based on codebase conventions\n\nGuidelines:\n- Read relevant files to understand current patterns\n- Identify all files that will need modification\n- Consider edge cases and error handling\n- Note any dependencies or prerequisites\n- Provide specific, actionable steps\n\nOutput format:\n1. Summary of the task\n2. Files to modify/create (with paths)\n3. Step-by-step implementation plan\n4. Potential challenges or considerations\n5. Testing approach\n\nYou are READ-ONLY. You cannot modify any files. Focus on planning, not execution.`,\n location: 'built-in',\n },\n\n // Bash: Shell command execution agent (Claude Code spec)\n {\n agentType: 'Bash',\n whenToUse:\n 'Command execution specialist for running bash commands. Use this for git operations, command execution, and other terminal tasks.',\n tools: ['Bash', 'Read', 'LS'],\n systemPrompt: `You are a bash execution agent specialized in running shell commands.\n\nYour role:\n- Execute shell commands safely and effectively\n- Handle build, test, and deployment tasks\n- Manage git operations\n- Run scripts and automation\n\nGuidelines:\n- Check command syntax before execution\n- Handle errors gracefully with clear messages\n- Report command output and exit codes\n- Be cautious with destructive commands (rm, git reset, etc.)\n- Use appropriate flags for verbose output when debugging\n- Chain commands with && for dependent operations\n\nAlways explain what a command will do before running it if it modifies the system.`,\n location: 'built-in',\n },\n]\n\n/**\n * Parse tools field from frontmatter\n */\nfunction parseTools(tools: any): string[] | '*' {\n if (!tools) return '*'\n if (tools === '*') return '*'\n if (Array.isArray(tools)) {\n // Ensure all items are strings and filter out non-strings\n const filteredTools = tools.filter(\n (t): t is string => typeof t === 'string',\n )\n return filteredTools.length > 0 ? filteredTools : '*'\n }\n if (typeof tools === 'string') {\n // Handle comma-separated string: \"Read, Grep, Glob\"\n if (tools.includes(',')) {\n return tools.split(',').map((t: string) => t.trim()).filter(Boolean)\n }\n return [tools]\n }\n return '*'\n}\n\n/**\n * Parse disallowedTools field from frontmatter\n */\nfunction parseDisallowedTools(disallowedTools: any): string[] | undefined {\n if (!disallowedTools) return undefined\n if (Array.isArray(disallowedTools)) {\n const filtered = disallowedTools.filter(\n (t): t is string => typeof t === 'string',\n )\n return filtered.length > 0 ? filtered : undefined\n }\n if (typeof disallowedTools === 'string') {\n // Handle comma-separated string\n if (disallowedTools.includes(',')) {\n return disallowedTools.split(',').map((t: string) => t.trim()).filter(Boolean)\n }\n return [disallowedTools]\n }\n return undefined\n}\n\n/**\n * Parse skills field from frontmatter\n */\nfunction parseSkills(skills: any): string[] | undefined {\n if (!skills) return undefined\n if (Array.isArray(skills)) {\n const filtered = skills.filter((s): s is string => typeof s === 'string')\n return filtered.length > 0 ? filtered : undefined\n }\n if (typeof skills === 'string') {\n if (skills.includes(',')) {\n return skills.split(',').map((s: string) => s.trim()).filter(Boolean)\n }\n return [skills]\n }\n return undefined\n}\n\n/**\n * Parse memory field from frontmatter\n */\nfunction parseMemory(memory: any): AgentMemory | undefined {\n if (!memory) return undefined\n if (typeof memory === 'string') {\n // Simple format: \"user\" | \"project\" | \"local\"\n if (['user', 'project', 'local'].includes(memory)) {\n return { scope: memory as AgentMemory['scope'] }\n }\n return undefined\n }\n if (typeof memory === 'object') {\n const scope = memory.scope\n if (['user', 'project', 'local'].includes(scope)) {\n return {\n scope: scope as AgentMemory['scope'],\n ...(memory.key && { key: String(memory.key) }),\n }\n }\n }\n return undefined\n}\n\n/**\n * Parse permissionMode field from frontmatter\n */\nfunction parsePermissionMode(mode: any): PermissionMode | undefined {\n if (!mode) return undefined\n const validModes: PermissionMode[] = [\n 'default',\n 'acceptEdits',\n 'dontAsk',\n 'plan',\n 'bypassPermissions',\n ]\n if (typeof mode === 'string' && validModes.includes(mode as PermissionMode)) {\n return mode as PermissionMode\n }\n return undefined\n}\n\n/**\n * Scan a directory for agent configuration files\n */\nasync function scanAgentDirectory(\n dirPath: string,\n location: 'user' | 'project',\n): Promise<AgentConfig[]> {\n if (!existsSync(dirPath)) {\n return []\n }\n\n const agents: AgentConfig[] = []\n\n try {\n const files = readdirSync(dirPath)\n\n for (const file of files) {\n if (!file.endsWith('.md')) continue\n\n const filePath = join(dirPath, file)\n const stat = statSync(filePath)\n\n if (!stat.isFile()) continue\n\n try {\n const content = readFileSync(filePath, 'utf-8')\n const { data: frontmatter, content: body } = matter(content)\n\n // Validate required fields\n if (!frontmatter.name || !frontmatter.description) {\n console.warn(\n `Skipping ${filePath}: missing required fields (name, description)`,\n )\n continue\n }\n\n // Silently ignore deprecated 'model' field - no warnings by default\n // Only warn if MINTO_DEBUG_AGENTS environment variable is set\n if (\n frontmatter.model &&\n !frontmatter.model_name &&\n !warnedAgents.has(frontmatter.name) &&\n process.env.MINTO_DEBUG_AGENTS\n ) {\n console.warn(\n `\u26A0\uFE0F Agent ${frontmatter.name}: 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`,\n )\n warnedAgents.add(frontmatter.name)\n }\n\n // Parse optional fields\n const disallowedTools = parseDisallowedTools(frontmatter.disallowedTools)\n const skills = parseSkills(frontmatter.skills)\n const memory = parseMemory(frontmatter.memory)\n const permissionMode = parsePermissionMode(frontmatter.permissionMode)\n\n // Build agent config with all Claude Code spec fields\n const agent: AgentConfig = {\n agentType: frontmatter.name,\n whenToUse: frontmatter.description.replace(/\\\\n/g, '\\n'),\n tools: parseTools(frontmatter.tools),\n systemPrompt: body.trim(),\n location,\n // Optional fields - only include if defined\n ...(frontmatter.color && { color: frontmatter.color }),\n ...(frontmatter.model_name && { model_name: frontmatter.model_name }),\n ...(disallowedTools && { disallowedTools }),\n ...(permissionMode && { permissionMode }),\n ...(skills && { skills }),\n ...(memory && { memory }),\n ...(frontmatter.maxThinkingTokens && {\n maxThinkingTokens: Number(frontmatter.maxThinkingTokens),\n }),\n ...(frontmatter.hooks && { hooks: frontmatter.hooks as AgentHooks }),\n }\n\n agents.push(agent)\n } catch (error) {\n console.warn(`Failed to parse agent file ${filePath}:`, error)\n }\n }\n } catch (error) {\n console.warn(`Failed to scan directory ${dirPath}:`, error)\n }\n\n return agents\n}\n\n/**\n * Load agents from installed plugins\n */\nasync function loadPluginAgents(): Promise<AgentConfig[]> {\n const agents: AgentConfig[] = []\n\n try {\n const plugins = loadAllPlugins()\n\n for (const plugin of plugins) {\n // Skip disabled plugins\n if (!plugin.enabled) continue\n\n for (const pluginAgent of plugin.agents) {\n try {\n // Read the agent file to parse frontmatter and content\n const content = readFileSync(pluginAgent.filePath, 'utf-8')\n const { data: frontmatter, content: body } = matter(content)\n\n // Validate required fields\n if (!frontmatter.name || !frontmatter.description) {\n console.warn(\n `Skipping plugin agent ${pluginAgent.filePath}: missing required fields (name, description)`,\n )\n continue\n }\n\n // Warn about deprecated 'model' field if debug mode is enabled\n if (\n frontmatter.model &&\n !frontmatter.model_name &&\n !warnedAgents.has(frontmatter.name) &&\n process.env.MINTO_DEBUG_AGENTS\n ) {\n console.warn(\n `\u26A0\uFE0F Plugin agent ${frontmatter.name} (from ${plugin.manifest.name}): 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`,\n )\n warnedAgents.add(frontmatter.name)\n }\n\n // Parse optional fields\n const disallowedTools = parseDisallowedTools(frontmatter.disallowedTools)\n const skills = parseSkills(frontmatter.skills)\n const memory = parseMemory(frontmatter.memory)\n const permissionMode = parsePermissionMode(frontmatter.permissionMode)\n\n // Build agent config with all Claude Code spec fields\n const agent: AgentConfig = {\n agentType: frontmatter.name,\n whenToUse: frontmatter.description.replace(/\\\\n/g, '\\n'),\n tools: parseTools(frontmatter.tools),\n systemPrompt: body.trim(),\n location: 'plugin',\n pluginName: plugin.manifest.name,\n // Optional fields\n ...(frontmatter.color && { color: frontmatter.color }),\n ...(frontmatter.model_name && { model_name: frontmatter.model_name }),\n ...(disallowedTools && { disallowedTools }),\n ...(permissionMode && { permissionMode }),\n ...(skills && { skills }),\n ...(memory && { memory }),\n ...(frontmatter.maxThinkingTokens && {\n maxThinkingTokens: Number(frontmatter.maxThinkingTokens),\n }),\n ...(frontmatter.hooks && { hooks: frontmatter.hooks as AgentHooks }),\n }\n\n agents.push(agent)\n } catch (error) {\n console.warn(\n `Failed to load plugin agent ${pluginAgent.name} from ${plugin.manifest.name}:`,\n error,\n )\n }\n }\n }\n } catch (error) {\n console.warn('Failed to load plugin agents:', error)\n }\n\n return agents\n}\n\n/**\n * Load all agent configurations\n *\n * Directory Priority (later overrides earlier):\n * 1. Built-in agents (general-purpose, Explore, Plan, Bash)\n * 2. Plugin agents\n * 3. ~/.minto/agents (Minto user directory)\n * 4. ./.minto/agents (Minto project directory - highest priority)\n */\nasync function loadAllAgents(): Promise<{\n activeAgents: AgentConfig[]\n allAgents: AgentConfig[]\n}> {\n try {\n const home = homedir()\n const cwd = getCwd()\n\n // Define directories in priority order (later overrides earlier)\n const userMintoDir = join(home, '.minto', 'agents')\n const projectMintoDir = join(cwd, '.minto', 'agents')\n\n // Load from all sources in parallel\n const [pluginAgents, userMintoAgents, projectMintoAgents] =\n await Promise.all([\n loadPluginAgents(),\n scanAgentDirectory(userMintoDir, 'user'),\n scanAgentDirectory(projectMintoDir, 'project'),\n ])\n\n // Apply priority override: built-in < plugin < user-minto < project-minto\n // Later entries override earlier ones with the same agentType\n const agentMap = new Map<string, AgentConfig>()\n\n // Add in priority order (later entries override earlier ones)\n for (const agent of BUILTIN_AGENTS) {\n agentMap.set(agent.agentType, agent)\n }\n for (const agent of pluginAgents) {\n agentMap.set(agent.agentType, agent)\n }\n for (const agent of userMintoAgents) {\n agentMap.set(agent.agentType, agent)\n }\n for (const agent of projectMintoAgents) {\n agentMap.set(agent.agentType, agent)\n }\n\n const activeAgents = Array.from(agentMap.values())\n const allAgents = [\n ...BUILTIN_AGENTS,\n ...pluginAgents,\n ...userMintoAgents,\n ...projectMintoAgents,\n ]\n\n return { activeAgents, allAgents }\n } catch (error) {\n console.error('Failed to load agents, falling back to built-in:', error)\n return {\n activeAgents: [...BUILTIN_AGENTS],\n allAgents: [...BUILTIN_AGENTS],\n }\n }\n}\n\n// Memoized version for performance\nexport const getActiveAgents = memoize(async (): Promise<AgentConfig[]> => {\n const { activeAgents } = await loadAllAgents()\n return activeAgents\n})\n\n// Get all agents (both active and overridden)\nexport const getAllAgents = memoize(async (): Promise<AgentConfig[]> => {\n const { allAgents } = await loadAllAgents()\n return allAgents\n})\n\n// Clear cache when needed\nexport function clearAgentCache() {\n getActiveAgents.cache?.clear?.()\n getAllAgents.cache?.clear?.()\n getAgentByType.cache?.clear?.()\n getAvailableAgentTypes.cache?.clear?.()\n}\n\n// Get a specific agent by type\nexport const getAgentByType = memoize(\n async (agentType: string): Promise<AgentConfig | undefined> => {\n const agents = await getActiveAgents()\n return agents.find(agent => agent.agentType === agentType)\n },\n)\n\n// Get all available agent types for validation\nexport const getAvailableAgentTypes = memoize(async (): Promise<string[]> => {\n const agents = await getActiveAgents()\n return agents.map(agent => agent.agentType)\n})\n\n// File watcher for hot reload\nlet watchers: FSWatcher[] = []\n\n/**\n * Start watching agent configuration directories for changes\n */\nexport async function startAgentWatcher(onChange?: () => void): Promise<void> {\n await stopAgentWatcher() // Clean up any existing watchers\n\n const home = homedir()\n const cwd = getCwd()\n\n // Watch .minto directories\n const directories = [\n { path: join(home, '.minto', 'agents'), label: 'user/.minto' },\n { path: join(cwd, '.minto', 'agents'), label: 'project/.minto' },\n ]\n\n const watchDirectory = (dirPath: string, label: string) => {\n if (existsSync(dirPath)) {\n const watcher = watch(\n dirPath,\n { recursive: false },\n async (eventType, filename) => {\n if (filename && filename.endsWith('.md')) {\n console.log(\n `\uD83D\uDD04 Agent configuration changed in ${label}: ${filename}`,\n )\n clearAgentCache()\n // Also clear any other related caches\n getAllAgents.cache?.clear?.()\n onChange?.()\n }\n },\n )\n watchers.push(watcher)\n }\n }\n\n // Watch all directories\n for (const { path, label } of directories) {\n watchDirectory(path, label)\n }\n}\n\n/**\n * Stop watching agent configuration directories\n */\nexport async function stopAgentWatcher(): Promise<void> {\n // FSWatcher.close() is synchronous and does not accept a callback on Node 18/20\n try {\n for (const watcher of watchers) {\n try {\n watcher.close()\n } catch (err) {\n console.error('Failed to close file watcher:', err)\n }\n }\n } finally {\n watchers = []\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|