@duckmind/dm-windows-x64 0.60.6 → 0.60.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/dm.exe +0 -0
- package/extensions/.dm-extensions.json +70 -123
- package/extensions/dm-9router-ext/src/index.js +410 -5
- package/extensions/dm-caveman/extensions/caveman.js +283 -12
- package/extensions/dm-cliproxy/index.js +182 -2
- package/extensions/dm-cliproxy/scripts/check-config-migration.js +66 -8
- package/extensions/dm-cliproxy/src/apply.js +228 -1
- package/extensions/dm-cliproxy/src/cache.js +42 -1
- package/extensions/dm-cliproxy/src/commands.js +50 -2
- package/extensions/dm-cliproxy/src/compat.js +81 -1
- package/extensions/dm-cliproxy/src/config.js +192 -2
- package/extensions/dm-cliproxy/src/conflicts.js +46 -1
- package/extensions/dm-cliproxy/src/fetch-models.js +190 -1
- package/extensions/dm-cliproxy/src/fetch-usage.js +41 -1
- package/extensions/dm-cliproxy/src/log.js +23 -1
- package/extensions/dm-cliproxy/src/status-quota.js +77 -1
- package/extensions/dm-cliproxy/src/ui-frame.js +50 -1
- package/extensions/dm-cliproxy/src/ui-hub/hub.js +199 -2
- package/extensions/dm-cliproxy/src/ui-hub/index.js +26 -2
- package/extensions/dm-cliproxy/src/ui-hub/shell.js +46 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-diagnostics.js +69 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-models.js +379 -1
- package/extensions/dm-cliproxy/src/ui-hub/view-usage.js +106 -1
- package/extensions/dm-cliproxy/src/ui-picker/catalog.js +41 -1
- package/extensions/dm-cliproxy/src/ui-picker/mutate.js +115 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-confirm.js +35 -1
- package/extensions/dm-cliproxy/src/ui-picker/prompt-name.js +62 -1
- package/extensions/dm-cliproxy/src/ui-picker/providers.js +45 -1
- package/extensions/dm-cliproxy/src/ui-picker/render-text.js +34 -1
- package/extensions/dm-cliproxy/src/ui-picker/rows.js +57 -1
- package/extensions/dm-cliproxy/src/ui-setup.js +260 -2
- package/extensions/dm-cliproxy/src/ui-usage.js +151 -1
- package/extensions/dm-cliproxy/src/usage-shared-cache.js +97 -1
- package/extensions/dm-context/src/context.js +144 -1
- package/extensions/dm-context/src/index.js +339 -7
- package/extensions/dm-context/src/utils.js +9 -1
- package/extensions/dm-cua/bin/browser-cua.mjs +73 -8
- package/extensions/dm-cua/index.js +75 -6
- package/extensions/dm-cua/src/browser-cua-lib.mjs +490 -6
- package/extensions/dm-cua/src/browser-install.mjs +331 -2
- package/extensions/dm-fff/src/index.js +688 -12
- package/extensions/dm-fff/src/query.js +60 -1
- package/extensions/dm-goal/src/goal.js +894 -23
- package/extensions/dm-image2/index.js +103 -9
- package/extensions/dm-image2/src/image-lib.mjs +1275 -8
- package/extensions/dm-subagents/install.mjs +62 -8
- package/extensions/dm-subagents/src/agents/agent-management.js +1190 -36
- package/extensions/dm-subagents/src/agents/agent-memory.js +216 -6
- package/extensions/dm-subagents/src/agents/agent-scope.js +5 -1
- package/extensions/dm-subagents/src/agents/agent-selection.js +20 -1
- package/extensions/dm-subagents/src/agents/agent-serializer.js +120 -5
- package/extensions/dm-subagents/src/agents/agents.js +1139 -11
- package/extensions/dm-subagents/src/agents/chain-serializer.js +299 -11
- package/extensions/dm-subagents/src/agents/frontmatter.js +65 -6
- package/extensions/dm-subagents/src/agents/identity.js +29 -1
- package/extensions/dm-subagents/src/agents/proactive-skills.js +141 -1
- package/extensions/dm-subagents/src/agents/skills.js +614 -6
- package/extensions/dm-subagents/src/extension/config.js +35 -2
- package/extensions/dm-subagents/src/extension/control-notices.js +69 -4
- package/extensions/dm-subagents/src/extension/doctor.js +172 -15
- package/extensions/dm-subagents/src/extension/fanout-child.js +158 -231
- package/extensions/dm-subagents/src/extension/index.js +521 -359
- package/extensions/dm-subagents/src/extension/rpc.js +266 -7
- package/extensions/dm-subagents/src/extension/schemas.js +275 -1
- package/extensions/dm-subagents/src/extension/tool-description.js +111 -6
- package/extensions/dm-subagents/src/intercom/intercom-bridge.js +126 -4
- package/extensions/dm-subagents/src/intercom/native-supervisor-channel.js +452 -5
- package/extensions/dm-subagents/src/intercom/result-intercom.js +319 -3
- package/extensions/dm-subagents/src/profiles/profiles.js +458 -3
- package/extensions/dm-subagents/src/runs/background/async-execution.js +834 -40
- package/extensions/dm-subagents/src/runs/background/async-job-tracker.js +435 -14
- package/extensions/dm-subagents/src/runs/background/async-resume.js +334 -8
- package/extensions/dm-subagents/src/runs/background/async-status.js +313 -12
- package/extensions/dm-subagents/src/runs/background/chain-append.js +245 -2
- package/extensions/dm-subagents/src/runs/background/chain-root-attachment.js +136 -1
- package/extensions/dm-subagents/src/runs/background/completion-batcher.js +94 -1
- package/extensions/dm-subagents/src/runs/background/completion-dedupe.js +54 -1
- package/extensions/dm-subagents/src/runs/background/control-channel.js +190 -1
- package/extensions/dm-subagents/src/runs/background/fleet-view.js +483 -17
- package/extensions/dm-subagents/src/runs/background/notify.js +129 -3
- package/extensions/dm-subagents/src/runs/background/parallel-groups.js +34 -1
- package/extensions/dm-subagents/src/runs/background/result-watcher.js +236 -6
- package/extensions/dm-subagents/src/runs/background/run-id-resolver.js +76 -4
- package/extensions/dm-subagents/src/runs/background/run-status.js +427 -23
- package/extensions/dm-subagents/src/runs/background/scheduled-runs.js +487 -4
- package/extensions/dm-subagents/src/runs/background/stale-run-reconciler.js +306 -9
- package/extensions/dm-subagents/src/runs/background/subagent-runner.js +2849 -73
- package/extensions/dm-subagents/src/runs/background/top-level-async.js +5 -1
- package/extensions/dm-subagents/src/runs/background/wait.js +206 -11
- package/extensions/dm-subagents/src/runs/foreground/chain-clarify.js +1013 -12
- package/extensions/dm-subagents/src/runs/foreground/chain-execution.js +980 -101
- package/extensions/dm-subagents/src/runs/foreground/execution.js +1165 -45
- package/extensions/dm-subagents/src/runs/foreground/subagent-executor.js +3157 -222
- package/extensions/dm-subagents/src/runs/shared/acceptance.js +835 -3
- package/extensions/dm-subagents/src/runs/shared/chain-outputs.js +104 -1
- package/extensions/dm-subagents/src/runs/shared/completion-guard.js +116 -3
- package/extensions/dm-subagents/src/runs/shared/dm-args.js +208 -1
- package/extensions/dm-subagents/src/runs/shared/dm-spawn.js +90 -1
- package/extensions/dm-subagents/src/runs/shared/dynamic-fanout.js +282 -1
- package/extensions/dm-subagents/src/runs/shared/long-running-guard.js +148 -1
- package/extensions/dm-subagents/src/runs/shared/mcp-direct-tool-allowlist.js +305 -1
- package/extensions/dm-subagents/src/runs/shared/model-fallback.js +194 -1
- package/extensions/dm-subagents/src/runs/shared/model-scope.js +65 -1
- package/extensions/dm-subagents/src/runs/shared/nested-events.js +851 -8
- package/extensions/dm-subagents/src/runs/shared/nested-path.js +41 -1
- package/extensions/dm-subagents/src/runs/shared/nested-render.js +105 -1
- package/extensions/dm-subagents/src/runs/shared/parallel-utils.js +81 -4
- package/extensions/dm-subagents/src/runs/shared/run-history.js +51 -4
- package/extensions/dm-subagents/src/runs/shared/single-output.js +149 -8
- package/extensions/dm-subagents/src/runs/shared/structured-output.js +58 -1
- package/extensions/dm-subagents/src/runs/shared/subagent-control.js +166 -5
- package/extensions/dm-subagents/src/runs/shared/subagent-prompt-runtime.js +329 -13
- package/extensions/dm-subagents/src/runs/shared/tool-budget.js +73 -1
- package/extensions/dm-subagents/src/runs/shared/turn-budget.js +47 -4
- package/extensions/dm-subagents/src/runs/shared/workflow-graph.js +196 -1
- package/extensions/dm-subagents/src/runs/shared/worktree.js +435 -3
- package/extensions/dm-subagents/src/shared/artifacts.js +92 -2
- package/extensions/dm-subagents/src/shared/atomic-json.js +55 -1
- package/extensions/dm-subagents/src/shared/child-transcript.js +167 -5
- package/extensions/dm-subagents/src/shared/file-coalescer.js +25 -1
- package/extensions/dm-subagents/src/shared/fork-context.js +147 -4
- package/extensions/dm-subagents/src/shared/formatters.js +98 -7
- package/extensions/dm-subagents/src/shared/jsonl-writer.js +56 -2
- package/extensions/dm-subagents/src/shared/model-info.js +62 -1
- package/extensions/dm-subagents/src/shared/post-exit-stdio-guard.js +68 -1
- package/extensions/dm-subagents/src/shared/session-identity.js +6 -1
- package/extensions/dm-subagents/src/shared/session-tokens.js +39 -2
- package/extensions/dm-subagents/src/shared/settings.js +198 -11
- package/extensions/dm-subagents/src/shared/status-format.js +53 -1
- package/extensions/dm-subagents/src/shared/types.js +184 -6
- package/extensions/dm-subagents/src/shared/utils.js +462 -2
- package/extensions/dm-subagents/src/slash/prompt-template-bridge.js +288 -1
- package/extensions/dm-subagents/src/slash/prompt-workflows.js +297 -7
- package/extensions/dm-subagents/src/slash/slash-bridge.js +118 -1
- package/extensions/dm-subagents/src/slash/slash-commands.js +1287 -31
- package/extensions/dm-subagents/src/slash/slash-live-state.js +240 -4
- package/extensions/dm-subagents/src/tui/render-helpers.js +64 -1
- package/extensions/dm-subagents/src/tui/render.js +1542 -4
- package/extensions/dm-usage/index.js +1294 -9
- package/extensions/greedysearch-dm/bin/cdp-greedy.mjs +40 -9
- package/extensions/greedysearch-dm/bin/cdp-headless.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp-visible.mjs +5 -2
- package/extensions/greedysearch-dm/bin/cdp.mjs +896 -30
- package/extensions/greedysearch-dm/bin/gschrome.mjs +30 -2
- package/extensions/greedysearch-dm/bin/kill-visible.mjs +7 -2
- package/extensions/greedysearch-dm/bin/launch-visible.mjs +13 -2
- package/extensions/greedysearch-dm/bin/launch.mjs +282 -10
- package/extensions/greedysearch-dm/bin/mcp.mjs +386 -361
- package/extensions/greedysearch-dm/bin/search.mjs +620 -540
- package/extensions/greedysearch-dm/bin/visible.mjs +22 -2
- package/extensions/greedysearch-dm/extractors/bing-copilot.mjs +329 -579
- package/extensions/greedysearch-dm/extractors/chatgpt.mjs +301 -583
- package/extensions/greedysearch-dm/extractors/common.mjs +408 -32
- package/extensions/greedysearch-dm/extractors/consensus.mjs +376 -365
- package/extensions/greedysearch-dm/extractors/consent.mjs +303 -14
- package/extensions/greedysearch-dm/extractors/gemini.mjs +228 -592
- package/extensions/greedysearch-dm/extractors/google-ai.mjs +78 -499
- package/extensions/greedysearch-dm/extractors/logically.mjs +270 -347
- package/extensions/greedysearch-dm/extractors/perplexity.mjs +243 -581
- package/extensions/greedysearch-dm/extractors/selectors.mjs +32 -1
- package/extensions/greedysearch-dm/extractors/semantic-scholar.mjs +130 -317
- package/extensions/greedysearch-dm/index.js +123 -23
- package/extensions/greedysearch-dm/src/fetcher.mjs +576 -2
- package/extensions/greedysearch-dm/src/formatters/results.js +95 -10
- package/extensions/greedysearch-dm/src/formatters/sources.js +57 -1
- package/extensions/greedysearch-dm/src/formatters/synthesis.js +49 -1
- package/extensions/greedysearch-dm/src/github.mjs +222 -7
- package/extensions/greedysearch-dm/src/reddit.mjs +145 -14
- package/extensions/greedysearch-dm/src/search/browser-lifecycle.mjs +340 -9
- package/extensions/greedysearch-dm/src/search/challenge-detect.mjs +112 -4
- package/extensions/greedysearch-dm/src/search/chrome.mjs +486 -285
- package/extensions/greedysearch-dm/src/search/constants.mjs +109 -8
- package/extensions/greedysearch-dm/src/search/defaults.mjs +10 -1
- package/extensions/greedysearch-dm/src/search/engines.mjs +79 -9
- package/extensions/greedysearch-dm/src/search/fetch-source.mjs +441 -349
- package/extensions/greedysearch-dm/src/search/file-sources.mjs +29 -7
- package/extensions/greedysearch-dm/src/search/minimize.mjs +86 -1
- package/extensions/greedysearch-dm/src/search/output.mjs +51 -5
- package/extensions/greedysearch-dm/src/search/paths.mjs +48 -1
- package/extensions/greedysearch-dm/src/search/pdf.mjs +63 -2
- package/extensions/greedysearch-dm/src/search/port-pid.mjs +69 -1
- package/extensions/greedysearch-dm/src/search/progress.mjs +109 -2
- package/extensions/greedysearch-dm/src/search/query.mjs +21 -1
- package/extensions/greedysearch-dm/src/search/recovery.mjs +49 -1
- package/extensions/greedysearch-dm/src/search/research.mjs +2227 -458
- package/extensions/greedysearch-dm/src/search/scale-aware.mjs +61 -11
- package/extensions/greedysearch-dm/src/search/simple-research.mjs +396 -805
- package/extensions/greedysearch-dm/src/search/sources.mjs +412 -1
- package/extensions/greedysearch-dm/src/search/synthesis-runner.mjs +127 -12
- package/extensions/greedysearch-dm/src/search/synthesis.mjs +202 -12
- package/extensions/greedysearch-dm/src/tools/greedy-search-handler.js +209 -23
- package/extensions/greedysearch-dm/src/tools/shared.js +226 -10
- package/extensions/greedysearch-dm/src/utils/content.mjs +35 -4
- package/extensions/greedysearch-dm/src/utils/helpers.js +22 -1
- package/extensions/greedysearch-dm/src/utils/node-runtime.mjs +10 -1
- package/extensions/greedysearch-dm/src/utils/system-cmds.mjs +61 -1
- package/package.json +1 -1
|
@@ -1,37 +1,1191 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
BUILTIN_AGENT_NAMES,
|
|
5
|
+
defaultInheritProjectContext,
|
|
6
|
+
defaultInheritSkills,
|
|
7
|
+
defaultSystemPromptMode,
|
|
8
|
+
discoverAgentsAll,
|
|
9
|
+
buildRuntimeName,
|
|
10
|
+
frontmatterNameForConfig,
|
|
11
|
+
parsePackageName,
|
|
12
|
+
mergeBuiltinAgentOverride,
|
|
13
|
+
removeBuiltinAgentOverride,
|
|
14
|
+
removeBuiltinAgentOverrideFields
|
|
15
|
+
} from "./agents.js";
|
|
16
|
+
import { serializeAgent } from "./agent-serializer.js";
|
|
17
|
+
import { serializeChain, serializeJsonChain } from "./chain-serializer.js";
|
|
18
|
+
import { discoverAvailableSkills } from "./skills.js";
|
|
19
|
+
import {
|
|
20
|
+
buildProactiveSkillSubagentRecommendationLines
|
|
21
|
+
} from "./proactive-skills.js";
|
|
22
|
+
import { parseFrontmatter } from "./frontmatter.js";
|
|
23
|
+
import { toModelInfo } from "../shared/model-info.js";
|
|
24
|
+
import { resolveSubagentModelOverride } from "../runs/shared/model-fallback.js";
|
|
25
|
+
import { validateToolBudgetConfig } from "../runs/shared/tool-budget.js";
|
|
26
|
+
import { getProjectConfigDir } from "../shared/utils.js";
|
|
27
|
+
function result(text, isError = false) {
|
|
28
|
+
return { content: [{ type: "text", text }], isError, details: { mode: "management", results: [] } };
|
|
29
|
+
}
|
|
30
|
+
function parseCsv(value) {
|
|
31
|
+
return [...new Set(value.split(",").map((v) => v.trim()).filter(Boolean))];
|
|
32
|
+
}
|
|
33
|
+
function configObject(config) {
|
|
34
|
+
let val = config;
|
|
35
|
+
if (typeof val === "string") {
|
|
36
|
+
try {
|
|
37
|
+
val = JSON.parse(val);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
40
|
+
return { error: `config must be valid JSON: ${message}` };
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!val || typeof val !== "object" || Array.isArray(val))
|
|
44
|
+
return {};
|
|
45
|
+
return { value: val };
|
|
46
|
+
}
|
|
47
|
+
function hasKey(obj, key) {
|
|
48
|
+
return Object.prototype.hasOwnProperty.call(obj, key);
|
|
49
|
+
}
|
|
50
|
+
function asDisambiguationScope(scope) {
|
|
51
|
+
if (scope === "user" || scope === "project")
|
|
52
|
+
return scope;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
function actionScope(scope, action) {
|
|
56
|
+
if (scope === undefined)
|
|
57
|
+
return { scope: "user" };
|
|
58
|
+
const parsed = asDisambiguationScope(scope);
|
|
59
|
+
return parsed ? { scope: parsed } : { error: result(`agentScope must be 'user' or 'project' for ${action}.`, true) };
|
|
60
|
+
}
|
|
61
|
+
function normalizeListScope(scope) {
|
|
62
|
+
if (scope === undefined)
|
|
63
|
+
return "both";
|
|
64
|
+
if (scope === "user" || scope === "project" || scope === "both")
|
|
65
|
+
return scope;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
function sanitizeName(name) {
|
|
69
|
+
return name.toLowerCase().trim().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
|
|
70
|
+
}
|
|
71
|
+
function parsePackageConfig(value) {
|
|
72
|
+
return parsePackageName(value, "config.package");
|
|
73
|
+
}
|
|
74
|
+
function allAgents(d) {
|
|
75
|
+
return [...d.builtin, ...d.package, ...d.user, ...d.project];
|
|
76
|
+
}
|
|
77
|
+
function availableNames(cwd, kind) {
|
|
78
|
+
const d = discoverAgentsAll(cwd);
|
|
79
|
+
const items = kind === "agent" ? allAgents(d) : d.chains;
|
|
80
|
+
return [...new Set(items.map((x) => x.name))].sort((a, b) => a.localeCompare(b));
|
|
81
|
+
}
|
|
82
|
+
function findAgents(name, cwd, scope = "both") {
|
|
83
|
+
const d = discoverAgentsAll(cwd);
|
|
84
|
+
const raw = name.trim();
|
|
85
|
+
const sanitized = sanitizeName(raw);
|
|
86
|
+
return allAgents(d).filter((a) => (scope === "both" || a.source === scope) && (a.name === raw || a.name === sanitized)).sort((a, b) => a.source.localeCompare(b.source));
|
|
87
|
+
}
|
|
88
|
+
function findChains(name, cwd, scope = "both") {
|
|
89
|
+
const raw = name.trim();
|
|
90
|
+
const sanitized = sanitizeName(raw);
|
|
91
|
+
return discoverAgentsAll(cwd).chains.filter((c) => (scope === "both" || c.source === scope) && (c.name === raw || c.name === sanitized)).sort((a, b) => a.source.localeCompare(b.source));
|
|
92
|
+
}
|
|
93
|
+
const AGENT_SOURCE_PRECEDENCE = { builtin: 0, package: 1, user: 2, project: 3 };
|
|
94
|
+
function pickEffectiveAgent(d, name) {
|
|
95
|
+
const raw = name.trim();
|
|
96
|
+
const sanitized = sanitizeName(raw);
|
|
97
|
+
const matches = allAgents(d).filter((a) => a.name === raw || a.name === sanitized);
|
|
98
|
+
if (matches.length === 0)
|
|
99
|
+
return;
|
|
100
|
+
return matches.reduce((best, agent) => AGENT_SOURCE_PRECEDENCE[agent.source] > AGENT_SOURCE_PRECEDENCE[best.source] ? agent : best);
|
|
101
|
+
}
|
|
102
|
+
function nameExistsInScope(cwd, scope, name, excludePath) {
|
|
103
|
+
const d = discoverAgentsAll(cwd);
|
|
104
|
+
for (const a of scope === "user" ? d.user : d.project) {
|
|
105
|
+
if (a.name === name && a.filePath !== excludePath)
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
for (const c of d.chains) {
|
|
109
|
+
if (c.source === scope && c.name === name && c.filePath !== excludePath)
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
function isMutableSource(source) {
|
|
115
|
+
return source === "user" || source === "project";
|
|
116
|
+
}
|
|
117
|
+
function unknownChainAgents(cwd, steps) {
|
|
118
|
+
const d = discoverAgentsAll(cwd);
|
|
119
|
+
const known = new Set(allAgents(d).map((a) => a.name));
|
|
120
|
+
return [...new Set(steps.map((s) => s.agent).filter((a) => !known.has(a)))].sort((a, b) => a.localeCompare(b));
|
|
121
|
+
}
|
|
122
|
+
function chainStepWarnings(ctx, steps) {
|
|
123
|
+
const warnings = [];
|
|
124
|
+
const available = new Set(discoverAvailableSkills(ctx.cwd).map((s) => s.name));
|
|
125
|
+
for (let i = 0;i < steps.length; i++) {
|
|
126
|
+
const s = steps[i];
|
|
127
|
+
if (s.model) {
|
|
128
|
+
const found = ctx.modelRegistry.getAvailable().some((m) => `${m.provider}/${m.id}` === s.model || m.id === s.model);
|
|
129
|
+
if (!found)
|
|
130
|
+
warnings.push(`Warning: step ${i + 1} (${s.agent}): model '${s.model}' is not in the current model registry.`);
|
|
131
|
+
}
|
|
132
|
+
if (Array.isArray(s.skills) && s.skills.length > 0) {
|
|
133
|
+
const missing = s.skills.filter((sk) => !available.has(sk));
|
|
134
|
+
if (missing.length)
|
|
135
|
+
warnings.push(`Warning: step ${i + 1} (${s.agent}): skills not found: ${missing.join(", ")}.`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return warnings;
|
|
139
|
+
}
|
|
140
|
+
function modelWarning(ctx, model) {
|
|
141
|
+
if (!model)
|
|
142
|
+
return;
|
|
143
|
+
const found = ctx.modelRegistry.getAvailable().some((m) => `${m.provider}/${m.id}` === model || m.id === model);
|
|
144
|
+
return found ? undefined : `Warning: model '${model}' is not in the current model registry.`;
|
|
145
|
+
}
|
|
146
|
+
function fallbackModelsWarning(ctx, fallbackModels) {
|
|
147
|
+
if (!fallbackModels || fallbackModels.length === 0)
|
|
148
|
+
return;
|
|
149
|
+
const available = new Set(ctx.modelRegistry.getAvailable().flatMap((m) => [`${m.provider}/${m.id}`, m.id]));
|
|
150
|
+
const missing = fallbackModels.filter((model) => !available.has(model));
|
|
151
|
+
return missing.length ? `Warning: fallback models not in the current model registry: ${missing.join(", ")}.` : undefined;
|
|
152
|
+
}
|
|
153
|
+
function skillsWarning(cwd, skills) {
|
|
154
|
+
if (!skills || skills.length === 0)
|
|
155
|
+
return;
|
|
156
|
+
const available = new Set(discoverAvailableSkills(cwd).map((s) => s.name));
|
|
157
|
+
const missing = skills.filter((s) => !available.has(s));
|
|
158
|
+
return missing.length ? `Warning: skills not found: ${missing.join(", ")}.` : undefined;
|
|
159
|
+
}
|
|
160
|
+
function editableAgentConfig(agent) {
|
|
161
|
+
const base = agent.override?.base;
|
|
162
|
+
if (!base)
|
|
163
|
+
return { ...agent };
|
|
164
|
+
return {
|
|
165
|
+
...agent,
|
|
166
|
+
model: base.model,
|
|
167
|
+
fallbackModels: base.fallbackModels ? [...base.fallbackModels] : undefined,
|
|
168
|
+
thinking: base.thinking,
|
|
169
|
+
systemPromptMode: base.systemPromptMode,
|
|
170
|
+
inheritProjectContext: base.inheritProjectContext,
|
|
171
|
+
inheritSkills: base.inheritSkills,
|
|
172
|
+
defaultContext: base.defaultContext,
|
|
173
|
+
disabled: base.disabled,
|
|
174
|
+
systemPrompt: base.systemPrompt,
|
|
175
|
+
skills: base.skills ? [...base.skills] : undefined,
|
|
176
|
+
tools: base.tools ? [...base.tools] : undefined,
|
|
177
|
+
mcpDirectTools: base.mcpDirectTools ? [...base.mcpDirectTools] : undefined,
|
|
178
|
+
subagentOnlyExtensions: base.subagentOnlyExtensions ? [...base.subagentOnlyExtensions] : undefined,
|
|
179
|
+
completionGuard: base.completionGuard,
|
|
180
|
+
override: undefined
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
function readAgentFrontmatterFields(filePath) {
|
|
184
|
+
try {
|
|
185
|
+
const { frontmatter } = parseFrontmatter(fs.readFileSync(filePath, "utf-8"));
|
|
186
|
+
return new Set(Object.keys(frontmatter));
|
|
187
|
+
} catch {
|
|
188
|
+
return new Set;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function preservedAgentFrontmatterFields(agent, cfg) {
|
|
192
|
+
const fields = readAgentFrontmatterFields(agent.filePath);
|
|
193
|
+
const changed = (...names) => {
|
|
194
|
+
for (const name of names)
|
|
195
|
+
fields.delete(name);
|
|
196
|
+
};
|
|
197
|
+
if (hasKey(cfg, "name"))
|
|
198
|
+
changed("name");
|
|
199
|
+
if (hasKey(cfg, "package"))
|
|
200
|
+
changed("package");
|
|
201
|
+
if (hasKey(cfg, "description"))
|
|
202
|
+
changed("description");
|
|
203
|
+
if (hasKey(cfg, "systemPrompt"))
|
|
204
|
+
changed("systemPrompt");
|
|
205
|
+
if (hasKey(cfg, "model"))
|
|
206
|
+
changed("model");
|
|
207
|
+
if (hasKey(cfg, "fallbackModels"))
|
|
208
|
+
changed("fallbackModels");
|
|
209
|
+
if (hasKey(cfg, "tools"))
|
|
210
|
+
changed("tools");
|
|
211
|
+
if (hasKey(cfg, "skills"))
|
|
212
|
+
changed("skill", "skills");
|
|
213
|
+
if (hasKey(cfg, "extensions"))
|
|
214
|
+
changed("extensions");
|
|
215
|
+
if (hasKey(cfg, "subagentOnlyExtensions"))
|
|
216
|
+
changed("subagentOnlyExtensions");
|
|
217
|
+
if (hasKey(cfg, "thinking")) {
|
|
218
|
+
changed("thinking");
|
|
219
|
+
if (cfg.thinking === "off")
|
|
220
|
+
fields.add("thinking");
|
|
221
|
+
}
|
|
222
|
+
if (hasKey(cfg, "systemPromptMode")) {
|
|
223
|
+
changed("systemPromptMode");
|
|
224
|
+
fields.add("systemPromptMode");
|
|
225
|
+
}
|
|
226
|
+
if (hasKey(cfg, "inheritProjectContext")) {
|
|
227
|
+
changed("inheritProjectContext");
|
|
228
|
+
fields.add("inheritProjectContext");
|
|
229
|
+
}
|
|
230
|
+
if (hasKey(cfg, "inheritSkills")) {
|
|
231
|
+
changed("inheritSkills");
|
|
232
|
+
fields.add("inheritSkills");
|
|
233
|
+
}
|
|
234
|
+
if (hasKey(cfg, "defaultContext"))
|
|
235
|
+
changed("defaultContext");
|
|
236
|
+
if (hasKey(cfg, "output"))
|
|
237
|
+
changed("output");
|
|
238
|
+
if (hasKey(cfg, "reads"))
|
|
239
|
+
changed("defaultReads");
|
|
240
|
+
if (hasKey(cfg, "progress"))
|
|
241
|
+
changed("defaultProgress");
|
|
242
|
+
if (hasKey(cfg, "maxSubagentDepth"))
|
|
243
|
+
changed("maxSubagentDepth");
|
|
244
|
+
if (hasKey(cfg, "completionGuard")) {
|
|
245
|
+
changed("completionGuard");
|
|
246
|
+
if (cfg.completionGuard === true)
|
|
247
|
+
fields.add("completionGuard");
|
|
248
|
+
}
|
|
249
|
+
if (hasKey(cfg, "toolBudget"))
|
|
250
|
+
changed("toolBudget");
|
|
251
|
+
return fields;
|
|
252
|
+
}
|
|
253
|
+
function parseStepList(raw) {
|
|
254
|
+
if (!Array.isArray(raw))
|
|
255
|
+
return { error: "config.steps must be an array." };
|
|
256
|
+
if (raw.length === 0)
|
|
257
|
+
return { error: "config.steps must include at least one step." };
|
|
258
|
+
const steps = [];
|
|
259
|
+
for (let i = 0;i < raw.length; i++) {
|
|
260
|
+
const item = raw[i];
|
|
261
|
+
if (!item || typeof item !== "object" || Array.isArray(item))
|
|
262
|
+
return { error: `config.steps[${i}] must be an object.` };
|
|
263
|
+
const s = item;
|
|
264
|
+
if (typeof s.agent !== "string" || !s.agent.trim())
|
|
265
|
+
return { error: `config.steps[${i}].agent must be a non-empty string.` };
|
|
266
|
+
const step = { agent: s.agent.trim(), task: typeof s.task === "string" ? s.task : "" };
|
|
267
|
+
if (hasKey(s, "phase")) {
|
|
268
|
+
if (typeof s.phase === "string")
|
|
269
|
+
step.phase = s.phase;
|
|
270
|
+
else
|
|
271
|
+
return { error: `config.steps[${i}].phase must be a string.` };
|
|
272
|
+
}
|
|
273
|
+
if (hasKey(s, "label")) {
|
|
274
|
+
if (typeof s.label === "string")
|
|
275
|
+
step.label = s.label;
|
|
276
|
+
else
|
|
277
|
+
return { error: `config.steps[${i}].label must be a string.` };
|
|
278
|
+
}
|
|
279
|
+
if (hasKey(s, "as")) {
|
|
280
|
+
if (typeof s.as === "string")
|
|
281
|
+
step.as = s.as;
|
|
282
|
+
else
|
|
283
|
+
return { error: `config.steps[${i}].as must be a string.` };
|
|
284
|
+
}
|
|
285
|
+
if (hasKey(s, "outputSchema")) {
|
|
286
|
+
if (typeof s.outputSchema === "string")
|
|
287
|
+
step.outputSchema = s.outputSchema;
|
|
288
|
+
else
|
|
289
|
+
return { error: `config.steps[${i}].outputSchema must be a schema file path string for saved chains.` };
|
|
290
|
+
}
|
|
291
|
+
if (hasKey(s, "output")) {
|
|
292
|
+
if (s.output === false)
|
|
293
|
+
step.output = false;
|
|
294
|
+
else if (typeof s.output === "string")
|
|
295
|
+
step.output = s.output;
|
|
296
|
+
else
|
|
297
|
+
return { error: `config.steps[${i}].output must be a string or false.` };
|
|
298
|
+
}
|
|
299
|
+
if (hasKey(s, "outputMode")) {
|
|
300
|
+
if (s.outputMode === "inline" || s.outputMode === "file-only")
|
|
301
|
+
step.outputMode = s.outputMode;
|
|
302
|
+
else
|
|
303
|
+
return { error: `config.steps[${i}].outputMode must be 'inline' or 'file-only'.` };
|
|
304
|
+
}
|
|
305
|
+
if (hasKey(s, "reads")) {
|
|
306
|
+
if (s.reads === false)
|
|
307
|
+
step.reads = false;
|
|
308
|
+
else if (Array.isArray(s.reads))
|
|
309
|
+
step.reads = s.reads.filter((v) => typeof v === "string").map((v) => v.trim()).filter(Boolean);
|
|
310
|
+
else
|
|
311
|
+
return { error: `config.steps[${i}].reads must be an array or false.` };
|
|
312
|
+
}
|
|
313
|
+
if (hasKey(s, "model")) {
|
|
314
|
+
if (typeof s.model === "string")
|
|
315
|
+
step.model = s.model;
|
|
316
|
+
else
|
|
317
|
+
return { error: `config.steps[${i}].model must be a string.` };
|
|
318
|
+
}
|
|
319
|
+
if (hasKey(s, "skills")) {
|
|
320
|
+
if (s.skills === false)
|
|
321
|
+
step.skills = false;
|
|
322
|
+
else if (Array.isArray(s.skills))
|
|
323
|
+
step.skills = s.skills.filter((v) => typeof v === "string").map((v) => v.trim()).filter(Boolean);
|
|
324
|
+
else
|
|
325
|
+
return { error: `config.steps[${i}].skills must be an array or false.` };
|
|
326
|
+
}
|
|
327
|
+
if (hasKey(s, "progress")) {
|
|
328
|
+
if (typeof s.progress === "boolean")
|
|
329
|
+
step.progress = s.progress;
|
|
330
|
+
else
|
|
331
|
+
return { error: `config.steps[${i}].progress must be a boolean.` };
|
|
332
|
+
}
|
|
333
|
+
if (hasKey(s, "toolBudget")) {
|
|
334
|
+
const validation = validateToolBudgetConfig(s.toolBudget, `config.steps[${i}].toolBudget`);
|
|
335
|
+
if (validation.error)
|
|
336
|
+
return { error: validation.error };
|
|
337
|
+
step.toolBudget = s.toolBudget;
|
|
338
|
+
}
|
|
339
|
+
steps.push(step);
|
|
340
|
+
}
|
|
341
|
+
return { steps };
|
|
342
|
+
}
|
|
343
|
+
function parseTools(raw) {
|
|
344
|
+
const tools = [];
|
|
345
|
+
const mcpDirectTools = [];
|
|
346
|
+
for (const item of parseCsv(raw)) {
|
|
347
|
+
if (item.startsWith("mcp:")) {
|
|
348
|
+
const direct = item.slice(4).trim();
|
|
349
|
+
if (direct)
|
|
350
|
+
mcpDirectTools.push(direct);
|
|
351
|
+
} else
|
|
352
|
+
tools.push(item);
|
|
353
|
+
}
|
|
354
|
+
return { tools: tools.length ? tools : undefined, mcpDirectTools: mcpDirectTools.length ? mcpDirectTools : undefined };
|
|
355
|
+
}
|
|
356
|
+
function applyAgentConfig(target, cfg) {
|
|
357
|
+
if (hasKey(cfg, "systemPrompt")) {
|
|
358
|
+
if (cfg.systemPrompt === false || cfg.systemPrompt === "")
|
|
359
|
+
target.systemPrompt = "";
|
|
360
|
+
else if (typeof cfg.systemPrompt === "string")
|
|
361
|
+
target.systemPrompt = cfg.systemPrompt;
|
|
362
|
+
else
|
|
363
|
+
return "config.systemPrompt must be a string or false when provided.";
|
|
364
|
+
}
|
|
365
|
+
if (hasKey(cfg, "model")) {
|
|
366
|
+
if (cfg.model === false || cfg.model === "")
|
|
367
|
+
target.model = undefined;
|
|
368
|
+
else if (typeof cfg.model === "string")
|
|
369
|
+
target.model = cfg.model.trim() || undefined;
|
|
370
|
+
else
|
|
371
|
+
return "config.model must be a string or false when provided.";
|
|
372
|
+
}
|
|
373
|
+
if (hasKey(cfg, "fallbackModels")) {
|
|
374
|
+
if (cfg.fallbackModels === false || cfg.fallbackModels === "")
|
|
375
|
+
target.fallbackModels = undefined;
|
|
376
|
+
else if (typeof cfg.fallbackModels === "string") {
|
|
377
|
+
const models = parseCsv(cfg.fallbackModels);
|
|
378
|
+
target.fallbackModels = models.length ? models : undefined;
|
|
379
|
+
} else if (Array.isArray(cfg.fallbackModels)) {
|
|
380
|
+
const models = cfg.fallbackModels.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean);
|
|
381
|
+
target.fallbackModels = models.length ? [...new Set(models)] : undefined;
|
|
382
|
+
} else
|
|
383
|
+
return "config.fallbackModels must be a comma-separated string, string array, or false when provided.";
|
|
384
|
+
}
|
|
385
|
+
if (hasKey(cfg, "tools")) {
|
|
386
|
+
if (cfg.tools === false || cfg.tools === "") {
|
|
387
|
+
target.tools = undefined;
|
|
388
|
+
target.mcpDirectTools = undefined;
|
|
389
|
+
} else if (typeof cfg.tools === "string") {
|
|
390
|
+
const parsed = parseTools(cfg.tools);
|
|
391
|
+
target.tools = parsed.tools;
|
|
392
|
+
target.mcpDirectTools = parsed.mcpDirectTools;
|
|
393
|
+
} else
|
|
394
|
+
return "config.tools must be a comma-separated string or false when provided.";
|
|
395
|
+
}
|
|
396
|
+
if (hasKey(cfg, "skills")) {
|
|
397
|
+
if (cfg.skills === false || cfg.skills === "")
|
|
398
|
+
target.skills = undefined;
|
|
399
|
+
else if (typeof cfg.skills === "string") {
|
|
400
|
+
const skills = parseCsv(cfg.skills);
|
|
401
|
+
target.skills = skills.length ? skills : undefined;
|
|
402
|
+
} else
|
|
403
|
+
return "config.skills must be a comma-separated string or false when provided.";
|
|
404
|
+
}
|
|
405
|
+
if (hasKey(cfg, "extensions")) {
|
|
406
|
+
if (cfg.extensions === false)
|
|
407
|
+
target.extensions = undefined;
|
|
408
|
+
else if (cfg.extensions === "")
|
|
409
|
+
target.extensions = [];
|
|
410
|
+
else if (typeof cfg.extensions === "string")
|
|
411
|
+
target.extensions = parseCsv(cfg.extensions);
|
|
412
|
+
else
|
|
413
|
+
return "config.extensions must be a comma-separated string, empty string, or false when provided.";
|
|
414
|
+
}
|
|
415
|
+
if (hasKey(cfg, "subagentOnlyExtensions")) {
|
|
416
|
+
if (cfg.subagentOnlyExtensions === false)
|
|
417
|
+
target.subagentOnlyExtensions = undefined;
|
|
418
|
+
else if (cfg.subagentOnlyExtensions === "")
|
|
419
|
+
target.subagentOnlyExtensions = [];
|
|
420
|
+
else if (typeof cfg.subagentOnlyExtensions === "string")
|
|
421
|
+
target.subagentOnlyExtensions = parseCsv(cfg.subagentOnlyExtensions);
|
|
422
|
+
else
|
|
423
|
+
return "config.subagentOnlyExtensions must be a comma-separated string, empty string, or false when provided.";
|
|
424
|
+
}
|
|
425
|
+
if (hasKey(cfg, "thinking")) {
|
|
426
|
+
if (cfg.thinking === false || cfg.thinking === "")
|
|
427
|
+
target.thinking = undefined;
|
|
428
|
+
else if (typeof cfg.thinking === "string")
|
|
429
|
+
target.thinking = cfg.thinking.trim() || undefined;
|
|
430
|
+
else
|
|
431
|
+
return "config.thinking must be a string or false when provided.";
|
|
432
|
+
}
|
|
433
|
+
if (hasKey(cfg, "systemPromptMode")) {
|
|
434
|
+
if (cfg.systemPromptMode === "append" || cfg.systemPromptMode === "replace")
|
|
435
|
+
target.systemPromptMode = cfg.systemPromptMode;
|
|
436
|
+
else
|
|
437
|
+
return "config.systemPromptMode must be 'append' or 'replace' when provided.";
|
|
438
|
+
}
|
|
439
|
+
if (hasKey(cfg, "inheritProjectContext")) {
|
|
440
|
+
if (typeof cfg.inheritProjectContext !== "boolean")
|
|
441
|
+
return "config.inheritProjectContext must be a boolean when provided.";
|
|
442
|
+
target.inheritProjectContext = cfg.inheritProjectContext;
|
|
443
|
+
}
|
|
444
|
+
if (hasKey(cfg, "inheritSkills")) {
|
|
445
|
+
if (typeof cfg.inheritSkills !== "boolean")
|
|
446
|
+
return "config.inheritSkills must be a boolean when provided.";
|
|
447
|
+
target.inheritSkills = cfg.inheritSkills;
|
|
448
|
+
}
|
|
449
|
+
if (hasKey(cfg, "defaultContext")) {
|
|
450
|
+
if (cfg.defaultContext === false || cfg.defaultContext === "")
|
|
451
|
+
target.defaultContext = undefined;
|
|
452
|
+
else if (cfg.defaultContext === "fresh" || cfg.defaultContext === "fork")
|
|
453
|
+
target.defaultContext = cfg.defaultContext;
|
|
454
|
+
else
|
|
455
|
+
return "config.defaultContext must be 'fresh', 'fork', or false when provided.";
|
|
456
|
+
}
|
|
457
|
+
if (hasKey(cfg, "output")) {
|
|
458
|
+
if (cfg.output === false || cfg.output === "")
|
|
459
|
+
target.output = undefined;
|
|
460
|
+
else if (typeof cfg.output === "string")
|
|
461
|
+
target.output = cfg.output;
|
|
462
|
+
else
|
|
463
|
+
return "config.output must be a string or false when provided.";
|
|
464
|
+
}
|
|
465
|
+
if (hasKey(cfg, "reads")) {
|
|
466
|
+
if (cfg.reads === false || cfg.reads === "")
|
|
467
|
+
target.defaultReads = undefined;
|
|
468
|
+
else if (typeof cfg.reads === "string") {
|
|
469
|
+
const reads = parseCsv(cfg.reads);
|
|
470
|
+
target.defaultReads = reads.length ? reads : undefined;
|
|
471
|
+
} else
|
|
472
|
+
return "config.reads must be a comma-separated string or false when provided.";
|
|
473
|
+
}
|
|
474
|
+
if (hasKey(cfg, "progress")) {
|
|
475
|
+
if (typeof cfg.progress !== "boolean")
|
|
476
|
+
return "config.progress must be a boolean when provided.";
|
|
477
|
+
target.defaultProgress = cfg.progress;
|
|
478
|
+
}
|
|
479
|
+
if (hasKey(cfg, "maxSubagentDepth")) {
|
|
480
|
+
if (cfg.maxSubagentDepth === false || cfg.maxSubagentDepth === "")
|
|
481
|
+
target.maxSubagentDepth = undefined;
|
|
482
|
+
else if (typeof cfg.maxSubagentDepth === "number" && Number.isInteger(cfg.maxSubagentDepth) && cfg.maxSubagentDepth >= 0) {
|
|
483
|
+
target.maxSubagentDepth = cfg.maxSubagentDepth;
|
|
484
|
+
} else
|
|
485
|
+
return "config.maxSubagentDepth must be an integer >= 0 or false when provided.";
|
|
486
|
+
}
|
|
487
|
+
if (hasKey(cfg, "completionGuard")) {
|
|
488
|
+
if (typeof cfg.completionGuard !== "boolean")
|
|
489
|
+
return "config.completionGuard must be a boolean when provided.";
|
|
490
|
+
target.completionGuard = cfg.completionGuard;
|
|
491
|
+
}
|
|
492
|
+
if (hasKey(cfg, "toolBudget")) {
|
|
493
|
+
if (cfg.toolBudget === false || cfg.toolBudget === "")
|
|
494
|
+
target.toolBudget = undefined;
|
|
495
|
+
else {
|
|
496
|
+
const validation = validateToolBudgetConfig(cfg.toolBudget, "config.toolBudget");
|
|
497
|
+
if (validation.error)
|
|
498
|
+
return validation.error;
|
|
499
|
+
target.toolBudget = cfg.toolBudget;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
function resolveTarget(kind, name, matches, cwd, scopeHint) {
|
|
505
|
+
const mutable = matches.filter((m) => isMutableSource(m.source));
|
|
506
|
+
if (mutable.length === 0) {
|
|
507
|
+
if (matches.length > 0) {
|
|
508
|
+
return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' is read-only and cannot be modified. Create a same-named ${kind} in user or project scope to override it.`, true);
|
|
509
|
+
}
|
|
510
|
+
const available = availableNames(cwd, kind);
|
|
511
|
+
return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' not found. Available: ${available.join(", ") || "none"}.`, true);
|
|
512
|
+
}
|
|
513
|
+
if (mutable.length === 1)
|
|
514
|
+
return mutable[0];
|
|
515
|
+
const scope = asDisambiguationScope(scopeHint);
|
|
516
|
+
if (!scope) {
|
|
517
|
+
const paths = mutable.map((m) => `${m.source}: ${m.filePath}`).join(`
|
|
518
|
+
`);
|
|
519
|
+
return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' exists in both scopes. Specify agentScope: 'user' or 'project'.
|
|
520
|
+
${paths}`, true);
|
|
521
|
+
}
|
|
522
|
+
const scoped = mutable.filter((m) => m.source === scope);
|
|
523
|
+
if (scoped.length === 0)
|
|
524
|
+
return result(`${kind === "agent" ? "Agent" : "Chain"} '${name}' not found in scope '${scope}'.`, true);
|
|
525
|
+
if (scoped.length > 1)
|
|
526
|
+
return result(`Multiple ${kind}s named '${name}' found in scope '${scope}': ${scoped.map((m) => m.filePath).join(", ")}`, true);
|
|
527
|
+
return scoped[0];
|
|
528
|
+
}
|
|
529
|
+
function renamePath(kind, currentPath, newName, scope, cwd) {
|
|
530
|
+
if (nameExistsInScope(cwd, scope, newName, currentPath))
|
|
531
|
+
return { error: `Name '${newName}' already exists in ${scope} scope.` };
|
|
532
|
+
const ext = kind === "agent" ? ".md" : currentPath.endsWith(".chain.json") ? ".chain.json" : ".chain.md";
|
|
533
|
+
const filePath = path.join(path.dirname(currentPath), `${newName}${ext}`);
|
|
534
|
+
if (fs.existsSync(filePath) && filePath !== currentPath) {
|
|
535
|
+
return { error: `File already exists at ${filePath} but is not a valid ${kind} definition. Remove or rename it first.` };
|
|
536
|
+
}
|
|
537
|
+
fs.renameSync(currentPath, filePath);
|
|
538
|
+
return { filePath };
|
|
539
|
+
}
|
|
540
|
+
function formatAgentDetail(agent) {
|
|
541
|
+
const tools = [...agent.tools ?? [], ...(agent.mcpDirectTools ?? []).map((t) => `mcp:${t}`)];
|
|
542
|
+
const lines = [`Agent: ${agent.name} (${agent.source})`, `Path: ${agent.filePath}`, `Description: ${agent.description}`];
|
|
543
|
+
if (agent.packageName) {
|
|
544
|
+
lines.push(`Local name: ${frontmatterNameForConfig(agent)}`);
|
|
545
|
+
lines.push(`Package: ${agent.packageName}`);
|
|
546
|
+
}
|
|
547
|
+
if (agent.model)
|
|
548
|
+
lines.push(`Model: ${agent.model}`);
|
|
549
|
+
if (agent.fallbackModels?.length)
|
|
550
|
+
lines.push(`Fallback models: ${agent.fallbackModels.join(", ")}`);
|
|
551
|
+
if (tools.length)
|
|
552
|
+
lines.push(`Tools: ${tools.join(", ")}`);
|
|
553
|
+
if (agent.skills?.length)
|
|
554
|
+
lines.push(`Skills: ${agent.skills.join(", ")}`);
|
|
555
|
+
lines.push(`System prompt mode: ${agent.systemPromptMode}`);
|
|
556
|
+
lines.push(`Inherit project context: ${agent.inheritProjectContext ? "true" : "false"}`);
|
|
557
|
+
lines.push(`Inherit skills: ${agent.inheritSkills ? "true" : "false"}`);
|
|
558
|
+
if (agent.defaultContext)
|
|
559
|
+
lines.push(`Default context: ${agent.defaultContext}`);
|
|
560
|
+
if (agent.source === "builtin")
|
|
561
|
+
lines.push(`Disabled: ${agent.disabled ? "true" : "false"}`);
|
|
562
|
+
if (agent.extensions !== undefined)
|
|
563
|
+
lines.push(`Extensions: ${agent.extensions.length ? agent.extensions.join(", ") : "(none)"}`);
|
|
564
|
+
if (agent.subagentOnlyExtensions !== undefined)
|
|
565
|
+
lines.push(`Subagent-only extensions: ${agent.subagentOnlyExtensions.length ? agent.subagentOnlyExtensions.join(", ") : "(none)"}`);
|
|
566
|
+
if (agent.thinking)
|
|
567
|
+
lines.push(`Thinking: ${agent.thinking}`);
|
|
568
|
+
if (agent.output)
|
|
569
|
+
lines.push(`Output: ${agent.output}`);
|
|
570
|
+
if (agent.defaultReads?.length)
|
|
571
|
+
lines.push(`Reads: ${agent.defaultReads.join(", ")}`);
|
|
572
|
+
if (agent.defaultProgress)
|
|
573
|
+
lines.push("Progress: true");
|
|
574
|
+
if (agent.maxSubagentDepth !== undefined)
|
|
575
|
+
lines.push(`Max subagent depth: ${agent.maxSubagentDepth}`);
|
|
576
|
+
if (agent.completionGuard === false)
|
|
577
|
+
lines.push("Completion guard: false");
|
|
578
|
+
if (agent.toolBudget)
|
|
579
|
+
lines.push(`Tool budget: ${JSON.stringify(agent.toolBudget)}`);
|
|
580
|
+
if (agent.memory)
|
|
581
|
+
lines.push(`Memory: ${agent.memory.scope} scope, path: ${agent.memory.path}`);
|
|
582
|
+
if (agent.systemPrompt.trim())
|
|
583
|
+
lines.push("", "System Prompt:", agent.systemPrompt);
|
|
584
|
+
return lines.join(`
|
|
585
|
+
`);
|
|
586
|
+
}
|
|
587
|
+
function formatChainStepDetail(step, index) {
|
|
588
|
+
const lines = [];
|
|
589
|
+
if (step.expand || step.collect) {
|
|
590
|
+
const parallel = step.parallel && !Array.isArray(step.parallel) && typeof step.parallel === "object" ? step.parallel : undefined;
|
|
591
|
+
const expand = step.expand && typeof step.expand === "object" ? step.expand : undefined;
|
|
592
|
+
const collect = step.collect && typeof step.collect === "object" ? step.collect : undefined;
|
|
593
|
+
lines.push(`${index + 1}. Dynamic fanout${typeof collect?.as === "string" ? ` -> ${collect.as}` : ""}`);
|
|
594
|
+
if (expand?.from)
|
|
595
|
+
lines.push(` Expand: ${String(expand.from.output ?? "?")}${String(expand.from.path ?? "")}`);
|
|
596
|
+
if (typeof expand?.item === "string")
|
|
597
|
+
lines.push(` Item variable: ${expand.item}`);
|
|
598
|
+
if (typeof expand?.key === "string")
|
|
599
|
+
lines.push(` Key: ${expand.key}`);
|
|
600
|
+
if (typeof expand?.maxItems === "number")
|
|
601
|
+
lines.push(` Max items: ${expand.maxItems}`);
|
|
602
|
+
if (typeof expand?.onEmpty === "string")
|
|
603
|
+
lines.push(` On empty: ${expand.onEmpty}`);
|
|
604
|
+
if (parallel?.agent)
|
|
605
|
+
lines.push(` Agent: ${String(parallel.agent)}`);
|
|
606
|
+
if (typeof parallel?.label === "string")
|
|
607
|
+
lines.push(` Label: ${parallel.label}`);
|
|
608
|
+
if (typeof parallel?.task === "string" && parallel.task.trim())
|
|
609
|
+
lines.push(` Task: ${parallel.task}`);
|
|
610
|
+
if (parallel?.outputSchema)
|
|
611
|
+
lines.push(" Structured output: true");
|
|
612
|
+
if (parallel && "toolBudget" in parallel)
|
|
613
|
+
lines.push(` Tool budget: ${JSON.stringify(parallel.toolBudget)}`);
|
|
614
|
+
if (collect?.outputSchema)
|
|
615
|
+
lines.push(" Collect schema: true");
|
|
616
|
+
if (step.concurrency !== undefined)
|
|
617
|
+
lines.push(` Concurrency: ${step.concurrency}`);
|
|
618
|
+
if (step.failFast !== undefined)
|
|
619
|
+
lines.push(` Fail fast: ${step.failFast ? "true" : "false"}`);
|
|
620
|
+
return lines;
|
|
621
|
+
}
|
|
622
|
+
lines.push(`${index + 1}. ${step.agent}`);
|
|
623
|
+
if (step.task?.trim())
|
|
624
|
+
lines.push(` Task: ${step.task}`);
|
|
625
|
+
if (step.output === false)
|
|
626
|
+
lines.push(" Output: false");
|
|
627
|
+
else if (step.output)
|
|
628
|
+
lines.push(` Output: ${step.output}`);
|
|
629
|
+
if (step.outputMode)
|
|
630
|
+
lines.push(` Output mode: ${step.outputMode}`);
|
|
631
|
+
if (step.toolBudget)
|
|
632
|
+
lines.push(` Tool budget: ${JSON.stringify(step.toolBudget)}`);
|
|
633
|
+
if (step.reads === false)
|
|
634
|
+
lines.push(" Reads: false");
|
|
635
|
+
else if (Array.isArray(step.reads) && step.reads.length > 0)
|
|
636
|
+
lines.push(` Reads: ${step.reads.join(", ")}`);
|
|
637
|
+
if (step.model)
|
|
638
|
+
lines.push(` Model: ${step.model}`);
|
|
639
|
+
if (step.skills === false)
|
|
640
|
+
lines.push(" Skills: false");
|
|
641
|
+
else if (Array.isArray(step.skills) && step.skills.length > 0)
|
|
642
|
+
lines.push(` Skills: ${step.skills.join(", ")}`);
|
|
643
|
+
if (step.progress !== undefined)
|
|
644
|
+
lines.push(` Progress: ${step.progress ? "true" : "false"}`);
|
|
645
|
+
return lines;
|
|
646
|
+
}
|
|
647
|
+
function formatChainDetail(chain) {
|
|
648
|
+
const lines = [`Chain: ${chain.name} (${chain.source})`, `Path: ${chain.filePath}`, `Description: ${chain.description}`];
|
|
649
|
+
if (chain.packageName) {
|
|
650
|
+
lines.push(`Local name: ${frontmatterNameForConfig(chain)}`);
|
|
651
|
+
lines.push(`Package: ${chain.packageName}`);
|
|
652
|
+
}
|
|
653
|
+
lines.push("", "Steps:");
|
|
654
|
+
for (let i = 0;i < chain.steps.length; i++) {
|
|
655
|
+
lines.push(...formatChainStepDetail(chain.steps[i], i));
|
|
656
|
+
}
|
|
657
|
+
return lines.join(`
|
|
658
|
+
`);
|
|
659
|
+
}
|
|
660
|
+
export function handleList(params, ctx) {
|
|
661
|
+
const scope = normalizeListScope(params.agentScope) ?? "both";
|
|
662
|
+
const d = discoverAgentsAll(ctx.cwd);
|
|
663
|
+
const scopedAgents = allAgents(d).filter((a) => scope === "both" || a.source === "builtin" || a.source === "package" || a.source === scope).sort((a, b) => a.name.localeCompare(b.name));
|
|
664
|
+
const agents = scopedAgents.filter((a) => !a.disabled);
|
|
665
|
+
const chains = d.chains.filter((c) => scope === "both" || c.source === "package" || c.source === scope).sort((a, b) => a.name.localeCompare(b.name));
|
|
666
|
+
const diagnostics = d.chainDiagnostics.filter((entry) => scope === "both" || entry.source === scope);
|
|
667
|
+
const proactiveSuggestions = buildProactiveSkillSubagentRecommendationLines({
|
|
668
|
+
agents,
|
|
669
|
+
chains,
|
|
670
|
+
config: ctx.config?.proactiveSkillSubagents,
|
|
671
|
+
discoverAvailableSkills: () => discoverAvailableSkills(ctx.cwd)
|
|
672
|
+
});
|
|
673
|
+
const lines = [
|
|
674
|
+
"Executable agents:",
|
|
675
|
+
...agents.length ? agents.map((a) => `- ${a.name} (${a.source}${a.defaultContext ? `, context: ${a.defaultContext}` : ""}): ${a.description}`) : ["- (none)"],
|
|
676
|
+
"",
|
|
677
|
+
"Chains:",
|
|
678
|
+
...chains.length ? chains.map((c) => `- ${c.name} (${c.source}): ${c.description}`) : ["- (none)"],
|
|
679
|
+
...proactiveSuggestions.length ? ["", ...proactiveSuggestions] : [],
|
|
680
|
+
...diagnostics.length ? ["", "Chain diagnostics:", ...diagnostics.map((entry) => `- ${entry.filePath}: ${entry.error}`)] : []
|
|
681
|
+
];
|
|
682
|
+
return result(lines.join(`
|
|
683
|
+
`));
|
|
684
|
+
}
|
|
685
|
+
function formatModelSource(agent, currentModel) {
|
|
686
|
+
if (agent.override && agent.model !== agent.override.base.model) {
|
|
687
|
+
return `${agent.override.scope} override`;
|
|
688
|
+
}
|
|
689
|
+
if (agent.modelSource?.type === "subagents.defaultModel" && agent.model === agent.modelSource.model) {
|
|
690
|
+
return `${agent.modelSource.scope} defaultModel`;
|
|
691
|
+
}
|
|
692
|
+
if (agent.model)
|
|
693
|
+
return "builtin agent config";
|
|
694
|
+
if (currentModel)
|
|
695
|
+
return "inherits current session model";
|
|
696
|
+
return "inherit requested, but no current session model is available";
|
|
697
|
+
}
|
|
698
|
+
function handleModels(params, ctx) {
|
|
699
|
+
const requestedAgent = params.agent?.trim();
|
|
700
|
+
if (requestedAgent && !BUILTIN_AGENT_NAMES.includes(requestedAgent)) {
|
|
701
|
+
return result(`Builtin agent '${requestedAgent}' not found. Available: ${BUILTIN_AGENT_NAMES.join(", ")}.`, true);
|
|
702
|
+
}
|
|
703
|
+
const discovered = discoverAgentsAll(ctx.cwd);
|
|
704
|
+
const builtinByName = new Map(discovered.builtin.map((agent) => [agent.name, agent]));
|
|
705
|
+
const availableModels = ctx.modelRegistry.getAvailable().map(toModelInfo);
|
|
706
|
+
const currentModel = ctx.model ? { provider: ctx.model.provider, id: ctx.model.id } : undefined;
|
|
707
|
+
const preferredProvider = ctx.model?.provider;
|
|
708
|
+
const names = requestedAgent ? [requestedAgent] : [...BUILTIN_AGENT_NAMES];
|
|
709
|
+
if (requestedAgent) {
|
|
710
|
+
const agent = builtinByName.get(requestedAgent);
|
|
711
|
+
if (!agent)
|
|
712
|
+
return result(`Builtin agent '${requestedAgent}' not found.`, true);
|
|
713
|
+
const resolvedModel = resolveSubagentModelOverride(agent.model, currentModel, availableModels, preferredProvider);
|
|
714
|
+
const lines = [
|
|
715
|
+
"Builtin subagent model",
|
|
716
|
+
"",
|
|
717
|
+
`Agent: ${requestedAgent}`,
|
|
718
|
+
"Effective model:",
|
|
719
|
+
` ${resolvedModel ?? "(unresolved)"}`,
|
|
720
|
+
`Source: ${formatModelSource(agent, currentModel)}`
|
|
721
|
+
];
|
|
722
|
+
if (agent.override) {
|
|
723
|
+
lines.push("Override file:");
|
|
724
|
+
lines.push(` ${agent.override.path}`);
|
|
725
|
+
}
|
|
726
|
+
if (agent.model && resolvedModel && agent.model !== resolvedModel) {
|
|
727
|
+
lines.push("Requested model setting:");
|
|
728
|
+
lines.push(` ${agent.model}`);
|
|
729
|
+
}
|
|
730
|
+
if (agent.disabled)
|
|
731
|
+
lines.push("Disabled: true");
|
|
732
|
+
lines.push("Current session model:");
|
|
733
|
+
lines.push(` ${currentModel ? `${currentModel.provider}/${currentModel.id}` : "(unavailable)"}`);
|
|
734
|
+
return result(lines.join(`
|
|
735
|
+
`));
|
|
736
|
+
}
|
|
737
|
+
const lines = [
|
|
738
|
+
"Builtin subagent models",
|
|
739
|
+
"",
|
|
740
|
+
"Current session model:",
|
|
741
|
+
` ${currentModel ? `${currentModel.provider}/${currentModel.id}` : "(unavailable)"}`,
|
|
742
|
+
""
|
|
743
|
+
];
|
|
744
|
+
for (const name of names) {
|
|
745
|
+
const agent = builtinByName.get(name);
|
|
746
|
+
if (!agent) {
|
|
747
|
+
lines.push(name);
|
|
748
|
+
lines.push(" model:");
|
|
749
|
+
lines.push(" (builtin definition not found)");
|
|
750
|
+
lines.push(" source: missing");
|
|
751
|
+
lines.push("");
|
|
752
|
+
continue;
|
|
753
|
+
}
|
|
754
|
+
const resolvedModel = resolveSubagentModelOverride(agent.model, currentModel, availableModels, preferredProvider);
|
|
755
|
+
const source = `${formatModelSource(agent, currentModel)}${agent.disabled ? "; disabled" : ""}`;
|
|
756
|
+
lines.push(name);
|
|
757
|
+
lines.push(" model:");
|
|
758
|
+
lines.push(` ${resolvedModel ?? "(unresolved)"}`);
|
|
759
|
+
lines.push(` source: ${source}`);
|
|
760
|
+
lines.push("");
|
|
761
|
+
}
|
|
762
|
+
return result(lines.join(`
|
|
763
|
+
`));
|
|
764
|
+
}
|
|
765
|
+
function handleGet(params, ctx) {
|
|
766
|
+
if (!params.agent && !params.chainName)
|
|
767
|
+
return result("Specify 'agent' or 'chainName' for get.", true);
|
|
768
|
+
const hasBoth = Boolean(params.agent && params.chainName);
|
|
769
|
+
const blocks = [];
|
|
770
|
+
let anyFound = false;
|
|
771
|
+
if (params.agent) {
|
|
772
|
+
const matches = findAgents(params.agent, ctx.cwd, "both");
|
|
773
|
+
if (!matches.length) {
|
|
774
|
+
const msg = `Agent '${params.agent}' not found. Available: ${availableNames(ctx.cwd, "agent").join(", ") || "none"}.`;
|
|
775
|
+
if (!hasBoth)
|
|
776
|
+
return result(msg, true);
|
|
777
|
+
blocks.push(msg);
|
|
778
|
+
} else {
|
|
779
|
+
anyFound = true;
|
|
780
|
+
blocks.push(...matches.map(formatAgentDetail));
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (params.chainName) {
|
|
784
|
+
const matches = findChains(params.chainName, ctx.cwd, "both");
|
|
785
|
+
if (!matches.length) {
|
|
786
|
+
const msg = `Chain '${params.chainName}' not found. Available: ${availableNames(ctx.cwd, "chain").join(", ") || "none"}.`;
|
|
787
|
+
if (!hasBoth)
|
|
788
|
+
return result(msg, true);
|
|
789
|
+
blocks.push(msg);
|
|
790
|
+
} else {
|
|
791
|
+
anyFound = true;
|
|
792
|
+
blocks.push(...matches.map(formatChainDetail));
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
return result(blocks.join(`
|
|
7
796
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
`),V=Y.match(/^([ \t]+)/m)?.[1]??"",K=V?Y.replace(new RegExp(`^${K0(V)}`,"gm"),"").replace(/^\n/,""):Y;J[W]=K}return{frontmatter:J,body:Z}}import{Compile as L9}from"typebox/compile";class M extends Error{}var bJ=/^[A-Za-z_][A-Za-z0-9_]*$/,xJ=/^[A-Za-z_][A-Za-z0-9_]*$/,F$=/\{([A-Za-z_][A-Za-z0-9_]*)(?:\.([^{}]+))?\}/g,PJ=new Set(["task","previous","chain_dir","outputs"]),A0=new Set(["expand","parallel","collect","concurrency","failFast","phase","label","acceptance"]),hJ=new Set([...A0,"effectiveAcceptance","sessionFiles","thinkingOverrides"]),fJ=new Set(["from","item","key","maxItems","onEmpty"]),vJ=new Set(["output","path"]),T0=new Set(["agent","task","phase","label","outputSchema","cwd","output","outputMode","reads","progress","skill","model","toolBudget","acceptance"]),uJ=new Set([...T0,"outputName","structured","inheritProjectContext","inheritSkills","skills","outputPath","maxSubagentDepth","structuredOutput","structuredOutputSchema","tools","extensions","subagentOnlyExtensions","mcpDirectTools","completionGuard","systemPrompt","systemPromptMode","thinking","modelCandidates","sessionFile","effectiveAcceptance","parentSessionId"]),mJ=new Set(["as","outputSchema"]);function z0($){return bJ.test($)}function _0($,J){if($==="")return;if(!$.startsWith("/"))throw new M(`${J} must be a JSON Pointer starting with '/'.`);for(let B of $.slice(1).split("/"))if(/~(?![01])/.test(B))throw new M(`${J} contains invalid JSON Pointer escape.`)}function q$($,J,B){if(!$||typeof $!=="object"||Array.isArray($))throw new M(`${B} must be an object.`);for(let U of Object.keys($))if(!J.has(U))throw new M(`${B} does not support field '${U}'.`)}function gJ($,J,B){for(let U of $.matchAll(/\{([^{}]*)\}/g)){let Q=U[0],Z=U[1];if(Z===J||Z.startsWith(`${J}.`)){if(!F$.test(Q)||Z===`${J}.`||Z.includes(".."))throw new M(`Invalid item reference '${Q}' in ${B}.`);F$.lastIndex=0;continue}F$.lastIndex=0;let X=Z.match(/^[A-Za-z_][A-Za-z0-9_]*/)?.[0];if(X===J)throw new M(`Invalid item reference '${Q}' in ${B}.`);if(X&&PJ.has(X))continue;if(X)throw new M(`Unsupported template reference '${Q}' in ${B}.`)}if(F$.lastIndex=0,$.includes(`{${J}.}`)||new RegExp(`\\{${J}(?:\\.|$)[^}]*$`).test($))throw new M(`Invalid item reference in ${B}.`)}function C0($){return!!$&&typeof $==="object"&&!Array.isArray($)&&(Object.prototype.hasOwnProperty.call($,"expand")||Object.prototype.hasOwnProperty.call($,"collect"))}function j0($,J,B={}){let U=`Dynamic chain step ${J+1}`;if(q$($,B.allowRunnerFields?hJ:A0,U),!$.expand||!$.expand.from)throw new M(`${U} requires expand.from.`);if(q$($.expand,fJ,`${U} expand`),q$($.expand.from,vJ,`${U} expand.from`),!z0($.expand.from.output))throw new M(`${U} has invalid expand.from.output '${$.expand.from.output}'.`);if(_0($.expand.from.path,`${U} expand.from.path`),$.expand.key!==void 0)_0($.expand.key,`${U} expand.key`);let Q=$.expand.item??"item";if(!xJ.test(Q))throw new M(`${U} has invalid expand.item '${Q}'.`);if($.expand.maxItems===void 0&&B.maxItems===void 0)throw new M(`${U} requires expand.maxItems or config.chain.dynamicFanout.maxItems.`);if($.expand.maxItems!==void 0&&(!Number.isInteger($.expand.maxItems)||$.expand.maxItems<0))throw new M(`${U} expand.maxItems must be an integer >= 0.`);if(B.maxItems!==void 0&&(!Number.isInteger(B.maxItems)||B.maxItems<0))throw new M("config.chain.dynamicFanout.maxItems must be an integer >= 0.");if(!$.parallel||Array.isArray($.parallel))throw new M(`${U} requires a single parallel template object and cannot mix dynamic expand/collect with static parallel arrays.`);if(q$($.parallel,B.allowRunnerFields?uJ:T0,`${U} parallel`),"expand"in $.parallel)throw new M(`${U} does not support nested dynamic fanout.`);if(!$.parallel.agent)throw new M(`${U} parallel.agent is required.`);if(!$.collect?.as||!z0($.collect.as))throw new M(`${U} requires collect.as with a safe output name.`);q$($.collect,mJ,`${U} collect`);for(let[Z,X]of[["parallel.task",$.parallel.task],["parallel.label",$.parallel.label]])if(X)gJ(X,Q,`${U} ${Z}`)}var dJ=/\{outputs\.([^}]*)\}/g,R0=/^[A-Za-z_][A-Za-z0-9_]*$/;class g extends Error{}function O0($){if(O$($))return $.parallel.map((B)=>B.as).filter((B)=>Boolean(B));if(Y$($))return[$.collect.as];let J=$.as;return J?[J]:[]}function pJ($){if(O$($))return $.parallel.map((J)=>J.task??"{previous}");if(Y$($))return[$.parallel.task??"{previous}",$.parallel.label??""].filter(Boolean);return[$.task??"{previous}"]}function F0($,J={}){cJ($,J)}function cJ($,J={},B={}){let U=[...B.priorOutputNames??[]],Q=new Set(U),Z=new Set(U);for(let X=0;X<$.length;X++){let W=(B.startStepIndex??0)+X+1,G=$[X];if(C0(G)){if(!Y$(G))throw new g(`Dynamic chain step ${W} requires expand, a single parallel template object, and collect; dynamic expand/collect cannot be mixed with static parallel arrays.`);try{j0(G,W-1,J)}catch(H){if(H instanceof M)throw new g(H.message);throw H}if(!Q.has(G.expand.from.output))throw new g(`Dynamic chain step ${W} references unknown output '${G.expand.from.output}'. Named outputs are only available after producing step/group completes.`)}for(let H of O0(G)){if(!R0.test(H))throw new g(`Invalid chain output name '${H}' at step ${W}. Use /^[A-Za-z_][A-Za-z0-9_]*$/.`);if(Z.has(H))throw new g(`Duplicate chain output name '${H}'. Each as name must be unique.`);Z.add(H)}for(let H of pJ(G))for(let Y of H.matchAll(dJ)){let q=Y[0],V=Y[1];if(!R0.test(V))throw new g(`Invalid chain output reference '${q}' at step ${W}. Use {outputs.name} with /^[A-Za-z_][A-Za-z0-9_]*$/ names.`);if(!Q.has(V))throw new g(`Unknown chain output reference '${q}' at step ${W}. Named outputs are only available after producing step/group completes.`)}for(let H of O0(G))Q.add(H)}}var I0=new Set(["auto","none","attested","checked","verified","reviewed"]),N0=new Set(["changed-files","tests-added","commands-run","validation-output","residual-risks","no-staged-files","diff-summary","review-findings","manual-notes"]),oJ=new Set(["level","criteria","evidence","verify","review","stopRules","reason"]),lJ=new Set(["id","must","evidence","severity"]),nJ=new Set(["id","command","timeoutMs","cwd","env","allowFailure"]),iJ=new Set(["agent","focus","required"]);function I$($,J="acceptance"){let B=[];if($===void 0)return B;if($===!1)return B;if(typeof $==="string"){if(!I0.has($))B.push(`${J} has invalid level '${$}'.`);return B}if(!$||typeof $!=="object"||Array.isArray($))return B.push(`${J} must be a string level, false, or an object.`),B;let U=$;for(let Q of Object.keys(U))if(!oJ.has(Q))B.push(`${J}.${Q} is not supported.`);if(U.level!==void 0&&(typeof U.level!=="string"||!I0.has(U.level)))B.push(`${J}.level must be one of auto, none, attested, checked, verified, reviewed.`);if(U.level==="none"&&(typeof U.reason!=="string"||!U.reason.trim()))B.push(`${J}.reason is required when level is none.`);if(U.reason!==void 0&&typeof U.reason!=="string")B.push(`${J}.reason must be a string.`);if(U.criteria!==void 0&&!Array.isArray(U.criteria))B.push(`${J}.criteria must be an array.`);if(Array.isArray(U.criteria))for(let[Q,Z]of U.criteria.entries()){if(typeof Z==="string")continue;let X=`${J}.criteria[${Q}]`;if(!Z||typeof Z!=="object"||Array.isArray(Z)){B.push(`${X} must be a string or an object.`);continue}let W=Z;for(let G of Object.keys(W))if(!lJ.has(G))B.push(`${X}.${G} is not supported.`);if(typeof W.id!=="string"||!W.id.trim())B.push(`${X}.id is required.`);if(typeof W.must!=="string"||!W.must.trim())B.push(`${X}.must is required.`);if(W.evidence!==void 0&&!Array.isArray(W.evidence))B.push(`${X}.evidence must be an array.`);if(Array.isArray(W.evidence)){for(let[G,H]of W.evidence.entries())if(typeof H!=="string"||!N0.has(H))B.push(`${X}.evidence[${G}] is not a supported evidence kind.`)}if(W.severity!==void 0&&W.severity!=="required"&&W.severity!=="recommended")B.push(`${X}.severity must be required or recommended.`)}if(Array.isArray(U.evidence)){for(let[Q,Z]of U.evidence.entries())if(typeof Z!=="string"||!N0.has(Z))B.push(`${J}.evidence[${Q}] is not a supported evidence kind.`)}else if(U.evidence!==void 0)B.push(`${J}.evidence must be an array.`);if(U.verify!==void 0&&!Array.isArray(U.verify))B.push(`${J}.verify must be an array.`);if(Array.isArray(U.verify))for(let[Q,Z]of U.verify.entries()){if(!Z||typeof Z!=="object"||Array.isArray(Z)){B.push(`${J}.verify[${Q}] must be an object.`);continue}let X=Z;for(let W of Object.keys(X))if(!nJ.has(W))B.push(`${J}.verify[${Q}].${W} is not supported.`);if(typeof X.id!=="string"||!X.id.trim())B.push(`${J}.verify[${Q}].id is required.`);if(typeof X.command!=="string"||!X.command.trim())B.push(`${J}.verify[${Q}].command is required.`);if(X.timeoutMs!==void 0&&(typeof X.timeoutMs!=="number"||!Number.isInteger(X.timeoutMs)||X.timeoutMs<1))B.push(`${J}.verify[${Q}].timeoutMs must be an integer >= 1.`);if(X.cwd!==void 0&&typeof X.cwd!=="string")B.push(`${J}.verify[${Q}].cwd must be a string.`);if(X.env!==void 0){if(!X.env||typeof X.env!=="object"||Array.isArray(X.env))B.push(`${J}.verify[${Q}].env must be an object.`);else for(let[W,G]of Object.entries(X.env))if(typeof G!=="string")B.push(`${J}.verify[${Q}].env.${W} must be a string.`)}if(X.allowFailure!==void 0&&typeof X.allowFailure!=="boolean")B.push(`${J}.verify[${Q}].allowFailure must be a boolean.`)}if(U.review!==void 0&&U.review!==!1)if(!U.review||typeof U.review!=="object"||Array.isArray(U.review))B.push(`${J}.review must be false or an object.`);else{let Q=U.review;for(let Z of Object.keys(Q))if(!iJ.has(Z))B.push(`${J}.review.${Z} is not supported.`);if(Q.agent!==void 0&&typeof Q.agent!=="string")B.push(`${J}.review.agent must be a string.`);if(Q.focus!==void 0&&typeof Q.focus!=="string")B.push(`${J}.review.focus must be a string.`);if(Q.required!==void 0&&typeof Q.required!=="boolean")B.push(`${J}.review.required must be a boolean.`)}if(U.stopRules!==void 0&&!Array.isArray(U.stopRules))B.push(`${J}.stopRules must be an array.`);if(Array.isArray(U.stopRules)){for(let[Q,Z]of U.stopRules.entries())if(typeof Z!=="string")B.push(`${J}.stopRules[${Q}] must be a string.`)}return B}var sJ=["read","grep","find","ls"];function rJ($){if($==="*")return"*";if($===void 0)return[...sJ];return[...new Set($.map((J)=>J.trim()).filter(Boolean))]}function Z$($,J="toolBudget"){if($===void 0)return{};if(!$||typeof $!=="object"||Array.isArray($))return{error:`${J} must be an object with hard and optional soft/block.`};let B=$;if(typeof B.hard!=="number"||!Number.isInteger(B.hard)||B.hard<1)return{error:`${J}.hard must be an integer >= 1.`};if(B.soft!==void 0&&(typeof B.soft!=="number"||!Number.isInteger(B.soft)||B.soft<1))return{error:`${J}.soft must be an integer >= 1 when provided.`};if(B.soft!==void 0&&B.soft>B.hard)return{error:`${J}.soft must be <= ${J}.hard.`};if(B.block!==void 0&&B.block!=="*"){if(!Array.isArray(B.block))return{error:`${J}.block must be "*" or an array of tool names.`};if(B.block.length===0)return{error:`${J}.block must contain at least one tool name.`};for(let U of B.block)if(typeof U!=="string"||!U.trim())return{error:`${J}.block must contain non-empty tool names.`}}return{budget:{hard:B.hard,...B.soft!==void 0?{soft:B.soft}:{},block:rJ(B.block)}}}function aJ($,J){let B=J.split(`
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
`,"utf-8")}function N$($,J){if($===void 0)return;if($===!1)return!1;if(!Array.isArray($))throw Error(`Builtin override '${J.name}' in '${J.filePath}' has invalid '${J.field}'; expected an array of strings or false.`);let B=[];for(let U of $){if(typeof U!=="string")throw Error(`Builtin override '${J.name}' in '${J.filePath}' has invalid '${J.field}'; expected an array of strings or false.`);let Q=U.trim();if(Q)B.push(Q)}return B}function K1($,J,B){if(!J||typeof J!=="object"||Array.isArray(J))throw Error(`Builtin override '${$}' in '${B}' must be an object.`);let U=J,Q={};if("model"in U)if(typeof U.model==="string"||U.model===!1)Q.model=U.model;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'model'; expected a string or false.`);if("thinking"in U)if(typeof U.thinking==="string"||U.thinking===!1)Q.thinking=U.thinking;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'thinking'; expected a string or false.`);if("systemPromptMode"in U)if(U.systemPromptMode==="append"||U.systemPromptMode==="replace")Q.systemPromptMode=U.systemPromptMode;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'systemPromptMode'; expected 'append' or 'replace'.`);if("inheritProjectContext"in U)if(typeof U.inheritProjectContext==="boolean")Q.inheritProjectContext=U.inheritProjectContext;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'inheritProjectContext'; expected a boolean.`);if("inheritSkills"in U)if(typeof U.inheritSkills==="boolean")Q.inheritSkills=U.inheritSkills;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'inheritSkills'; expected a boolean.`);if("defaultContext"in U)if(U.defaultContext==="fresh"||U.defaultContext==="fork"||U.defaultContext===!1)Q.defaultContext=U.defaultContext;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'defaultContext'; expected 'fresh', 'fork', or false.`);if("disabled"in U)if(typeof U.disabled==="boolean")Q.disabled=U.disabled;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'disabled'; expected a boolean.`);if("completionGuard"in U)if(typeof U.completionGuard==="boolean")Q.completionGuard=U.completionGuard;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'completionGuard'; expected a boolean.`);if("toolBudget"in U)if(U.toolBudget===!1)Q.toolBudget=!1;else if(U.toolBudget&&typeof U.toolBudget==="object"&&!Array.isArray(U.toolBudget))Q.toolBudget=U.toolBudget;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'toolBudget'; expected an object or false.`);if("systemPrompt"in U)if(typeof U.systemPrompt==="string")Q.systemPrompt=U.systemPrompt;else throw Error(`Builtin override '${$}' in '${B}' has invalid 'systemPrompt'; expected a string.`);let Z=N$(U.fallbackModels,{filePath:B,name:$,field:"fallbackModels"});if(Z!==void 0)Q.fallbackModels=Z;let X=N$(U.skills,{filePath:B,name:$,field:"skills"});if(X!==void 0)Q.skills=X;let W=N$(U.tools,{filePath:B,name:$,field:"tools"});if(W!==void 0)Q.tools=W;let G=N$(U.subagentOnlyExtensions,{filePath:B,name:$,field:"subagentOnlyExtensions"});if(G!==void 0)Q.subagentOnlyExtensions=G;return Object.keys(Q).length>0?Q:void 0}function h0($){if(!$)return b0;let B=k$($).subagents;if(!B||typeof B!=="object"||Array.isArray(B))return b0;let U=B,Q;if("disableBuiltins"in U)if(typeof U.disableBuiltins==="boolean")Q=U.disableBuiltins;else throw Error(`Subagent settings in '${$}' have invalid 'disableBuiltins'; expected a boolean.`);let Z;if("disableThinking"in U)if(typeof U.disableThinking==="boolean")Z=U.disableThinking;else throw Error(`Subagent settings in '${$}' have invalid 'disableThinking'; expected a boolean.`);let X;if("defaultModel"in U)if(typeof U.defaultModel==="string"&&U.defaultModel.trim())X=U.defaultModel.trim();else throw Error(`Subagent settings in '${$}' have invalid 'defaultModel'; expected a non-empty string.`);let W=D0(U.modelScope,{filePath:$}),G={},H=U.agentOverrides;if(!H||typeof H!=="object"||Array.isArray(H))return{overrides:G,defaultModel:X,disableBuiltins:Q,disableThinking:Z,modelScope:W};for(let[Y,q]of Object.entries(H)){let V=K1(Y,q,$);if(V)G[Y]=V}return{overrides:G,defaultModel:X,disableBuiltins:Q,disableThinking:Z,modelScope:W}}function z1($,J,B,U){if(U&&J.defaultModel!==void 0)return{type:"subagents.defaultModel",scope:"project",path:U,model:J.defaultModel};return $.defaultModel!==void 0?{type:"subagents.defaultModel",scope:"user",path:B,model:$.defaultModel}:void 0}function E$($,J){if(!J)return $;return $.map((B)=>{if(B.model!==void 0)return B;let U={...B,model:J.model,modelSource:J},Q=S$.get(B);if(Q)S$.set(U,Q);return U})}function L$($,J,B){let U={...$,override:{...B,base:a$($)}};if(J.model!==void 0)U.model=J.model===!1?void 0:J.model;if(J.fallbackModels!==void 0)U.fallbackModels=J.fallbackModels===!1?void 0:[...J.fallbackModels];if(J.thinking!==void 0)U.thinking=J.thinking===!1?void 0:J.thinking;if(J.systemPromptMode!==void 0)U.systemPromptMode=J.systemPromptMode;if(J.inheritProjectContext!==void 0)U.inheritProjectContext=J.inheritProjectContext;if(J.inheritSkills!==void 0)U.inheritSkills=J.inheritSkills;if(J.defaultContext!==void 0)U.defaultContext=J.defaultContext===!1?void 0:J.defaultContext;if(J.disabled!==void 0)U.disabled=J.disabled;if(J.systemPrompt!==void 0)U.systemPrompt=J.systemPrompt;if(J.skills!==void 0)U.skills=J.skills===!1?void 0:[...J.skills];if(J.tools!==void 0){let{tools:Q,mcpDirectTools:Z}=u0(J.tools===!1?[]:J.tools);U.tools=Q,U.mcpDirectTools=Z}if(J.subagentOnlyExtensions!==void 0)U.subagentOnlyExtensions=J.subagentOnlyExtensions===!1?void 0:[...J.subagentOnlyExtensions];if(J.completionGuard!==void 0)U.completionGuard=J.completionGuard;if(J.toolBudget!==void 0)U.toolBudget=J.toolBudget===!1?void 0:J.toolBudget;return U}function _1($,J){if($.thinking===void 0)return $;return{...$,thinking:void 0,override:$.override??{...J,base:a$($)}}}function A1($,J,B,U,Q){let Z=B.disableBuiltins===!0&&Q!==null,X=B.disableBuiltins===void 0&&J.disableBuiltins===!0,W=B.disableThinking!==void 0&&Q!==null,G=W?B.disableThinking===!0:J.disableThinking===!0,H=W?{scope:"project",path:Q}:{scope:"user",path:U},Y=(q,V)=>{if(!G||V)return q;return _1(q,H)};return $.map((q)=>{let V=B.overrides[q.name];if(V&&Q)return Y(L$(q,V,{scope:"project",path:Q}),V.thinking!==void 0);if(Z&&Q)return Y(L$(q,{disabled:!0},{scope:"project",path:Q}),!1);let K=J.overrides[q.name];if(K)return Y(L$(q,K,{scope:"user",path:U}),!W&&K.thinking!==void 0);if(X)return Y(L$(q,{disabled:!0},{scope:"user",path:U}),!1);return Y(q,!1)})}function f0($,...J){let B=S$.get($);return B?J.some((U)=>B.has(U)):!1}function v0($,J,B){let U,Q=!1,Z=()=>{return U??={...$},U},X=(W,G,H)=>{if(f0($,...G))return;Z()[W]=H,Q=!0};if(J.model!==void 0)X("model",["model"],J.model===!1?void 0:J.model);if(J.fallbackModels!==void 0)X("fallbackModels",["fallbackModels"],J.fallbackModels===!1?void 0:[...J.fallbackModels]);if(J.thinking!==void 0)X("thinking",["thinking"],J.thinking===!1?void 0:J.thinking);if(J.systemPromptMode!==void 0)X("systemPromptMode",["systemPromptMode"],J.systemPromptMode);if(J.inheritProjectContext!==void 0)X("inheritProjectContext",["inheritProjectContext"],J.inheritProjectContext);if(J.inheritSkills!==void 0)X("inheritSkills",["inheritSkills"],J.inheritSkills);if(J.defaultContext!==void 0)X("defaultContext",["defaultContext"],J.defaultContext===!1?void 0:J.defaultContext);if(J.disabled!==void 0&&$.disabled===void 0)Z().disabled=J.disabled,Q=!0;if(J.skills!==void 0)X("skills",["skill","skills"],J.skills===!1?void 0:[...J.skills]);if(J.tools!==void 0&&!f0($,"tools")){let{tools:W,mcpDirectTools:G}=u0(J.tools===!1?[]:J.tools),H=Z();H.tools=W,H.mcpDirectTools=G,Q=!0}if(J.subagentOnlyExtensions!==void 0)X("subagentOnlyExtensions",["subagentOnlyExtensions"],J.subagentOnlyExtensions===!1?void 0:[...J.subagentOnlyExtensions]);if(J.completionGuard!==void 0)X("completionGuard",["completionGuard"],J.completionGuard);if(J.toolBudget!==void 0)X("toolBudget",["toolBudget"],J.toolBudget===!1?void 0:J.toolBudget);if(!Q||!U)return $;return U.override={...B,base:a$($)},U}function o$($,J,B,U,Q){return $.map((Z)=>{let X=B.overrides[Z.name];if(X&&Q)return v0(Z,X,{scope:"project",path:Q});let W=J.overrides[Z.name];if(W)return v0(Z,W,{scope:"user",path:U});return Z})}function m0($,J,B){let U=B==="project"?y$($):D$();if(!U)throw Error("Project override is not available here. No project config root was found.");if(!N.existsSync(U))return{path:U,removed:!1};let Q=k$(U),Z=Q.subagents;if(!Z||typeof Z!=="object"||Array.isArray(Z))return{path:U,removed:!1};let X={...Z},W=X.agentOverrides;if(!W||typeof W!=="object"||Array.isArray(W))return{path:U,removed:!1};let G={...W};if(!Object.prototype.hasOwnProperty.call(G,J))return{path:U,removed:!1};if(delete G[J],Object.keys(G).length>0)X.agentOverrides=G;else delete X.agentOverrides;if(Object.keys(X).length>0)Q.subagents=X;else delete Q.subagents;return t$(U,Q),{path:U,removed:!0}}function g0($,J,B,U){let Q=B==="project"?y$($):D$();if(!Q)throw Error("Project override is not available here. No project config root was found.");let Z=k$(Q),X=Z.subagents&&typeof Z.subagents==="object"&&!Array.isArray(Z.subagents)?{...Z.subagents}:{},W=X.agentOverrides&&typeof X.agentOverrides==="object"&&!Array.isArray(X.agentOverrides)?{...X.agentOverrides}:{},G=W[J],H=G&&typeof G==="object"&&!Array.isArray(G)?G:{};return W[J]={...H,...V1(U)},X.agentOverrides=W,Z.subagents=X,t$(Q,Z),Q}function d0($,J,B,U){let Q=B==="project"?y$($):D$();if(!Q)throw Error("Project override is not available here. No project config root was found.");if(!N.existsSync(Q))return{path:Q,removed:!1};let Z=k$(Q),X=Z.subagents;if(!X||typeof X!=="object"||Array.isArray(X))return{path:Q,removed:!1};let W=X.agentOverrides;if(!W||typeof W!=="object"||Array.isArray(W))return{path:Q,removed:!1};let G=W[J];if(!G||typeof G!=="object"||Array.isArray(G))return{path:Q,removed:!1};let H={...G},Y=!1;for(let V of U)if(Object.prototype.hasOwnProperty.call(H,V))delete H[V],Y=!0;if(!Y)return{path:Q,removed:!1};let q={...X};if(Object.keys(H).length>0)q.agentOverrides[J]=H;else{let V={...W};if(delete V[J],Object.keys(V).length>0)q.agentOverrides=V;else delete q.agentOverrides}if(Object.keys(q).length>0)Z.subagents=q;else delete Z.subagents;return t$(Q,Z),{path:Q,removed:!0}}function e$($,J){let B=[];if(!N.existsSync($))return B;let U;try{U=N.readdirSync($,{withFileTypes:!0}).sort((Q,Z)=>Q.name.localeCompare(Z.name))}catch{return B}for(let Q of U){let Z=j.join($,Q.name);if(Q.isDirectory()){B.push(...e$(Z,J));continue}if(!Q.isFile()&&!Q.isSymbolicLink())continue;if(!J(Q.name))continue;B.push(Z)}return B}function T1($,J){let U=j.relative($,J).split(j.sep).map((Q)=>Q.toLowerCase());if(j.basename($).toLowerCase()===".agents")U.unshift(".agents");return U.some((Q,Z)=>Q===".agents"&&U[Z+1]==="skills")}function X$($,J){let B=[];for(let U of e$($,(Q)=>Q.endsWith(".md")&&!Q.endsWith(".chain.md"))){if(T1($,U))continue;let Q;try{Q=N.readFileSync(U,"utf-8")}catch{continue}let{frontmatter:Z,body:X}=Q$(Q);if(!Z.name||!Z.description)continue;let W=Z.name,G=n(Z.package,`Agent '${W}' package`);if(G.error)continue;let H=G.packageName,Y=m(W,H),q=Z.tools?.split(",").map((F)=>F.trim()).filter(Boolean),V=[],K=[];if(q)for(let F of q)if(F.startsWith("mcp:"))V.push(F.slice(4));else K.push(F);let z=Z.defaultReads?.split(",").map((F)=>F.trim()).filter(Boolean),O=(Z.skill||Z.skills)?.split(",").map((F)=>F.trim()).filter(Boolean),R=Z.fallbackModels?.split(",").map((F)=>F.trim()).filter(Boolean),D=Z.systemPromptMode==="replace"?"replace":Z.systemPromptMode==="append"?"append":i$(W),x=Z.inheritProjectContext==="true"?!0:Z.inheritProjectContext==="false"?!1:s$(W),y=Z.inheritSkills==="true"?!0:Z.inheritSkills==="false"?!1:r$(),P=Z.defaultContext==="fork"?"fork":Z.defaultContext==="fresh"?"fresh":void 0,h;if(Z.extensions!==void 0)h=Z.extensions.split(",").map((F)=>F.trim()).filter(Boolean);let r;if(Z.subagentOnlyExtensions!==void 0)r=Z.subagentOnlyExtensions.split(",").map((F)=>F.trim()).filter(Boolean);let I={};for(let[F,c]of Object.entries(Z))if(!m$.has(F))I[F]=c;let u=Number(Z.maxSubagentDepth),t;if(Z.toolBudget!==void 0&&Z.toolBudget.trim()){let F=JSON.parse(Z.toolBudget);if(!F||typeof F!=="object"||Array.isArray(F))throw Error(`Agent '${W}' has invalid toolBudget frontmatter; expected a JSON object.`);t=F}let h$=Z.completionGuard==="false"?!1:Z.completionGuard==="true"?!0:void 0,k={name:Y,localName:W,packageName:H,description:Z.description,tools:K.length>0?K:void 0,mcpDirectTools:V.length>0?V:void 0,model:Z.model,fallbackModels:R&&R.length>0?R:void 0,thinking:Z.thinking,systemPromptMode:D,inheritProjectContext:x,inheritSkills:y,defaultContext:P,systemPrompt:X,source:J,filePath:U,skills:O&&O.length>0?O:void 0,extensions:h,subagentOnlyExtensions:r,output:Z.output,defaultReads:z&&z.length>0?z:void 0,defaultProgress:Z.defaultProgress==="true",interactive:Z.interactive==="true",maxSubagentDepth:Number.isInteger(u)&&u>=0?u:void 0,completionGuard:h$,toolBudget:t,memory:k0(Z.memory),extraFields:Object.keys(I).length>0?I:void 0};S$.set(k,new Set(Object.keys(Z))),B.push(k)}return B}function l$($,J){let B=new Map,U=[];for(let Q of e$($,(Z)=>Z.endsWith(".chain.md")||Z.endsWith(".chain.json"))){let Z;try{Z=N.readFileSync(Q,"utf-8")}catch{continue}try{let X=Q.endsWith(".chain.json")?L0(Z,J,Q):E0(Z,J,Q),W=B.get(X.name);if(W&&W.filePath.endsWith(".chain.json")&&Q.endsWith(".chain.md"))continue;B.set(X.name,X)}catch(X){U.push({source:J,filePath:Q,error:X instanceof Error?X.message:String(X)});continue}}return{chains:Array.from(B.values()),diagnostics:U}}function z$($){try{return N.statSync($).isDirectory()}catch{return!1}}function C1($){let J=V$($);if(!J)return{readDirs:[],preferredDir:null};let B=j.join(J,".agents"),U=j.join(w(J),"agents"),Q=[];if(z$(B))Q.push(B);if(z$(U))Q.push(U);return{readDirs:Q,preferredDir:U}}function j1($){let J=V$($);if(!J)return{readDirs:[],preferredDir:null};let B=j.join(w(J),"chains");return{readDirs:z$(B)?[B]:[],preferredDir:B}}var R1=j.resolve(j.dirname(J1(import.meta.url)),"..","..","agents"),O1="DM_SUBAGENT_EXTRA_AGENT_DIRS";function F1(){let $=process.env[O1];if(!$)return[];return $.split(j.delimiter).map((J)=>J.trim()).filter((J)=>J.length>0)}function S($){let J=j.join(l(),"agents"),B=j.join(M$.homedir(),".agents"),U=B1(),{readDirs:Q,preferredDir:Z}=C1($),{readDirs:X,preferredDir:W}=j1($),G=D$(),H=y$($),Y=h0(G),q=h0(H),V=z1(Y,q,G,H),K=q1($),z=A1(E$(X$(R1,"builtin"),V),Y,q,G,H),C=o$(E$([...F1().flatMap((k)=>X$(k,"user")),...X$(J,"user"),...X$(B,"user")],V),Y,q,G,H),O=new Map;for(let k of K.agents)for(let F of X$(k,"package"))if(!O.has(F.name))O.set(F.name,F);let R=o$(E$(Array.from(O.values()),V),Y,q,G,H),D=new Map;for(let k of Q)for(let F of X$(k,"project"))D.set(F.name,F);let x=o$(E$(Array.from(D.values()),V),Y,q,G,H),y=new Map,P=[],h=new Map;for(let k of K.chains){let F=l$(k,"package");P.push(...F.diagnostics);for(let c of F.chains)if(!h.has(c.name))h.set(c.name,c)}let r=[];for(let k of X){let F=l$(k,"project");r.push(...F.diagnostics);for(let c of F.chains)y.set(c.name,c)}let I=l$(U,"user"),u=[...Array.from(h.values()),...I.chains,...Array.from(y.values())],t=[...P,...I.diagnostics,...r],h$=process.env.DM_CODING_AGENT_DIR?J:N.existsSync(B)?B:J;return{builtin:z,package:R,user:C,project:x,chains:u,chainDiagnostics:t,userDir:h$,projectDir:Z,userChainDir:U,projectChainDir:W,userSettingsPath:G,projectSettingsPath:H}}var I1=["reviewer","context-builder","delegate"];function p0($){if(typeof $!=="number")return;if(!Number.isInteger($)||!Number.isFinite($)||$<1)return;return $}function o0($){if($===!1)return{enabled:!1,minReferences:2,maxRecommendations:3,preferredAgent:"reviewer"};let J=p0($?.maxRecommendations)??3;return{enabled:$?.enabled??!0,minReferences:p0($?.minReferences)??2,maxRecommendations:Math.min(J,5),preferredAgent:typeof $?.preferredAgent==="string"&&$.preferredAgent.trim()?$.preferredAgent.trim():"reviewer"}}function N1($){if($===!1||$===!0||$===void 0||$===null)return[];if(Array.isArray($))return[...new Set($.filter((J)=>typeof J==="string").map((J)=>J.trim()).filter(Boolean))];if(typeof $==="string")return[...new Set($.split(",").map((J)=>J.trim()).filter(Boolean))];return[]}function $0($,J){for(let U of N1($.skills??$.skill))J.add(U);let B=$.parallel;if(!B)return;if(Array.isArray(B)){for(let U of B)if(U&&typeof U==="object"&&!Array.isArray(U))$0(U,J);return}if(typeof B==="object")$0(B,J)}function E1($,J){let B=$.filter((U)=>!U.disabled);if(B.some((U)=>U.name===J))return J;for(let U of I1)if(B.some((Q)=>Q.name===U))return U;return B[0]?.name}function c0($,J,B){if(J==="dm-subagents")return;let U=$.get(J)??new Set;U.add(B),$.set(J,U)}function L1($){let J=o0($.config);if(!J.enabled)return[];let B=E1($.agents,J.preferredAgent);if(!B)return[];let U=$.availableSkills?new Map($.availableSkills.map((Z)=>[Z.name,Z])):void 0,Q=new Map;for(let Z of $.agents){if(Z.disabled)continue;for(let X of Z.skills??[])c0(Q,X,`agent:${Z.name}`)}for(let Z of $.chains??[]){let X=new Set;for(let W of Z.steps)$0(W,X);for(let W of X)c0(Q,W,`chain:${Z.name}`)}return[...Q.entries()].filter(([Z,X])=>X.size>=J.minReferences&&(!U||U.has(Z))).map(([Z,X])=>({skill:Z,agent:B,references:X.size,sources:[...X].sort((W,G)=>W.localeCompare(G)),description:U?.get(Z)?.description,reason:`referenced by ${X.size} configured agents/chains`})).sort((Z,X)=>X.references-Z.references||Z.skill.localeCompare(X.skill)).slice(0,J.maxRecommendations)}function M1($){if($.length===0)return[];return["Proactive skill subagent suggestions:",...$.map((J)=>{let B=J.sources.slice(0,3).join(", "),U=J.sources.length>3?`, +${J.sources.length-3} more`:"",Q=J.description?` - ${J.description}`:"";return`- ${J.skill} via ${J.agent} (${J.reason}; ${B}${U})${Q}`}),"Guardrails: use these for broad tasks where a skill-specialist pass is useful; keep fanout small, use fresh context unless private/session context is explicitly needed, and skip when the user asks for a direct answer."]}function l0($){if(!o0($.config).enabled)return[];let J;try{J=$.discoverAvailableSkills()}catch{J=[]}return M1(L1({agents:$.agents,chains:$.chains,availableSkills:J,config:$.config}))}function S1($){let J=$.lastIndexOf(":");if(J===-1)return{baseModel:$,thinkingSuffix:""};return{baseModel:$.substring(0,J),thinkingSuffix:$.substring(J)}}var w1="inherit";function i($){return $.toLowerCase().replace(/[._]+/g,"-").replace(/-+/g,"-").replace(/^-|-$/g,"")}function n0($,J,B){let U=Number($),Q=Number(J),Z=Number(B);return U>=1900&&U<=2099&&Q>=1&&Q<=12&&Z>=1&&Z<=31}function i0($){let J=/^(.*)-(\d{4})-(\d{2})-(\d{2})$/.exec($);if(J&&n0(J[2],J[3],J[4]))return J[1];let B=/^(.*)-(\d{4})(\d{2})(\d{2})$/.exec($);if(B&&n0(B[2],B[3],B[4]))return B[1];return $}function s0($,J,B){if($.includes("/")){let U=J.find((Q)=>Q.fullId===$);if(U)return U.fullId}else{let U=J.filter((Q)=>Q.id===$);if(B){let Q=U.find((Z)=>Z.provider===B);if(Q)return Q.fullId}if(U.length===1)return U[0].fullId}return D1($,J,B)}function D1($,J,B){let U,Q=$,Z=$.indexOf("/");if(Z!==-1)U=i($.slice(0,Z)),Q=$.slice(Z+1);else{let H=[":","."];for(let Y of H){let q=$.indexOf(Y);if(q<=0)continue;let V=i($.slice(0,q));if(!J.some((K)=>i(K.provider)===V))continue;U=V,Q=$.slice(q+1);break}}let X=i(Q),W=i0(X),G=J.filter((H)=>{let Y=i(H.id);if(Y!==X&&i0(Y)!==W)return!1;if(U!==void 0&&i(H.provider)!==U)return!1;return!0});if(G.length===0)return;if(B){let H=i(B),Y=G.find((q)=>i(q.provider)===H);if(Y)return Y.fullId}if(G.length===1)return G[0].fullId;return}function y1($,J,B){if(!$)return;if(!J||J.length===0)return $;let U=s0($,J,B);if(U)return U;let{baseModel:Q,thinkingSuffix:Z}=S1($);if(!Z)return $;let X=s0(Q,J,B);if(X)return`${X}${Z}`;return $}function k1($){console.warn(`[dm-subagents] ${$.message}`)}function J0($,J,B,U,Q){let Z=typeof $==="string"?$.trim():"",X=Z&&Z!==w1?Z:void 0,W;if(X===void 0)W=J?`${J.provider}/${J.id}`:void 0;else W=y1(X,B,U);if(W&&Q?.scope?.enforce){let G=X===void 0?"inherited":Q.source??"inherited",H=w0(W,Q.scope,G);if(H){if(H.severity==="error")throw Error(H.message);(Q.onWarn??k1)(H)}}return W}function _($,J=!1){return{content:[{type:"text",text:$}],isError:J,details:{mode:"management",results:[]}}}function W$($){return[...new Set($.split(",").map((J)=>J.trim()).filter(Boolean))]}function e0($){let J=$;if(typeof J==="string")try{J=JSON.parse(J)}catch(B){return{error:`config must be valid JSON: ${B instanceof Error?B.message:String(B)}`}}if(!J||typeof J!=="object"||Array.isArray(J))return{};return{value:J}}function A($,J){return Object.prototype.hasOwnProperty.call($,J)}function _$($){if($==="user"||$==="project")return $;return}function P$($,J){if($===void 0)return{scope:"user"};let B=_$($);return B?{scope:B}:{error:_(`agentScope must be 'user' or 'project' for ${J}.`,!0)}}function b1($){if($===void 0)return"both";if($==="user"||$==="project"||$==="both")return $;return}function s($){return $.toLowerCase().trim().replace(/\s+/g,"-").replace(/[^a-z0-9-]/g,"").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function B0($){return n($,"config.package")}function A$($){return[...$.builtin,...$.package,...$.user,...$.project]}function a($,J){let B=S($),U=J==="agent"?A$(B):B.chains;return[...new Set(U.map((Q)=>Q.name))].sort((Q,Z)=>Q.localeCompare(Z))}function U0($,J,B="both"){let U=S(J),Q=$.trim(),Z=s(Q);return A$(U).filter((X)=>(B==="both"||X.source===B)&&(X.name===Q||X.name===Z)).sort((X,W)=>X.source.localeCompare(W.source))}function Q0($,J,B="both"){let U=$.trim(),Q=s(U);return S(J).chains.filter((Z)=>(B==="both"||Z.source===B)&&(Z.name===U||Z.name===Q)).sort((Z,X)=>Z.source.localeCompare(X.source))}var r0={builtin:0,package:1,user:2,project:3};function b$($,J){let B=J.trim(),U=s(B),Q=A$($).filter((Z)=>Z.name===B||Z.name===U);if(Q.length===0)return;return Q.reduce((Z,X)=>r0[X.source]>r0[Z.source]?X:Z)}function Z0($,J,B,U){let Q=S($);for(let Z of J==="user"?Q.user:Q.project)if(Z.name===B&&Z.filePath!==U)return!0;for(let Z of Q.chains)if(Z.source===J&&Z.name===B&&Z.filePath!==U)return!0;return!1}function x1($){return $==="user"||$==="project"}function $J($,J){let B=S($),U=new Set(A$(B).map((Q)=>Q.name));return[...new Set(J.map((Q)=>Q.agent).filter((Q)=>!U.has(Q)))].sort((Q,Z)=>Q.localeCompare(Z))}function JJ($,J){let B=[],U=new Set(C$($.cwd).map((Q)=>Q.name));for(let Q=0;Q<J.length;Q++){let Z=J[Q];if(Z.model){if(!$.modelRegistry.getAvailable().some((W)=>`${W.provider}/${W.id}`===Z.model||W.id===Z.model))B.push(`Warning: step ${Q+1} (${Z.agent}): model '${Z.model}' is not in the current model registry.`)}if(Array.isArray(Z.skills)&&Z.skills.length>0){let X=Z.skills.filter((W)=>!U.has(W));if(X.length)B.push(`Warning: step ${Q+1} (${Z.agent}): skills not found: ${X.join(", ")}.`)}}return B}function BJ($,J){if(!J)return;return $.modelRegistry.getAvailable().some((U)=>`${U.provider}/${U.id}`===J||U.id===J)?void 0:`Warning: model '${J}' is not in the current model registry.`}function UJ($,J){if(!J||J.length===0)return;let B=new Set($.modelRegistry.getAvailable().flatMap((Q)=>[`${Q.provider}/${Q.id}`,Q.id])),U=J.filter((Q)=>!B.has(Q));return U.length?`Warning: fallback models not in the current model registry: ${U.join(", ")}.`:void 0}function QJ($,J){if(!J||J.length===0)return;let B=new Set(C$($).map((Q)=>Q.name)),U=J.filter((Q)=>!B.has(Q));return U.length?`Warning: skills not found: ${U.join(", ")}.`:void 0}function P1($){let J=$.override?.base;if(!J)return{...$};return{...$,model:J.model,fallbackModels:J.fallbackModels?[...J.fallbackModels]:void 0,thinking:J.thinking,systemPromptMode:J.systemPromptMode,inheritProjectContext:J.inheritProjectContext,inheritSkills:J.inheritSkills,defaultContext:J.defaultContext,disabled:J.disabled,systemPrompt:J.systemPrompt,skills:J.skills?[...J.skills]:void 0,tools:J.tools?[...J.tools]:void 0,mcpDirectTools:J.mcpDirectTools?[...J.mcpDirectTools]:void 0,subagentOnlyExtensions:J.subagentOnlyExtensions?[...J.subagentOnlyExtensions]:void 0,completionGuard:J.completionGuard,override:void 0}}function h1($){try{let{frontmatter:J}=Q$(E.readFileSync($,"utf-8"));return new Set(Object.keys(J))}catch{return new Set}}function f1($,J){let B=h1($.filePath),U=(...Q)=>{for(let Z of Q)B.delete(Z)};if(A(J,"name"))U("name");if(A(J,"package"))U("package");if(A(J,"description"))U("description");if(A(J,"systemPrompt"))U("systemPrompt");if(A(J,"model"))U("model");if(A(J,"fallbackModels"))U("fallbackModels");if(A(J,"tools"))U("tools");if(A(J,"skills"))U("skill","skills");if(A(J,"extensions"))U("extensions");if(A(J,"subagentOnlyExtensions"))U("subagentOnlyExtensions");if(A(J,"thinking")){if(U("thinking"),J.thinking==="off")B.add("thinking")}if(A(J,"systemPromptMode"))U("systemPromptMode"),B.add("systemPromptMode");if(A(J,"inheritProjectContext"))U("inheritProjectContext"),B.add("inheritProjectContext");if(A(J,"inheritSkills"))U("inheritSkills"),B.add("inheritSkills");if(A(J,"defaultContext"))U("defaultContext");if(A(J,"output"))U("output");if(A(J,"reads"))U("defaultReads");if(A(J,"progress"))U("defaultProgress");if(A(J,"maxSubagentDepth"))U("maxSubagentDepth");if(A(J,"completionGuard")){if(U("completionGuard"),J.completionGuard===!0)B.add("completionGuard")}if(A(J,"toolBudget"))U("toolBudget");return B}function ZJ($){if(!Array.isArray($))return{error:"config.steps must be an array."};if($.length===0)return{error:"config.steps must include at least one step."};let J=[];for(let B=0;B<$.length;B++){let U=$[B];if(!U||typeof U!=="object"||Array.isArray(U))return{error:`config.steps[${B}] must be an object.`};let Q=U;if(typeof Q.agent!=="string"||!Q.agent.trim())return{error:`config.steps[${B}].agent must be a non-empty string.`};let Z={agent:Q.agent.trim(),task:typeof Q.task==="string"?Q.task:""};if(A(Q,"phase"))if(typeof Q.phase==="string")Z.phase=Q.phase;else return{error:`config.steps[${B}].phase must be a string.`};if(A(Q,"label"))if(typeof Q.label==="string")Z.label=Q.label;else return{error:`config.steps[${B}].label must be a string.`};if(A(Q,"as"))if(typeof Q.as==="string")Z.as=Q.as;else return{error:`config.steps[${B}].as must be a string.`};if(A(Q,"outputSchema"))if(typeof Q.outputSchema==="string")Z.outputSchema=Q.outputSchema;else return{error:`config.steps[${B}].outputSchema must be a schema file path string for saved chains.`};if(A(Q,"output"))if(Q.output===!1)Z.output=!1;else if(typeof Q.output==="string")Z.output=Q.output;else return{error:`config.steps[${B}].output must be a string or false.`};if(A(Q,"outputMode"))if(Q.outputMode==="inline"||Q.outputMode==="file-only")Z.outputMode=Q.outputMode;else return{error:`config.steps[${B}].outputMode must be 'inline' or 'file-only'.`};if(A(Q,"reads"))if(Q.reads===!1)Z.reads=!1;else if(Array.isArray(Q.reads))Z.reads=Q.reads.filter((X)=>typeof X==="string").map((X)=>X.trim()).filter(Boolean);else return{error:`config.steps[${B}].reads must be an array or false.`};if(A(Q,"model"))if(typeof Q.model==="string")Z.model=Q.model;else return{error:`config.steps[${B}].model must be a string.`};if(A(Q,"skills"))if(Q.skills===!1)Z.skills=!1;else if(Array.isArray(Q.skills))Z.skills=Q.skills.filter((X)=>typeof X==="string").map((X)=>X.trim()).filter(Boolean);else return{error:`config.steps[${B}].skills must be an array or false.`};if(A(Q,"progress"))if(typeof Q.progress==="boolean")Z.progress=Q.progress;else return{error:`config.steps[${B}].progress must be a boolean.`};if(A(Q,"toolBudget")){let X=Z$(Q.toolBudget,`config.steps[${B}].toolBudget`);if(X.error)return{error:X.error};Z.toolBudget=Q.toolBudget}J.push(Z)}return{steps:J}}function v1($){let J=[],B=[];for(let U of W$($))if(U.startsWith("mcp:")){let Q=U.slice(4).trim();if(Q)B.push(Q)}else J.push(U);return{tools:J.length?J:void 0,mcpDirectTools:B.length?B:void 0}}function XJ($,J){if(A(J,"systemPrompt"))if(J.systemPrompt===!1||J.systemPrompt==="")$.systemPrompt="";else if(typeof J.systemPrompt==="string")$.systemPrompt=J.systemPrompt;else return"config.systemPrompt must be a string or false when provided.";if(A(J,"model"))if(J.model===!1||J.model==="")$.model=void 0;else if(typeof J.model==="string")$.model=J.model.trim()||void 0;else return"config.model must be a string or false when provided.";if(A(J,"fallbackModels"))if(J.fallbackModels===!1||J.fallbackModels==="")$.fallbackModels=void 0;else if(typeof J.fallbackModels==="string"){let B=W$(J.fallbackModels);$.fallbackModels=B.length?B:void 0}else if(Array.isArray(J.fallbackModels)){let B=J.fallbackModels.filter((U)=>typeof U==="string").map((U)=>U.trim()).filter(Boolean);$.fallbackModels=B.length?[...new Set(B)]:void 0}else return"config.fallbackModels must be a comma-separated string, string array, or false when provided.";if(A(J,"tools"))if(J.tools===!1||J.tools==="")$.tools=void 0,$.mcpDirectTools=void 0;else if(typeof J.tools==="string"){let B=v1(J.tools);$.tools=B.tools,$.mcpDirectTools=B.mcpDirectTools}else return"config.tools must be a comma-separated string or false when provided.";if(A(J,"skills"))if(J.skills===!1||J.skills==="")$.skills=void 0;else if(typeof J.skills==="string"){let B=W$(J.skills);$.skills=B.length?B:void 0}else return"config.skills must be a comma-separated string or false when provided.";if(A(J,"extensions"))if(J.extensions===!1)$.extensions=void 0;else if(J.extensions==="")$.extensions=[];else if(typeof J.extensions==="string")$.extensions=W$(J.extensions);else return"config.extensions must be a comma-separated string, empty string, or false when provided.";if(A(J,"subagentOnlyExtensions"))if(J.subagentOnlyExtensions===!1)$.subagentOnlyExtensions=void 0;else if(J.subagentOnlyExtensions==="")$.subagentOnlyExtensions=[];else if(typeof J.subagentOnlyExtensions==="string")$.subagentOnlyExtensions=W$(J.subagentOnlyExtensions);else return"config.subagentOnlyExtensions must be a comma-separated string, empty string, or false when provided.";if(A(J,"thinking"))if(J.thinking===!1||J.thinking==="")$.thinking=void 0;else if(typeof J.thinking==="string")$.thinking=J.thinking.trim()||void 0;else return"config.thinking must be a string or false when provided.";if(A(J,"systemPromptMode"))if(J.systemPromptMode==="append"||J.systemPromptMode==="replace")$.systemPromptMode=J.systemPromptMode;else return"config.systemPromptMode must be 'append' or 'replace' when provided.";if(A(J,"inheritProjectContext")){if(typeof J.inheritProjectContext!=="boolean")return"config.inheritProjectContext must be a boolean when provided.";$.inheritProjectContext=J.inheritProjectContext}if(A(J,"inheritSkills")){if(typeof J.inheritSkills!=="boolean")return"config.inheritSkills must be a boolean when provided.";$.inheritSkills=J.inheritSkills}if(A(J,"defaultContext"))if(J.defaultContext===!1||J.defaultContext==="")$.defaultContext=void 0;else if(J.defaultContext==="fresh"||J.defaultContext==="fork")$.defaultContext=J.defaultContext;else return"config.defaultContext must be 'fresh', 'fork', or false when provided.";if(A(J,"output"))if(J.output===!1||J.output==="")$.output=void 0;else if(typeof J.output==="string")$.output=J.output;else return"config.output must be a string or false when provided.";if(A(J,"reads"))if(J.reads===!1||J.reads==="")$.defaultReads=void 0;else if(typeof J.reads==="string"){let B=W$(J.reads);$.defaultReads=B.length?B:void 0}else return"config.reads must be a comma-separated string or false when provided.";if(A(J,"progress")){if(typeof J.progress!=="boolean")return"config.progress must be a boolean when provided.";$.defaultProgress=J.progress}if(A(J,"maxSubagentDepth"))if(J.maxSubagentDepth===!1||J.maxSubagentDepth==="")$.maxSubagentDepth=void 0;else if(typeof J.maxSubagentDepth==="number"&&Number.isInteger(J.maxSubagentDepth)&&J.maxSubagentDepth>=0)$.maxSubagentDepth=J.maxSubagentDepth;else return"config.maxSubagentDepth must be an integer >= 0 or false when provided.";if(A(J,"completionGuard")){if(typeof J.completionGuard!=="boolean")return"config.completionGuard must be a boolean when provided.";$.completionGuard=J.completionGuard}if(A(J,"toolBudget"))if(J.toolBudget===!1||J.toolBudget==="")$.toolBudget=void 0;else{let B=Z$(J.toolBudget,"config.toolBudget");if(B.error)return B.error;$.toolBudget=J.toolBudget}return}function x$($,J,B,U,Q){let Z=B.filter((G)=>x1(G.source));if(Z.length===0){if(B.length>0)return _(`${$==="agent"?"Agent":"Chain"} '${J}' is read-only and cannot be modified. Create a same-named ${$} in user or project scope to override it.`,!0);let G=a(U,$);return _(`${$==="agent"?"Agent":"Chain"} '${J}' not found. Available: ${G.join(", ")||"none"}.`,!0)}if(Z.length===1)return Z[0];let X=_$(Q);if(!X){let G=Z.map((H)=>`${H.source}: ${H.filePath}`).join(`
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
797
|
+
`), !anyFound);
|
|
798
|
+
}
|
|
799
|
+
export function handleCreate(params, ctx) {
|
|
800
|
+
const parsedConfig = configObject(params.config);
|
|
801
|
+
if (parsedConfig.error)
|
|
802
|
+
return result(parsedConfig.error, true);
|
|
803
|
+
const cfg = parsedConfig.value;
|
|
804
|
+
if (!cfg)
|
|
805
|
+
return result("config required for create.", true);
|
|
806
|
+
if (typeof cfg.name !== "string" || !cfg.name.trim())
|
|
807
|
+
return result("config.name is required and must be a non-empty string.", true);
|
|
808
|
+
if (typeof cfg.description !== "string" || !cfg.description.trim())
|
|
809
|
+
return result("config.description is required and must be a non-empty string.", true);
|
|
810
|
+
const name = sanitizeName(cfg.name);
|
|
811
|
+
if (!name)
|
|
812
|
+
return result("config.name is invalid after sanitization. Use letters, numbers, spaces, or hyphens.", true);
|
|
813
|
+
const parsedPackage = parsePackageConfig(cfg.package);
|
|
814
|
+
if (parsedPackage.error)
|
|
815
|
+
return result(parsedPackage.error, true);
|
|
816
|
+
const runtimeName = buildRuntimeName(name, parsedPackage.packageName);
|
|
817
|
+
const scopeRaw = cfg.scope ?? "user";
|
|
818
|
+
if (scopeRaw !== "user" && scopeRaw !== "project")
|
|
819
|
+
return result("config.scope must be 'user' or 'project'.", true);
|
|
820
|
+
const scope = scopeRaw;
|
|
821
|
+
const isChain = hasKey(cfg, "steps");
|
|
822
|
+
const d = discoverAgentsAll(ctx.cwd);
|
|
823
|
+
const projectConfigDir = getProjectConfigDir(ctx.cwd);
|
|
824
|
+
const targetDir = isChain ? scope === "user" ? d.userChainDir : d.projectChainDir ?? path.join(projectConfigDir, "chains") : scope === "user" ? d.userDir : d.projectDir ?? path.join(projectConfigDir, "agents");
|
|
825
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
826
|
+
if (nameExistsInScope(ctx.cwd, scope, runtimeName))
|
|
827
|
+
return result(`Name '${runtimeName}' already exists in ${scope} scope. Use update instead.`, true);
|
|
828
|
+
const targetPath = path.join(targetDir, isChain ? `${runtimeName}.chain.md` : `${runtimeName}.md`);
|
|
829
|
+
if (fs.existsSync(targetPath))
|
|
830
|
+
return result(`File already exists at ${targetPath} but is not a valid ${isChain ? "chain" : "agent"} definition. Remove or rename it first.`, true);
|
|
831
|
+
const warnings = [];
|
|
832
|
+
if (!isChain && d.builtin.some((a) => a.name === runtimeName))
|
|
833
|
+
warnings.push(`Note: this shadows the builtin agent '${runtimeName}'.`);
|
|
834
|
+
if (isChain) {
|
|
835
|
+
const parsed = parseStepList(cfg.steps);
|
|
836
|
+
if (parsed.error)
|
|
837
|
+
return result(parsed.error, true);
|
|
838
|
+
const chain = { name: runtimeName, localName: name, packageName: parsedPackage.packageName, description: cfg.description.trim(), source: scope, filePath: targetPath, steps: parsed.steps };
|
|
839
|
+
fs.writeFileSync(targetPath, serializeChain(chain), "utf-8");
|
|
840
|
+
const missing = unknownChainAgents(ctx.cwd, chain.steps);
|
|
841
|
+
if (missing.length)
|
|
842
|
+
warnings.push(`Warning: chain steps reference unknown agents: ${missing.join(", ")}.`);
|
|
843
|
+
warnings.push(...chainStepWarnings(ctx, chain.steps));
|
|
844
|
+
return result([`Created chain '${runtimeName}' at ${targetPath}.`, ...warnings].join(`
|
|
845
|
+
`));
|
|
846
|
+
}
|
|
847
|
+
const agent = {
|
|
848
|
+
name: runtimeName,
|
|
849
|
+
localName: name,
|
|
850
|
+
packageName: parsedPackage.packageName,
|
|
851
|
+
description: cfg.description.trim(),
|
|
852
|
+
source: scope,
|
|
853
|
+
filePath: targetPath,
|
|
854
|
+
systemPrompt: "",
|
|
855
|
+
systemPromptMode: defaultSystemPromptMode(name),
|
|
856
|
+
inheritProjectContext: defaultInheritProjectContext(name),
|
|
857
|
+
inheritSkills: defaultInheritSkills()
|
|
858
|
+
};
|
|
859
|
+
const applyError = applyAgentConfig(agent, cfg);
|
|
860
|
+
if (applyError)
|
|
861
|
+
return result(applyError, true);
|
|
862
|
+
const mw = modelWarning(ctx, agent.model);
|
|
863
|
+
if (mw)
|
|
864
|
+
warnings.push(mw);
|
|
865
|
+
const fmw = fallbackModelsWarning(ctx, agent.fallbackModels);
|
|
866
|
+
if (fmw)
|
|
867
|
+
warnings.push(fmw);
|
|
868
|
+
const sw = skillsWarning(ctx.cwd, agent.skills);
|
|
869
|
+
if (sw)
|
|
870
|
+
warnings.push(sw);
|
|
871
|
+
fs.writeFileSync(targetPath, serializeAgent(agent), "utf-8");
|
|
872
|
+
return result([`Created agent '${runtimeName}' at ${targetPath}.`, ...warnings].join(`
|
|
873
|
+
`));
|
|
874
|
+
}
|
|
875
|
+
export function handleUpdate(params, ctx) {
|
|
876
|
+
if (!params.agent && !params.chainName)
|
|
877
|
+
return result("Specify 'agent' or 'chainName' for update.", true);
|
|
878
|
+
if (params.agent && params.chainName)
|
|
879
|
+
return result("Specify either 'agent' or 'chainName', not both.", true);
|
|
880
|
+
const parsedConfig = configObject(params.config);
|
|
881
|
+
if (parsedConfig.error)
|
|
882
|
+
return result(parsedConfig.error, true);
|
|
883
|
+
const cfg = parsedConfig.value;
|
|
884
|
+
if (!cfg)
|
|
885
|
+
return result("config required for update.", true);
|
|
886
|
+
const warnings = [];
|
|
887
|
+
if (params.agent) {
|
|
888
|
+
const scopeHint = asDisambiguationScope(params.agentScope);
|
|
889
|
+
const targetOrError = resolveTarget("agent", params.agent, findAgents(params.agent, ctx.cwd, scopeHint ?? "both"), ctx.cwd, params.agentScope);
|
|
890
|
+
if ("content" in targetOrError)
|
|
891
|
+
return targetOrError;
|
|
892
|
+
const target = targetOrError;
|
|
893
|
+
const updated = editableAgentConfig(target);
|
|
894
|
+
const oldName = target.name;
|
|
895
|
+
if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim()))
|
|
896
|
+
return result("config.name must be a non-empty string when provided.", true);
|
|
897
|
+
if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim()))
|
|
898
|
+
return result("config.description must be a non-empty string when provided.", true);
|
|
899
|
+
let newLocalName = target.localName ?? frontmatterNameForConfig(target);
|
|
900
|
+
if (hasKey(cfg, "name")) {
|
|
901
|
+
newLocalName = sanitizeName(cfg.name);
|
|
902
|
+
if (!newLocalName)
|
|
903
|
+
return result("config.name is invalid after sanitization.", true);
|
|
904
|
+
}
|
|
905
|
+
let newPackageName = target.packageName;
|
|
906
|
+
if (hasKey(cfg, "package")) {
|
|
907
|
+
const parsedPackage = parsePackageConfig(cfg.package);
|
|
908
|
+
if (parsedPackage.error)
|
|
909
|
+
return result(parsedPackage.error, true);
|
|
910
|
+
newPackageName = parsedPackage.packageName;
|
|
911
|
+
}
|
|
912
|
+
const applyError = applyAgentConfig(updated, cfg);
|
|
913
|
+
if (applyError)
|
|
914
|
+
return result(applyError, true);
|
|
915
|
+
const preserveFrontmatterFields = preservedAgentFrontmatterFields(target, cfg);
|
|
916
|
+
updated.localName = newLocalName;
|
|
917
|
+
updated.packageName = newPackageName;
|
|
918
|
+
updated.name = buildRuntimeName(newLocalName, newPackageName);
|
|
919
|
+
if (hasKey(cfg, "description"))
|
|
920
|
+
updated.description = cfg.description.trim();
|
|
921
|
+
if (hasKey(cfg, "model")) {
|
|
922
|
+
const mw = modelWarning(ctx, updated.model);
|
|
923
|
+
if (mw)
|
|
924
|
+
warnings.push(mw);
|
|
925
|
+
}
|
|
926
|
+
if (hasKey(cfg, "fallbackModels")) {
|
|
927
|
+
const fmw = fallbackModelsWarning(ctx, updated.fallbackModels);
|
|
928
|
+
if (fmw)
|
|
929
|
+
warnings.push(fmw);
|
|
930
|
+
}
|
|
931
|
+
if (hasKey(cfg, "skills")) {
|
|
932
|
+
const sw = skillsWarning(ctx.cwd, updated.skills);
|
|
933
|
+
if (sw)
|
|
934
|
+
warnings.push(sw);
|
|
935
|
+
}
|
|
936
|
+
if (updated.name !== oldName) {
|
|
937
|
+
const renamed = renamePath("agent", target.filePath, updated.name, target.source, ctx.cwd);
|
|
938
|
+
if (renamed.error)
|
|
939
|
+
return result(renamed.error, true);
|
|
940
|
+
updated.filePath = renamed.filePath;
|
|
941
|
+
}
|
|
942
|
+
fs.writeFileSync(updated.filePath, serializeAgent(updated, { preserveFrontmatterFields }), "utf-8");
|
|
943
|
+
if (updated.name !== oldName) {
|
|
944
|
+
const refs = discoverAgentsAll(ctx.cwd).chains.filter((c) => c.steps.some((s) => s.agent === oldName)).map((c) => `${c.name} (${c.source})`);
|
|
945
|
+
if (refs.length)
|
|
946
|
+
warnings.push(`Warning: chains still reference '${oldName}': ${refs.join(", ")}.`);
|
|
947
|
+
}
|
|
948
|
+
const headline = updated.name === oldName ? `Updated agent '${updated.name}' at ${updated.filePath}.` : `Updated agent '${oldName}' to '${updated.name}' at ${updated.filePath}.`;
|
|
949
|
+
return result([headline, ...warnings].join(`
|
|
950
|
+
`));
|
|
951
|
+
}
|
|
952
|
+
const scopeHint = asDisambiguationScope(params.agentScope);
|
|
953
|
+
const targetOrError = resolveTarget("chain", params.chainName, findChains(params.chainName, ctx.cwd, scopeHint ?? "both"), ctx.cwd, params.agentScope);
|
|
954
|
+
if ("content" in targetOrError)
|
|
955
|
+
return targetOrError;
|
|
956
|
+
const target = targetOrError;
|
|
957
|
+
const updated = { ...target, steps: [...target.steps] };
|
|
958
|
+
const oldName = target.name;
|
|
959
|
+
if (hasKey(cfg, "name") && (typeof cfg.name !== "string" || !cfg.name.trim()))
|
|
960
|
+
return result("config.name must be a non-empty string when provided.", true);
|
|
961
|
+
if (hasKey(cfg, "description") && (typeof cfg.description !== "string" || !cfg.description.trim()))
|
|
962
|
+
return result("config.description must be a non-empty string when provided.", true);
|
|
963
|
+
let newLocalName = target.localName ?? frontmatterNameForConfig(target);
|
|
964
|
+
if (hasKey(cfg, "name")) {
|
|
965
|
+
newLocalName = sanitizeName(cfg.name);
|
|
966
|
+
if (!newLocalName)
|
|
967
|
+
return result("config.name is invalid after sanitization.", true);
|
|
968
|
+
}
|
|
969
|
+
let newPackageName = target.packageName;
|
|
970
|
+
if (hasKey(cfg, "package")) {
|
|
971
|
+
const parsedPackage = parsePackageConfig(cfg.package);
|
|
972
|
+
if (parsedPackage.error)
|
|
973
|
+
return result(parsedPackage.error, true);
|
|
974
|
+
newPackageName = parsedPackage.packageName;
|
|
975
|
+
}
|
|
976
|
+
let parsedSteps;
|
|
977
|
+
if (hasKey(cfg, "steps")) {
|
|
978
|
+
const parsed = parseStepList(cfg.steps);
|
|
979
|
+
if (parsed.error)
|
|
980
|
+
return result(parsed.error, true);
|
|
981
|
+
parsedSteps = parsed.steps;
|
|
982
|
+
}
|
|
983
|
+
updated.localName = newLocalName;
|
|
984
|
+
updated.packageName = newPackageName;
|
|
985
|
+
updated.name = buildRuntimeName(newLocalName, newPackageName);
|
|
986
|
+
if (hasKey(cfg, "description"))
|
|
987
|
+
updated.description = cfg.description.trim();
|
|
988
|
+
if (parsedSteps) {
|
|
989
|
+
updated.steps = parsedSteps;
|
|
990
|
+
const missing = unknownChainAgents(ctx.cwd, updated.steps);
|
|
991
|
+
if (missing.length)
|
|
992
|
+
warnings.push(`Warning: chain steps reference unknown agents: ${missing.join(", ")}.`);
|
|
993
|
+
warnings.push(...chainStepWarnings(ctx, updated.steps));
|
|
994
|
+
}
|
|
995
|
+
if (updated.name !== oldName) {
|
|
996
|
+
const renamed = renamePath("chain", target.filePath, updated.name, target.source, ctx.cwd);
|
|
997
|
+
if (renamed.error)
|
|
998
|
+
return result(renamed.error, true);
|
|
999
|
+
updated.filePath = renamed.filePath;
|
|
1000
|
+
}
|
|
1001
|
+
fs.writeFileSync(updated.filePath, updated.filePath.endsWith(".chain.json") ? serializeJsonChain(updated) : serializeChain(updated), "utf-8");
|
|
1002
|
+
const headline = updated.name === oldName ? `Updated chain '${updated.name}' at ${updated.filePath}.` : `Updated chain '${oldName}' to '${updated.name}' at ${updated.filePath}.`;
|
|
1003
|
+
return result([headline, ...warnings].join(`
|
|
1004
|
+
`));
|
|
1005
|
+
}
|
|
1006
|
+
function handleDelete(params, ctx) {
|
|
1007
|
+
if (!params.agent && !params.chainName)
|
|
1008
|
+
return result("Specify 'agent' or 'chainName' for delete.", true);
|
|
1009
|
+
if (params.agent && params.chainName)
|
|
1010
|
+
return result("Specify either 'agent' or 'chainName', not both.", true);
|
|
1011
|
+
const scopeHint = asDisambiguationScope(params.agentScope);
|
|
1012
|
+
if (params.agent) {
|
|
1013
|
+
const targetOrError = resolveTarget("agent", params.agent, findAgents(params.agent, ctx.cwd, scopeHint ?? "both"), ctx.cwd, params.agentScope);
|
|
1014
|
+
if ("content" in targetOrError)
|
|
1015
|
+
return targetOrError;
|
|
1016
|
+
const target = targetOrError;
|
|
1017
|
+
fs.unlinkSync(target.filePath);
|
|
1018
|
+
const refs = discoverAgentsAll(ctx.cwd).chains.filter((c) => c.steps.some((s) => s.agent === target.name)).map((c) => `${c.name} (${c.source})`);
|
|
1019
|
+
const lines = [`Deleted agent '${target.name}' at ${target.filePath}.`];
|
|
1020
|
+
if (refs.length)
|
|
1021
|
+
lines.push(`Warning: chains reference deleted agent '${target.name}': ${refs.join(", ")}.`);
|
|
1022
|
+
return result(lines.join(`
|
|
1023
|
+
`));
|
|
1024
|
+
}
|
|
1025
|
+
const targetOrError = resolveTarget("chain", params.chainName, findChains(params.chainName, ctx.cwd, scopeHint ?? "both"), ctx.cwd, params.agentScope);
|
|
1026
|
+
if ("content" in targetOrError)
|
|
1027
|
+
return targetOrError;
|
|
1028
|
+
const target = targetOrError;
|
|
1029
|
+
fs.unlinkSync(target.filePath);
|
|
1030
|
+
return result(`Deleted chain '${target.name}' at ${target.filePath}.`);
|
|
1031
|
+
}
|
|
1032
|
+
function handleEject(params, ctx) {
|
|
1033
|
+
if (!params.agent)
|
|
1034
|
+
return result("Specify 'agent' for eject.", true);
|
|
1035
|
+
const raw = params.agent.trim();
|
|
1036
|
+
const sanitized = sanitizeName(raw);
|
|
1037
|
+
const parsedScope = actionScope(params.agentScope, "eject");
|
|
1038
|
+
if (parsedScope.error)
|
|
1039
|
+
return parsedScope.error;
|
|
1040
|
+
const scope = parsedScope.scope;
|
|
1041
|
+
const d = discoverAgentsAll(ctx.cwd);
|
|
1042
|
+
const source = [...d.package, ...d.builtin].find((a) => a.name === raw || a.name === sanitized);
|
|
1043
|
+
if (!source) {
|
|
1044
|
+
return result(`Agent '${raw}' not found or is not a bundled/package agent. eject copies a builtin or package agent to ${scope} scope so it can be customized. Available: ${availableNames(ctx.cwd, "agent").join(", ") || "none"}.`, true);
|
|
1045
|
+
}
|
|
1046
|
+
const runtimeName = source.name;
|
|
1047
|
+
const existingCustom = (scope === "user" ? d.user : d.project).find((a) => a.name === runtimeName);
|
|
1048
|
+
if (existingCustom) {
|
|
1049
|
+
return result(`Agent '${runtimeName}' is already a custom ${scope} agent at ${existingCustom.filePath}. Edit it with { action: "update", agent: "${runtimeName}" } or delete it first.`, true);
|
|
1050
|
+
}
|
|
1051
|
+
if (nameExistsInScope(ctx.cwd, scope, runtimeName)) {
|
|
1052
|
+
return result(`An agent or chain named '${runtimeName}' already exists in ${scope} scope. Remove or rename it first.`, true);
|
|
1053
|
+
}
|
|
1054
|
+
const projectConfigDir = getProjectConfigDir(ctx.cwd);
|
|
1055
|
+
const targetDir = scope === "user" ? d.userDir : d.projectDir ?? path.join(projectConfigDir, "agents");
|
|
1056
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
1057
|
+
const targetPath = path.join(targetDir, `${runtimeName}.md`);
|
|
1058
|
+
if (fs.existsSync(targetPath)) {
|
|
1059
|
+
return result(`File already exists at ${targetPath} but is not a valid agent definition. Remove or rename it first.`, true);
|
|
1060
|
+
}
|
|
1061
|
+
let content;
|
|
1062
|
+
try {
|
|
1063
|
+
content = fs.readFileSync(source.filePath, "utf-8");
|
|
1064
|
+
} catch (error) {
|
|
1065
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1066
|
+
return result(`Failed to read source agent at ${source.filePath}: ${message}`, true);
|
|
1067
|
+
}
|
|
1068
|
+
fs.writeFileSync(targetPath, content, "utf-8");
|
|
1069
|
+
return result(`Ejected agent '${runtimeName}' from ${source.source} to ${scope} scope at ${targetPath}. Edit it there to customize; it shadows the bundled ${source.source} agent of the same name.`);
|
|
1070
|
+
}
|
|
1071
|
+
function handleDisable(params, ctx) {
|
|
1072
|
+
if (!params.agent)
|
|
1073
|
+
return result("Specify 'agent' for disable.", true);
|
|
1074
|
+
const raw = params.agent.trim();
|
|
1075
|
+
const parsedScope = actionScope(params.agentScope, "disable");
|
|
1076
|
+
if (parsedScope.error)
|
|
1077
|
+
return parsedScope.error;
|
|
1078
|
+
const scope = parsedScope.scope;
|
|
1079
|
+
const d = discoverAgentsAll(ctx.cwd);
|
|
1080
|
+
if (scope === "project" && d.projectSettingsPath === null) {
|
|
1081
|
+
return result("Project override is not available here: no DM project config root was found above the cwd. Use agentScope: 'user' or run from inside a project.", true);
|
|
1082
|
+
}
|
|
1083
|
+
const effective = pickEffectiveAgent(d, raw);
|
|
1084
|
+
if (!effective) {
|
|
1085
|
+
return result(`Agent '${raw}' not found. Available: ${availableNames(ctx.cwd, "agent").join(", ") || "none"}.`, true);
|
|
1086
|
+
}
|
|
1087
|
+
const runtimeName = effective.name;
|
|
1088
|
+
const settingsPath = mergeBuiltinAgentOverride(ctx.cwd, runtimeName, scope, { disabled: true });
|
|
1089
|
+
const after = pickEffectiveAgent(discoverAgentsAll(ctx.cwd), raw);
|
|
1090
|
+
if (after?.disabled === true) {
|
|
1091
|
+
return result(`Disabled agent '${runtimeName}' via ${scope} settings override at ${settingsPath}. It is now hidden from runtime discovery and { action: "list" }.`);
|
|
1092
|
+
}
|
|
1093
|
+
return result(`Wrote a disabled override for '${runtimeName}' at ${settingsPath}, but the agent is still enabled. A higher-precedence ${after?.override?.scope ?? "project"} override is likely winning. Try agentScope: '${after?.override?.scope ?? "project"}'.`, true);
|
|
1094
|
+
}
|
|
1095
|
+
function handleEnable(params, ctx) {
|
|
1096
|
+
if (!params.agent)
|
|
1097
|
+
return result("Specify 'agent' for enable.", true);
|
|
1098
|
+
const raw = params.agent.trim();
|
|
1099
|
+
const parsedScope = actionScope(params.agentScope, "enable");
|
|
1100
|
+
if (parsedScope.error)
|
|
1101
|
+
return parsedScope.error;
|
|
1102
|
+
const scope = parsedScope.scope;
|
|
1103
|
+
const d = discoverAgentsAll(ctx.cwd);
|
|
1104
|
+
if (scope === "project" && d.projectSettingsPath === null) {
|
|
1105
|
+
return result("Project override is not available here: no DM project config root was found above the cwd. Use agentScope: 'user' or run from inside a project.", true);
|
|
1106
|
+
}
|
|
1107
|
+
const effective = pickEffectiveAgent(d, raw);
|
|
1108
|
+
if (!effective) {
|
|
1109
|
+
return result(`Agent '${raw}' not found. Available: ${availableNames(ctx.cwd, "agent").join(", ") || "none"}.`, true);
|
|
1110
|
+
}
|
|
1111
|
+
const runtimeName = effective.name;
|
|
1112
|
+
const { path: settingsPath, removed } = removeBuiltinAgentOverrideFields(ctx.cwd, runtimeName, scope, ["disabled"]);
|
|
1113
|
+
const after = pickEffectiveAgent(discoverAgentsAll(ctx.cwd), raw);
|
|
1114
|
+
if (after && after.disabled !== true) {
|
|
1115
|
+
if (removed)
|
|
1116
|
+
return result(`Enabled agent '${runtimeName}' (removed disabled override at ${settingsPath}).`);
|
|
1117
|
+
return result(`Agent '${runtimeName}' is already enabled.`);
|
|
1118
|
+
}
|
|
1119
|
+
if (after?.override?.scope && after.override.scope !== scope) {
|
|
1120
|
+
return result(`Agent '${runtimeName}' is still disabled via a ${after.override.scope} scope override at ${after.override.path}. Specify agentScope: '${after.override.scope}' to enable it.`, true);
|
|
1121
|
+
}
|
|
1122
|
+
return result(`Agent '${runtimeName}' is still disabled after removing the ${scope} disabled override. It may be hidden via subagents.disableBuiltins in ${after?.override?.scope ?? scope} settings at ${after?.override?.path ?? settingsPath}.`, true);
|
|
1123
|
+
}
|
|
1124
|
+
function handleReset(params, ctx) {
|
|
1125
|
+
if (!params.agent)
|
|
1126
|
+
return result("Specify 'agent' for reset.", true);
|
|
1127
|
+
const raw = params.agent.trim();
|
|
1128
|
+
const sanitized = sanitizeName(raw);
|
|
1129
|
+
const parsedScope = actionScope(params.agentScope, "reset");
|
|
1130
|
+
if (parsedScope.error)
|
|
1131
|
+
return parsedScope.error;
|
|
1132
|
+
const scope = parsedScope.scope;
|
|
1133
|
+
const d = discoverAgentsAll(ctx.cwd);
|
|
1134
|
+
if (scope === "project" && d.projectSettingsPath === null) {
|
|
1135
|
+
return result("Project override is not available here: no DM project config root was found above the cwd. Use agentScope: 'user' or run from inside a project.", true);
|
|
1136
|
+
}
|
|
1137
|
+
const bundled = [...d.package, ...d.builtin].find((a) => a.name === raw || a.name === sanitized);
|
|
1138
|
+
if (!bundled) {
|
|
1139
|
+
const custom = [...d.user, ...d.project].find((a) => a.name === raw || a.name === sanitized);
|
|
1140
|
+
if (custom) {
|
|
1141
|
+
return result(`Agent '${raw}' has no bundled default to reset to. Use { action: "delete", agent: "${custom.name}" } to remove the custom ${custom.source} agent.`, true);
|
|
1142
|
+
}
|
|
1143
|
+
return result(`Agent '${raw}' not found. Available: ${availableNames(ctx.cwd, "agent").join(", ") || "none"}.`, true);
|
|
1144
|
+
}
|
|
1145
|
+
const runtimeName = bundled.name;
|
|
1146
|
+
const custom = (scope === "user" ? d.user : d.project).find((a) => a.name === raw || a.name === sanitized);
|
|
1147
|
+
const lines = [];
|
|
1148
|
+
if (custom) {
|
|
1149
|
+
fs.unlinkSync(custom.filePath);
|
|
1150
|
+
lines.push(`Deleted custom ${scope} agent file at ${custom.filePath}.`);
|
|
1151
|
+
}
|
|
1152
|
+
const overrideRemoval = removeBuiltinAgentOverride(ctx.cwd, runtimeName, scope);
|
|
1153
|
+
if (overrideRemoval.removed)
|
|
1154
|
+
lines.push(`Removed ${scope} settings override at ${overrideRemoval.path}.`);
|
|
1155
|
+
if (lines.length === 0) {
|
|
1156
|
+
const otherScope = scope === "user" ? "project" : "user";
|
|
1157
|
+
const otherCustom = (otherScope === "user" ? d.user : d.project).find((a) => a.name === raw || a.name === sanitized);
|
|
1158
|
+
const hasOtherOverride = bundled.override?.scope === otherScope;
|
|
1159
|
+
const note = otherCustom || hasOtherOverride ? ` Customization exists in ${otherScope} scope; specify agentScope: '${otherScope}' to reset it.` : "";
|
|
1160
|
+
return result(`Agent '${runtimeName}' has no ${scope} customization to reset.${note} It is at its bundled ${bundled.source} default.`);
|
|
1161
|
+
}
|
|
1162
|
+
lines.push(`Reset agent '${runtimeName}' to its bundled ${bundled.source} default.`);
|
|
1163
|
+
return result(lines.join(`
|
|
1164
|
+
`));
|
|
1165
|
+
}
|
|
1166
|
+
export function handleManagementAction(action, params, ctx) {
|
|
1167
|
+
switch (action) {
|
|
1168
|
+
case "list":
|
|
1169
|
+
return handleList(params, ctx);
|
|
1170
|
+
case "get":
|
|
1171
|
+
return handleGet(params, ctx);
|
|
1172
|
+
case "models":
|
|
1173
|
+
return handleModels(params, ctx);
|
|
1174
|
+
case "create":
|
|
1175
|
+
return handleCreate(params, ctx);
|
|
1176
|
+
case "update":
|
|
1177
|
+
return handleUpdate(params, ctx);
|
|
1178
|
+
case "delete":
|
|
1179
|
+
return handleDelete(params, ctx);
|
|
1180
|
+
case "eject":
|
|
1181
|
+
return handleEject(params, ctx);
|
|
1182
|
+
case "disable":
|
|
1183
|
+
return handleDisable(params, ctx);
|
|
1184
|
+
case "enable":
|
|
1185
|
+
return handleEnable(params, ctx);
|
|
1186
|
+
case "reset":
|
|
1187
|
+
return handleReset(params, ctx);
|
|
1188
|
+
default:
|
|
1189
|
+
return result(`Unknown action: ${action}`, true);
|
|
1190
|
+
}
|
|
1191
|
+
}
|