pi-subagents 0.60.0 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +55 -0
- package/docs/agents.md +7 -3
- package/docs/configuration.md +9 -5
- package/docs/extension-api.md +14 -7
- package/docs/models.md +1 -1
- package/docs/observability.md +1 -1
- package/docs/tool-reference.md +13 -4
- package/docs/workflows.md +14 -13
- package/install.mjs +1 -1
- package/package.json +1 -1
- package/skills/pi-subagents/SKILL.md +6 -4
- package/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/skills/pi-subagents/references/execution-controls.md +41 -11
- package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
- package/skills/pi-subagents/references/prompting-and-roles.md +4 -4
- package/skills/pi-subagents/references/review-and-validation.md +1 -1
- package/src/agents/agent-management.ts +121 -63
- package/src/agents/agent-serializer.ts +3 -0
- package/src/agents/agents.ts +543 -223
- package/src/agents/runtime-agent-registry.ts +5 -1
- package/src/api/background-work.ts +7 -2
- package/src/api/external-runs.ts +67 -4
- package/src/api/preflight.ts +17 -8
- package/src/api/shared-types.ts +1 -0
- package/src/extension/index.ts +7 -4
- package/src/extension/public-execution.ts +48 -4
- package/src/extension/rpc.ts +62 -4
- package/src/extension/schemas.ts +17 -9
- package/src/extension/tool-description.ts +15 -19
- package/src/runs/background/active-async-capacity.ts +26 -7
- package/src/runs/background/async-execution.ts +98 -51
- package/src/runs/background/async-job-tracker.ts +62 -3
- package/src/runs/background/async-resume.ts +6 -3
- package/src/runs/background/async-status.ts +59 -9
- package/src/runs/background/auto-drain.ts +1 -1
- package/src/runs/background/fleet-view.ts +1 -1
- package/src/runs/background/process-terminal.ts +16 -0
- package/src/runs/background/result-watcher.ts +1 -1
- package/src/runs/background/resume-guidance.ts +1 -1
- package/src/runs/background/run-status.ts +2 -2
- package/src/runs/background/scheduled-runs.ts +63 -6
- package/src/runs/background/steering.ts +4 -1
- package/src/runs/background/subagent-runner.ts +15 -9
- package/src/runs/background/subagent-wait.ts +20 -21
- package/src/runs/background/wait-completions.ts +1 -1
- package/src/runs/background/wait-tool.ts +18 -18
- package/src/runs/foreground/execution.ts +75 -9
- package/src/runs/foreground/subagent-executor.ts +181 -60
- package/src/runs/shared/acceptance.ts +113 -27
- package/src/runs/shared/capability-ceiling.ts +1 -0
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/host-step-status.ts +1 -0
- package/src/runs/shared/model-fallback.ts +61 -17
- package/src/runs/shared/parallel-utils.ts +2 -6
- package/src/runs/shared/permissions.ts +1 -1
- package/src/runs/shared/pi-args.ts +24 -12
- package/src/runs/shared/pi-spawn.ts +69 -35
- package/src/runs/shared/structured-output.ts +33 -6
- package/src/runs/shared/subagent-prompt-runtime.ts +20 -3
- package/src/runs/shared/task-intent.ts +17 -6
- package/src/runs/shared/tool-timeout.ts +1 -1
- package/src/runs/shared/workflow-graph.ts +3 -2
- package/src/shared/atomic-json.ts +3 -1
- package/src/shared/fork-context.ts +0 -12
- package/src/shared/fork-session-cwd.ts +27 -0
- package/src/shared/launch-contract.ts +3 -0
- package/src/shared/types.ts +43 -4
- package/src/shared/workflow-child-permit.ts +91 -0
- package/src/slash/prompt-template-bridge.ts +37 -1
- package/src/slash/slash-commands.ts +18 -26
- package/src/slash/subagents-admin.ts +2 -0
- package/src/tui/render.ts +95 -52
- package/src/workflows/scripted-workflow.ts +153 -4
- package/src/workflows/workflow-child-summary.ts +1 -1
- package/src/workflows/workflow-receipt.ts +41 -4
- package/src/workflows/workflow-resources.ts +150 -0
|
@@ -7,7 +7,6 @@ import {
|
|
|
7
7
|
type AgentDiscoveryDiagnostic,
|
|
8
8
|
type AgentScope,
|
|
9
9
|
type AgentSource,
|
|
10
|
-
BUILTIN_AGENT_NAMES,
|
|
11
10
|
defaultInheritProjectContext,
|
|
12
11
|
defaultInheritSkills,
|
|
13
12
|
defaultSystemPromptMode,
|
|
@@ -28,7 +27,7 @@ import {
|
|
|
28
27
|
buildProactiveSkillSubagentRecommendationLines,
|
|
29
28
|
} from "./proactive-skills.ts";
|
|
30
29
|
import { parseFrontmatter, parseFrontmatterList } from "./frontmatter.ts";
|
|
31
|
-
import { toModelInfo } from "../shared/model-info.ts";
|
|
30
|
+
import { resolveEffectiveThinking, toModelInfo } from "../shared/model-info.ts";
|
|
32
31
|
import { resolveSubagentModelOverride, type ParentModel } from "../runs/shared/model-fallback.ts";
|
|
33
32
|
import { validateToolBudgetConfig } from "../runs/shared/tool-budget.ts";
|
|
34
33
|
import { validateAcceptanceInput } from "../runs/shared/acceptance.ts";
|
|
@@ -37,7 +36,7 @@ import type { AcceptanceInput, AgentCapabilitiesSnapshot, AgentCapabilityRow, De
|
|
|
37
36
|
import { getProjectConfigDir } from "../shared/utils.ts";
|
|
38
37
|
import { previewDisplayText } from "../shared/display-text.ts";
|
|
39
38
|
import { capabilityCeilingAgentRestrictionSources, isAgentAllowedByCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.ts";
|
|
40
|
-
import {
|
|
39
|
+
import { mergeRuntimeAgents, type RuntimeAgentOwner } from "./runtime-agent-registry.ts";
|
|
41
40
|
import { listExternalJobProviders } from "../api/external-job-provider.ts";
|
|
42
41
|
|
|
43
42
|
type ManagementAction = "list" | "get" | "models" | "create" | "update" | "delete" | "eject" | "disable" | "enable" | "reset";
|
|
@@ -129,18 +128,39 @@ function allAgents(d: { builtin: AgentConfig[]; package: AgentConfig[]; user: Ag
|
|
|
129
128
|
return [...d.builtin, ...d.package, ...d.user, ...d.project];
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
function
|
|
133
|
-
|
|
131
|
+
function effectiveAgentsForScope(
|
|
132
|
+
scope: AgentScope,
|
|
133
|
+
d: { builtin: AgentConfig[]; package: AgentConfig[]; user: AgentConfig[]; project: AgentConfig[] },
|
|
134
|
+
runtimeAgentOwner?: RuntimeAgentOwner,
|
|
135
|
+
): AgentConfig[] {
|
|
136
|
+
let agents = mergeAgentsForScope(scope, d.user, d.project, d.builtin, d.package);
|
|
137
|
+
if (runtimeAgentOwner) {
|
|
138
|
+
agents = mergeRuntimeAgents(runtimeAgentOwner, { agents }, allAgents(d)).agents;
|
|
139
|
+
}
|
|
140
|
+
return agents;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function availableAgentNamesFromDiscovery(
|
|
144
|
+
d: { builtin: AgentConfig[]; package: AgentConfig[]; user: AgentConfig[]; project: AgentConfig[] },
|
|
145
|
+
runtimeAgentOwner?: RuntimeAgentOwner,
|
|
146
|
+
): string[] {
|
|
147
|
+
const agents = runtimeAgentOwner ? effectiveAgentsForScope("both", d, runtimeAgentOwner) : allAgents(d);
|
|
148
|
+
return [...new Set(agents.map((agent) => agent.name))].sort((a, b) => a.localeCompare(b));
|
|
134
149
|
}
|
|
135
150
|
|
|
136
151
|
function availableAgentNames(cwd: string): string[] {
|
|
137
152
|
return availableAgentNamesFromDiscovery(discoverAgentsAll(cwd));
|
|
138
153
|
}
|
|
139
154
|
|
|
140
|
-
function findAgentsInDiscovery(
|
|
155
|
+
function findAgentsInDiscovery(
|
|
156
|
+
name: string,
|
|
157
|
+
d: { builtin: AgentConfig[]; package: AgentConfig[]; user: AgentConfig[]; project: AgentConfig[] },
|
|
158
|
+
scope: AgentScope = "both",
|
|
159
|
+
runtimeAgentOwner?: RuntimeAgentOwner,
|
|
160
|
+
): AgentConfig[] {
|
|
141
161
|
const raw = name.trim();
|
|
142
162
|
const sanitized = sanitizeName(raw);
|
|
143
|
-
const scoped =
|
|
163
|
+
const scoped = effectiveAgentsForScope(scope, d, runtimeAgentOwner);
|
|
144
164
|
let resolved = resolveAgentName(raw, scoped);
|
|
145
165
|
if (!resolved.agent && !resolved.error && sanitized !== raw) resolved = resolveAgentName(sanitized, scoped);
|
|
146
166
|
if (resolved.agent) return scoped.filter((agent) => agent.name === resolved.agent!.name).sort((a, b) => a.source.localeCompare(b.source));
|
|
@@ -249,6 +269,7 @@ export function editableAgentConfig(agent: AgentConfig): AgentConfig {
|
|
|
249
269
|
skills: _skills,
|
|
250
270
|
skillPath: _skillPath,
|
|
251
271
|
tools: _tools,
|
|
272
|
+
excludeTools: _excludeTools,
|
|
252
273
|
mcpDirectTools: _mcpDirectTools,
|
|
253
274
|
subagentOnlyExtensions: _subagentOnlyExtensions,
|
|
254
275
|
mutationTools: _mutationTools,
|
|
@@ -281,6 +302,7 @@ export function editableAgentConfig(agent: AgentConfig): AgentConfig {
|
|
|
281
302
|
...(base.skills !== undefined ? { skills: [...base.skills] } : {}),
|
|
282
303
|
...(base.skillPath !== undefined ? { skillPath: [...base.skillPath] } : {}),
|
|
283
304
|
...(base.tools !== undefined ? { tools: [...base.tools] } : {}),
|
|
305
|
+
...(base.excludeTools !== undefined ? { excludeTools: [...base.excludeTools] } : {}),
|
|
284
306
|
...(base.mcpDirectTools !== undefined ? { mcpDirectTools: [...base.mcpDirectTools] } : {}),
|
|
285
307
|
...(base.extensions !== undefined ? { extensions: [...base.extensions] } : {}),
|
|
286
308
|
...(base.subagentOnlyExtensions !== undefined ? { subagentOnlyExtensions: [...base.subagentOnlyExtensions] } : {}),
|
|
@@ -313,6 +335,7 @@ export function preservedAgentFrontmatterFields(agent: AgentConfig, cfg: Record<
|
|
|
313
335
|
if (hasKey(cfg, "model")) changed("model");
|
|
314
336
|
if (hasKey(cfg, "fallbackModels")) changed("fallbackModels");
|
|
315
337
|
if (hasKey(cfg, "tools")) changed("tools");
|
|
338
|
+
if (hasKey(cfg, "excludeTools")) changed("excludeTools");
|
|
316
339
|
if (hasKey(cfg, "skills")) changed("skill", "skills");
|
|
317
340
|
if (hasKey(cfg, "skillPath")) changed("skillPath");
|
|
318
341
|
if (hasKey(cfg, "extensions")) changed("extensions");
|
|
@@ -443,6 +466,18 @@ function applyAgentConfig(target: AgentConfig, cfg: Record<string, unknown>): st
|
|
|
443
466
|
else delete target.mcpDirectTools;
|
|
444
467
|
} else return "config.tools must be a comma-separated string or false when provided.";
|
|
445
468
|
}
|
|
469
|
+
if (hasKey(cfg, "excludeTools")) {
|
|
470
|
+
if (cfg.excludeTools === false || cfg.excludeTools === "") delete target.excludeTools;
|
|
471
|
+
else if (typeof cfg.excludeTools === "string") {
|
|
472
|
+
const excludeTools = parseCsv(cfg.excludeTools);
|
|
473
|
+
if (excludeTools.length) target.excludeTools = [...new Set(excludeTools)];
|
|
474
|
+
else delete target.excludeTools;
|
|
475
|
+
} else if (Array.isArray(cfg.excludeTools) && cfg.excludeTools.every((entry) => typeof entry === "string")) {
|
|
476
|
+
const excludeTools = [...new Set(cfg.excludeTools.map((entry) => entry.trim()).filter(Boolean))];
|
|
477
|
+
if (excludeTools.length) target.excludeTools = excludeTools;
|
|
478
|
+
else delete target.excludeTools;
|
|
479
|
+
} else return "config.excludeTools must be a comma-separated string, string array, or false when provided.";
|
|
480
|
+
}
|
|
446
481
|
if (hasKey(cfg, "skills")) {
|
|
447
482
|
if (cfg.skills === false || cfg.skills === "") delete target.skills;
|
|
448
483
|
else if (typeof cfg.skills === "string") {
|
|
@@ -575,6 +610,7 @@ function applyAgentConfig(target: AgentConfig, cfg: Record<string, unknown>): st
|
|
|
575
610
|
if (target.runner?.type === "external-cli" || target.runner?.type === "external-job") {
|
|
576
611
|
const unsupported = [
|
|
577
612
|
target.tools?.length || target.mcpDirectTools?.length ? "tools" : undefined,
|
|
613
|
+
target.excludeTools?.length ? "excludeTools" : undefined,
|
|
578
614
|
target.model ? "model" : undefined,
|
|
579
615
|
target.fallbackModels?.length ? "fallbackModels" : undefined,
|
|
580
616
|
target.thinking ? "thinking" : undefined,
|
|
@@ -681,6 +717,7 @@ function formatAgentCapabilitiesLine(agent: AgentConfig, providerNames: Set<stri
|
|
|
681
717
|
} else if (declaredTools.length > 0) {
|
|
682
718
|
tools = declaredTools.join(", ");
|
|
683
719
|
}
|
|
720
|
+
if (agent.excludeTools?.length) tools = `${tools}; excludes: ${agent.excludeTools.join(", ")}`;
|
|
684
721
|
let model = "inherits current session";
|
|
685
722
|
if (agent.model !== undefined) {
|
|
686
723
|
model = agent.model;
|
|
@@ -708,6 +745,7 @@ function agentCapabilityTools(agent: AgentConfig): AgentCapabilityRow["tools"] {
|
|
|
708
745
|
return {
|
|
709
746
|
ambient: agent.tools === undefined && agent.mcpDirectTools === undefined,
|
|
710
747
|
names: listOrEmpty(agent.tools),
|
|
748
|
+
...(agent.excludeTools !== undefined ? { excludeTools: [...agent.excludeTools] } : {}),
|
|
711
749
|
mcpDirectTools: listOrEmpty(agent.mcpDirectTools),
|
|
712
750
|
mutationTools: agent.mutationTools,
|
|
713
751
|
};
|
|
@@ -826,6 +864,7 @@ function formatAgentDetail(agent: AgentConfig): string {
|
|
|
826
864
|
if (agent.model) lines.push(`Model: ${agent.model}`);
|
|
827
865
|
if (agent.fallbackModels?.length) lines.push(`Fallback models: ${agent.fallbackModels.join(", ")}`);
|
|
828
866
|
if (tools.length) lines.push(`Tools: ${tools.join(", ")}`);
|
|
867
|
+
if (agent.excludeTools?.length) lines.push(`Excluded tools: ${agent.excludeTools.join(", ")}`);
|
|
829
868
|
if (agent.skills?.length) lines.push(`Skills: ${agent.skills.join(", ")}`);
|
|
830
869
|
if (agent.skillPath?.length) lines.push(`Skill paths: ${agent.skillPath.join(", ")}`);
|
|
831
870
|
lines.push(`System prompt mode: ${agent.systemPromptMode}`);
|
|
@@ -863,16 +902,7 @@ function formatAgentDetail(agent: AgentConfig): string {
|
|
|
863
902
|
export function handleList(params: ManagementParams, ctx: ManagementContext): AgentToolResult<Details> {
|
|
864
903
|
const scope = normalizeListScope(params.agentScope) ?? "both";
|
|
865
904
|
const d = discoverAgentsAll(ctx.cwd, ctx.model?.provider);
|
|
866
|
-
let scopedAgents =
|
|
867
|
-
if (ctx.runtimeAgentOwner && listRuntimeAgentConfigs(ctx.runtimeAgentOwner).length > 0) {
|
|
868
|
-
const configuredAgents: AgentConfig[] = [
|
|
869
|
-
...d.builtin,
|
|
870
|
-
...d.package,
|
|
871
|
-
...d.user,
|
|
872
|
-
...d.project,
|
|
873
|
-
];
|
|
874
|
-
scopedAgents = mergeRuntimeAgents(ctx.runtimeAgentOwner, { agents: scopedAgents }, configuredAgents).agents;
|
|
875
|
-
}
|
|
905
|
+
let scopedAgents = effectiveAgentsForScope(scope, d, ctx.runtimeAgentOwner);
|
|
876
906
|
scopedAgents = scopedAgents
|
|
877
907
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
878
908
|
const capabilityCeiling = resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId);
|
|
@@ -913,80 +943,108 @@ function formatModelSource(agent: AgentConfig, currentModel: ParentModel | undef
|
|
|
913
943
|
if (agent.modelSource?.type === "subagents.defaultModel" && agent.model === agent.modelSource.model) {
|
|
914
944
|
return `${agent.modelSource.scope} defaultModel`;
|
|
915
945
|
}
|
|
916
|
-
if (agent.model) return
|
|
946
|
+
if (agent.model) return `${agent.source} agent config`;
|
|
917
947
|
if (currentModel) return "inherits current session model";
|
|
918
948
|
return "inherit requested, but no current session model is available";
|
|
919
949
|
}
|
|
920
950
|
|
|
921
951
|
function handleModels(params: ManagementParams, ctx: ManagementContext): AgentToolResult<Details> {
|
|
922
952
|
const requestedAgent = params.agent?.trim();
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
}
|
|
953
|
+
const scope = normalizeListScope(params.agentScope);
|
|
954
|
+
if (!scope) return result("agentScope must be 'user', 'project', or 'both' for models.", true);
|
|
926
955
|
|
|
927
956
|
const discovered = discoverAgentsAll(ctx.cwd, ctx.model?.provider);
|
|
928
|
-
const
|
|
929
|
-
|
|
957
|
+
const effectiveAgents = effectiveAgentsForScope(scope, discovered, ctx.runtimeAgentOwner)
|
|
958
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
930
959
|
const availableModels = ctx.modelRegistry.getAvailable().map(toModelInfo);
|
|
931
960
|
const currentModel = ctx.model ? { provider: ctx.model.provider, id: ctx.model.id } : undefined;
|
|
932
961
|
const preferredProvider = ctx.model?.provider;
|
|
933
|
-
const
|
|
962
|
+
const capabilityCeiling = resolveCurrentSubagentCapabilityCeiling(ctx.currentSessionId);
|
|
934
963
|
|
|
964
|
+
let selectedAgents = effectiveAgents;
|
|
935
965
|
if (requestedAgent) {
|
|
936
|
-
const
|
|
937
|
-
|
|
938
|
-
const
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
`
|
|
946
|
-
];
|
|
947
|
-
if (agent.override) {
|
|
948
|
-
lines.push("Override file:");
|
|
949
|
-
lines.push(` ${agent.override.path}`);
|
|
950
|
-
}
|
|
951
|
-
if (agent.model && resolvedModel && agent.model !== resolvedModel) {
|
|
952
|
-
lines.push("Requested model setting:");
|
|
953
|
-
lines.push(` ${agent.model}`);
|
|
966
|
+
const matches = findAgentsInDiscovery(requestedAgent, discovered, scope, ctx.runtimeAgentOwner);
|
|
967
|
+
const diagnostics = diagnosticsForScope(discovered.agentDiagnostics, scope);
|
|
968
|
+
const normalizedName = sanitizeName(requestedAgent);
|
|
969
|
+
const diagnostic = findBlockingAgentDiagnostic(requestedAgent, matches, diagnostics)
|
|
970
|
+
?? (normalizedName !== requestedAgent ? findBlockingAgentDiagnostic(normalizedName, matches, diagnostics) : undefined);
|
|
971
|
+
if (diagnostic) return result(`Agent '${params.agent}' has invalid configuration: ${diagnostic.error}`, true);
|
|
972
|
+
const distinctNames = [...new Set(matches.map((agent) => agent.name))];
|
|
973
|
+
if (distinctNames.length > 1) return result(`Ambiguous agent alias or name '${params.agent}': ${distinctNames.sort((a, b) => a.localeCompare(b)).join(", ")}`, true);
|
|
974
|
+
if (!matches.length) {
|
|
975
|
+
return result(`Agent '${params.agent}' not found. Available: ${availableAgentNamesFromDiscovery(discovered, ctx.runtimeAgentOwner).join(", ") || "none"}.`, true);
|
|
954
976
|
}
|
|
955
|
-
|
|
956
|
-
lines.push("Current session model:");
|
|
957
|
-
lines.push(` ${currentModel ? `${currentModel.provider}/${currentModel.id}` : "(unavailable)"}`);
|
|
958
|
-
return result(lines.join("\n"));
|
|
977
|
+
selectedAgents = [matches[0]!];
|
|
959
978
|
}
|
|
960
979
|
|
|
961
980
|
const lines = [
|
|
962
|
-
"
|
|
963
|
-
"",
|
|
964
|
-
"Current session model:",
|
|
965
|
-
` ${currentModel ? `${currentModel.provider}/${currentModel.id}` : "(unavailable)"}`,
|
|
981
|
+
requestedAgent ? "Subagent model" : "Subagent models",
|
|
966
982
|
"",
|
|
983
|
+
...(requestedAgent ? [] : [
|
|
984
|
+
"Current session model:",
|
|
985
|
+
` ${currentModel ? `${currentModel.provider}/${currentModel.id}` : "(unavailable)"}`,
|
|
986
|
+
"",
|
|
987
|
+
]),
|
|
967
988
|
];
|
|
968
989
|
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
990
|
+
const modelEntries = selectedAgents.flatMap((agent) => requestedAgent
|
|
991
|
+
? [{ agent, name: requestedAgent }]
|
|
992
|
+
: [{ agent, name: agent.name }, ...(agent.aliases ?? []).map((name) => ({ agent, name }))]);
|
|
993
|
+
for (const { agent, name } of modelEntries) {
|
|
994
|
+
const resolvedModel = resolveSubagentModelOverride(agent.model, currentModel, availableModels, agent.modelProvider ?? preferredProvider);
|
|
995
|
+
const effectiveThinking = resolveEffectiveThinking(resolvedModel, agent.thinking)
|
|
996
|
+
?? (agent.thinking === false ? "off" : undefined);
|
|
997
|
+
const source = `${formatModelSource(agent, currentModel)}${agent.disabled ? "; disabled" : ""}${isAgentAllowedByCapabilityCeiling(agent.name, capabilityCeiling) ? "" : "; restricted"}`;
|
|
998
|
+
if (requestedAgent) {
|
|
999
|
+
lines.push(`Agent: ${requestedAgent}`);
|
|
1000
|
+
lines.push("Effective model:");
|
|
1001
|
+
lines.push(` ${resolvedModel ?? "(unresolved)"}`);
|
|
1002
|
+
lines.push(`Source: ${source}`);
|
|
1003
|
+
lines.push(`Thinking: ${effectiveThinking ?? "default"}`);
|
|
1004
|
+
if (agent.fallbackModels?.length) {
|
|
1005
|
+
lines.push("Fallback models:");
|
|
1006
|
+
for (const fallback of agent.fallbackModels) {
|
|
1007
|
+
lines.push(` ${resolveSubagentModelOverride(fallback, currentModel, availableModels, agent.modelProvider ?? preferredProvider) ?? fallback}`);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
if (agent.override) {
|
|
1011
|
+
lines.push("Override file:");
|
|
1012
|
+
lines.push(` ${agent.override.path}`);
|
|
1013
|
+
}
|
|
1014
|
+
if (agent.model && resolvedModel && agent.model !== resolvedModel) {
|
|
1015
|
+
lines.push("Requested model setting:");
|
|
1016
|
+
lines.push(` ${agent.model}`);
|
|
1017
|
+
}
|
|
1018
|
+
if (agent.disabled) lines.push("Disabled: true");
|
|
1019
|
+
if (!isAgentAllowedByCapabilityCeiling(agent.name, capabilityCeiling)) lines.push("Restricted: true");
|
|
1020
|
+
lines.push("Current session model:");
|
|
1021
|
+
lines.push(` ${currentModel ? `${currentModel.provider}/${currentModel.id}` : "(unavailable)"}`);
|
|
1022
|
+
break;
|
|
978
1023
|
}
|
|
979
|
-
const resolvedModel = resolveSubagentModelOverride(agent.model, currentModel, availableModels, preferredProvider);
|
|
980
|
-
const source = `${formatModelSource(agent, currentModel)}${agent.disabled ? "; disabled" : ""}`;
|
|
981
1024
|
lines.push(name);
|
|
982
1025
|
lines.push(" model:");
|
|
983
1026
|
lines.push(` ${resolvedModel ?? "(unresolved)"}`);
|
|
984
1027
|
lines.push(` source: ${source}`);
|
|
1028
|
+
lines.push(` thinking: ${effectiveThinking ?? "default"}`);
|
|
1029
|
+
if (agent.fallbackModels?.length) {
|
|
1030
|
+
lines.push(" fallback models:");
|
|
1031
|
+
for (const fallback of agent.fallbackModels) {
|
|
1032
|
+
lines.push(` ${resolveSubagentModelOverride(fallback, currentModel, availableModels, agent.modelProvider ?? preferredProvider) ?? fallback}`);
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
if (agent.override) {
|
|
1036
|
+
lines.push(" override file:");
|
|
1037
|
+
lines.push(` ${agent.override.path}`);
|
|
1038
|
+
}
|
|
1039
|
+
if (agent.model && resolvedModel && agent.model !== resolvedModel) {
|
|
1040
|
+
lines.push(" requested model setting:");
|
|
1041
|
+
lines.push(` ${agent.model}`);
|
|
1042
|
+
}
|
|
985
1043
|
lines.push("");
|
|
986
1044
|
}
|
|
987
1045
|
|
|
988
1046
|
const availableFullIds = availableModels.map((m) => m.fullId).sort();
|
|
989
|
-
if (availableFullIds.length > 0) {
|
|
1047
|
+
if (!requestedAgent && availableFullIds.length > 0) {
|
|
990
1048
|
lines.push("Available models in this session's registry (copy an exact provider/id when passing model):");
|
|
991
1049
|
lines.push("");
|
|
992
1050
|
const shown = availableFullIds.slice(0, 80);
|
|
@@ -995,7 +1053,7 @@ function handleModels(params: ManagementParams, ctx: ManagementContext): AgentTo
|
|
|
995
1053
|
lines.push("");
|
|
996
1054
|
lines.push("Use an exact provider/id from this list when you pass model; bare ids resolve only when unique in the registry.");
|
|
997
1055
|
}
|
|
998
|
-
|
|
1056
|
+
if (!requestedAgent) appendAgentDiagnosticLines(lines, diagnosticsForScope(discovered.agentDiagnostics, scope));
|
|
999
1057
|
return result(lines.join("\n"));
|
|
1000
1058
|
}
|
|
1001
1059
|
|
|
@@ -9,6 +9,7 @@ export const KNOWN_FIELDS = new Set([
|
|
|
9
9
|
"alias",
|
|
10
10
|
"aliases",
|
|
11
11
|
"tools",
|
|
12
|
+
"excludeTools",
|
|
12
13
|
"allowNestedSubagents",
|
|
13
14
|
"model",
|
|
14
15
|
"fallbackModels",
|
|
@@ -70,6 +71,8 @@ export function serializeAgent(config: AgentConfig, options: SerializeAgentOptio
|
|
|
70
71
|
];
|
|
71
72
|
const toolsValue = joinComma(tools);
|
|
72
73
|
if (toolsValue || preserve("tools")) lines.push(`tools: ${toolsValue ?? ""}`);
|
|
74
|
+
const excludeToolsValue = joinComma(config.excludeTools);
|
|
75
|
+
if (excludeToolsValue || preserve("excludeTools")) lines.push(`excludeTools: ${excludeToolsValue ?? ""}`);
|
|
73
76
|
if (config.allowNestedSubagents === true || preserve("allowNestedSubagents")) {
|
|
74
77
|
lines.push(`allowNestedSubagents: ${config.allowNestedSubagents === undefined ? "" : config.allowNestedSubagents ? "true" : "false"}`);
|
|
75
78
|
}
|