pi-subagents 0.67.0 → 0.69.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 +90 -0
- package/README.md +1 -1
- package/docs/agents.md +41 -12
- package/docs/configuration.md +61 -19
- package/docs/extension-api.md +5 -1
- package/docs/missions.md +2 -2
- package/docs/models.md +11 -79
- package/docs/observability.md +18 -8
- package/docs/standalone-background.md +13 -3
- package/docs/tool-reference.md +38 -14
- package/docs/watchdog.md +10 -12
- package/docs/workflows.md +59 -1
- package/index.ts +5 -2
- package/package.json +4 -2
- package/runner-peer-loader.mjs +24 -0
- package/runner-peer-preload.mjs +25 -11
- package/skills/pi-subagents/SKILL.md +18 -21
- package/skills/pi-subagents/references/constraints-and-recipes.md +3 -2
- package/skills/pi-subagents/references/execution-controls.md +6 -4
- package/skills/pi-subagents/references/management-authoring-rpc.md +0 -1
- package/skills/pi-subagents/references/multi-lane-orchestration.md +1 -1
- package/skills/pi-subagents/references/prompting-and-roles.md +16 -12
- package/skills/pi-subagents/references/review-and-validation.md +3 -3
- package/src/agents/agent-management.ts +57 -58
- package/src/agents/agent-serializer.ts +4 -3
- package/src/agents/agents.ts +185 -72
- package/src/agents/chain-serializer.ts +5 -0
- package/src/agents/runtime-agent-registry.ts +7 -6
- package/src/agents/skills.ts +1 -1
- package/src/api/preflight.ts +20 -16
- package/src/api/required-child-extensions.ts +6 -0
- package/src/extension/config.ts +10 -37
- package/src/extension/fanout-child.ts +3 -0
- package/src/extension/herdr-pi-bridge.ts +160 -0
- package/src/extension/index.ts +42 -31
- package/src/extension/public-execution.ts +3 -3
- package/src/extension/schemas.ts +23 -6
- package/src/extension/tool-description.ts +8 -7
- package/src/inspectors/ghostty/plugin.ts +13 -1
- package/src/intercom/native-supervisor-channel.ts +22 -18
- package/src/policy/authority.ts +4 -0
- package/src/profiles/profiles.ts +12 -6
- package/src/runs/background/active-run-index.ts +17 -1
- package/src/runs/background/async-execution.ts +309 -126
- package/src/runs/background/async-job-tracker.ts +8 -6
- package/src/runs/background/async-resume.ts +13 -4
- package/src/runs/background/async-status.ts +15 -4
- package/src/runs/background/auto-drain.ts +20 -10
- package/src/runs/background/binary-bootstrap.ts +5 -0
- package/src/runs/background/chain-append.ts +1 -1
- package/src/runs/background/chain-root-attachment.ts +14 -33
- package/src/runs/background/notify.ts +74 -6
- package/src/runs/background/result-files.ts +8 -4
- package/src/runs/background/result-watcher.ts +19 -2
- package/src/runs/background/run-child-session.ts +20 -29
- package/src/runs/background/runner-aliases.ts +4 -33
- package/src/runs/background/runner-child-launch.ts +4 -1
- package/src/runs/background/runner-child-sessions.ts +2 -2
- package/src/runs/background/runner-http-dispatcher.ts +119 -0
- package/src/runs/background/scheduled-runs.ts +11 -5
- package/src/runs/background/stale-run-reconciler.ts +35 -11
- package/src/runs/background/subagent-runner.ts +413 -276
- package/src/runs/background/subagent-wait.ts +128 -23
- package/src/runs/background/wait-completions.ts +75 -27
- package/src/runs/background/wait-subscriptions.ts +9 -3
- package/src/runs/background/wait-tool.ts +4 -2
- package/src/runs/foreground/async-stop-action.ts +93 -3
- package/src/runs/foreground/execution.ts +115 -219
- package/src/runs/foreground/foreground-history.ts +2 -1
- package/src/runs/foreground/subagent-executor.ts +281 -80
- package/src/runs/shared/acceptance.ts +194 -37
- package/src/runs/shared/async-status-projection.ts +123 -33
- package/src/runs/shared/child-launch-plan.ts +15 -3
- package/src/runs/shared/child-launch.ts +19 -6
- package/src/runs/shared/child-runtime-config.ts +5 -0
- package/src/runs/shared/child-session.ts +94 -50
- package/src/runs/shared/child-tool-plan.ts +28 -16
- package/src/runs/shared/dynamic-fanout.ts +2 -2
- package/src/runs/shared/external-cli-contract.ts +11 -1
- package/src/runs/shared/external-cli-preflight.ts +6 -2
- package/src/runs/shared/herdr-connection.ts +134 -0
- package/src/runs/shared/herdr-external-adapters.ts +169 -0
- package/src/runs/shared/herdr-machine.ts +279 -0
- package/src/runs/shared/herdr-pi-protocol.ts +59 -0
- package/src/runs/shared/herdr-placed-run.ts +263 -0
- package/src/runs/shared/model-resolution-diagnostic.ts +76 -0
- package/src/runs/shared/{model-fallback.ts → model-resolution.ts} +22 -237
- package/src/runs/shared/model-scope.ts +1 -1
- package/src/runs/shared/nested-events.ts +11 -2
- package/src/runs/shared/parallel-utils.ts +7 -2
- package/src/runs/shared/pi-spawn.ts +1 -1
- package/src/runs/shared/subagent-prompt-runtime.ts +4 -2
- package/src/runs/shared/worktree-setup-command.ts +27 -4
- package/src/runs/shared/worktree.ts +30 -8
- package/src/shared/child-cache-retention.ts +43 -0
- package/src/shared/launch-contract.ts +6 -9
- package/src/shared/pruned-fork.ts +1 -1
- package/src/shared/required-child-extensions.ts +81 -0
- package/src/shared/settings.ts +5 -2
- package/src/shared/shortcuts.ts +0 -4
- package/src/shared/types.ts +81 -29
- package/src/slash/slash-commands.ts +0 -6
- package/src/slash/subagents-admin.ts +13 -9
- package/src/tui/render.ts +20 -10
- package/src/watchdog/child-status.ts +28 -36
- package/src/watchdog/lsp-diagnostics.ts +1 -1
- package/src/watchdog/model-selection.ts +1 -1
- package/src/watchdog/register-child.ts +10 -3
- package/src/watchdog/register-main.ts +20 -20
- package/src/watchdog/render.ts +1 -1
- package/src/watchdog/review.ts +14 -30
- package/src/watchdog/rules.ts +1 -1
- package/src/watchdog/runtime.ts +23 -12
- package/src/watchdog/settings.ts +3 -6
- package/src/watchdog/types.ts +3 -5
- package/src/watchdog/warning-format.ts +1 -1
- package/src/workflows/scripted-workflow.ts +68 -7
- package/src/workflows/workflow-receipt.ts +21 -3
- package/src/workflows/workflow-resources.ts +13 -2
- package/src/runs/shared/model-exclusions.ts +0 -374
- package/src/runs/shared/readonly-model-continuation.ts +0 -69
- package/src/runs/shared/readonly-session-evidence.ts +0 -307
|
@@ -4,7 +4,7 @@ import type { AgentConfig } from "../agents/agents.ts";
|
|
|
4
4
|
import type { PiLaunchToolPlan } from "../runs/shared/child-tool-plan.ts";
|
|
5
5
|
import type { ExtensionBindings } from "../runs/shared/extension-bindings.ts";
|
|
6
6
|
|
|
7
|
-
export const AGENT_DEFINITION_PROJECTION_VERSION =
|
|
7
|
+
export const AGENT_DEFINITION_PROJECTION_VERSION = 2 as const;
|
|
8
8
|
// v2: the Intercom bridge prompt and tools are part of the binding on every
|
|
9
9
|
// path, and the bridge text no longer names the parent session.
|
|
10
10
|
export const LAUNCH_BINDING_PROJECTION_VERSION = 2 as const;
|
|
@@ -50,7 +50,6 @@ export function projectAgentDefinition(agent: AgentConfig): Record<string, unkno
|
|
|
50
50
|
inheritSkills: agent.inheritSkills,
|
|
51
51
|
model: agent.model,
|
|
52
52
|
modelProvider: agent.modelProvider,
|
|
53
|
-
fallbackModels: agent.fallbackModels,
|
|
54
53
|
fast: agent.fast,
|
|
55
54
|
thinking: agent.thinking,
|
|
56
55
|
tools: agent.tools,
|
|
@@ -63,6 +62,7 @@ export function projectAgentDefinition(agent: AgentConfig): Record<string, unkno
|
|
|
63
62
|
skills: agent.skills,
|
|
64
63
|
skillPath: agent.skillPath,
|
|
65
64
|
output: agent.output,
|
|
65
|
+
outputSchema: agent.outputSchema,
|
|
66
66
|
defaultReads: agent.defaultReads,
|
|
67
67
|
defaultProgress: agent.defaultProgress,
|
|
68
68
|
defaultContext: agent.defaultContext,
|
|
@@ -88,7 +88,6 @@ export interface LaunchBindingInput {
|
|
|
88
88
|
/** Caller task; runtime acceptance/output task annotations are explicitly outside the preflight-known subset. */
|
|
89
89
|
task?: string;
|
|
90
90
|
model?: string;
|
|
91
|
-
modelCandidates?: string[];
|
|
92
91
|
fast?: boolean;
|
|
93
92
|
thinking?: string;
|
|
94
93
|
systemPrompt?: string | null;
|
|
@@ -114,9 +113,7 @@ export function projectLaunchBinding(input: LaunchBindingInput): Record<string,
|
|
|
114
113
|
version: LAUNCH_BINDING_PROJECTION_VERSION,
|
|
115
114
|
definitionDigest: input.definitionDigest,
|
|
116
115
|
taskDigest: input.task === undefined ? undefined : stableJsonDigest(input.task),
|
|
117
|
-
|
|
118
|
-
// this set makes retries correlate to the same preflight binding.
|
|
119
|
-
modelCandidates: input.modelCandidates,
|
|
116
|
+
model: input.model,
|
|
120
117
|
fast: input.fast,
|
|
121
118
|
thinking: input.thinking,
|
|
122
119
|
systemPromptDigest: input.systemPrompt === undefined || input.systemPrompt === null ? undefined : stableJsonDigest(input.systemPrompt),
|
|
@@ -155,7 +152,7 @@ export type LaunchBindingSource = LaunchBindingIdentity
|
|
|
155
152
|
& Pick<LaunchBindingInput, "fast" | "thinking" | "skills" | "outputPath" | "outputMode" | "structuredOutputSchema" | "extensionBindings">
|
|
156
153
|
& {
|
|
157
154
|
task: string;
|
|
158
|
-
|
|
155
|
+
model?: string;
|
|
159
156
|
/** Effective child system prompt before runtime acceptance prose. */
|
|
160
157
|
systemPrompt: string;
|
|
161
158
|
toolPlan: Pick<PiLaunchToolPlan, "effectiveToolAllowlist" | "excludeTools" | "extensionArgs" | "effectiveMcpTools">;
|
|
@@ -183,7 +180,7 @@ export function resolveLaunchBinding(source: LaunchBindingSource): LaunchBinding
|
|
|
183
180
|
launchContractDigest: launchBindingDigest({
|
|
184
181
|
...identity,
|
|
185
182
|
task: source.task,
|
|
186
|
-
|
|
183
|
+
model: source.model,
|
|
187
184
|
fast: source.fast,
|
|
188
185
|
thinking: source.thinking || undefined,
|
|
189
186
|
systemPrompt: source.systemPrompt,
|
|
@@ -194,7 +191,7 @@ export function resolveLaunchBinding(source: LaunchBindingSource): LaunchBinding
|
|
|
194
191
|
mcpDirectTools: source.toolPlan.effectiveMcpTools,
|
|
195
192
|
outputPath: source.outputPath || undefined,
|
|
196
193
|
outputMode: source.outputMode,
|
|
197
|
-
structuredOutputSchema: source.structuredOutputSchema
|
|
194
|
+
structuredOutputSchema: source.structuredOutputSchema,
|
|
198
195
|
extensionBindings: source.extensionBindings || undefined,
|
|
199
196
|
}),
|
|
200
197
|
};
|
|
@@ -5,7 +5,7 @@ import * as path from "node:path";
|
|
|
5
5
|
import type { TextContent } from "@earendil-works/pi-ai";
|
|
6
6
|
import { completeSimple } from "@earendil-works/pi-ai/compat";
|
|
7
7
|
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
8
|
-
import { resolveModelCandidate } from "../runs/shared/model-
|
|
8
|
+
import { resolveModelCandidate } from "../runs/shared/model-resolution.ts";
|
|
9
9
|
import { splitKnownThinkingSuffix, toModelInfo } from "./model-info.ts";
|
|
10
10
|
import type { ForkContextConfig } from "./types.ts";
|
|
11
11
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
|
|
4
|
+
const ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
|
|
5
|
+
const MAX_REQUIRED_EXTENSIONS = 32;
|
|
6
|
+
const MAX_PATH_BYTES = 4096;
|
|
7
|
+
const EMPTY_SNAPSHOT: RequiredChildExtensionSnapshot = Object.freeze([]);
|
|
8
|
+
|
|
9
|
+
export interface RequiredChildExtension {
|
|
10
|
+
/** Safe host-owned identity exposed in launch evidence. */
|
|
11
|
+
id: string;
|
|
12
|
+
/** Existing importable module path. Snapshotted to its canonical absolute path. */
|
|
13
|
+
path: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface RegisterRequiredChildExtensionsInput {
|
|
17
|
+
sessionId: string;
|
|
18
|
+
extensions: readonly RequiredChildExtension[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RequiredChildExtensionRegistration { dispose(): void }
|
|
22
|
+
export type RequiredChildExtensionSnapshot = ReadonlyArray<Readonly<RequiredChildExtension>>;
|
|
23
|
+
|
|
24
|
+
/** Validate and freeze a snapshot; registration canonicalizes once, while retained launches preserve that identity. */
|
|
25
|
+
export function snapshotRequiredChildExtensions(value: unknown, label = "Required child extensions", canonicalizeFiles = false): RequiredChildExtensionSnapshot {
|
|
26
|
+
if (!Array.isArray(value) || value.length > MAX_REQUIRED_EXTENSIONS) throw new Error(`${label} must be an array of at most ${MAX_REQUIRED_EXTENSIONS} entries.`);
|
|
27
|
+
const ids = new Set<string>();
|
|
28
|
+
const paths = new Set<string>();
|
|
29
|
+
return Object.freeze(value.map((entry, index) => {
|
|
30
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry) || Object.keys(entry).some((key) => key !== "id" && key !== "path")) throw new Error(`${label} entry ${index} requires only id and path.`);
|
|
31
|
+
const id = "id" in entry ? entry.id : undefined;
|
|
32
|
+
const rawPath = "path" in entry ? entry.path : undefined;
|
|
33
|
+
if (typeof id !== "string" || !ID_PATTERN.test(id)) throw new Error(`${label} entry ${index} requires a safe id of at most 128 characters.`);
|
|
34
|
+
if (ids.has(id)) throw new Error(`${label} id '${id}' is duplicated.`);
|
|
35
|
+
if (typeof rawPath !== "string" || !rawPath.trim() || rawPath.includes("\0") || Buffer.byteLength(rawPath, "utf8") > MAX_PATH_BYTES || (!canonicalizeFiles && !path.isAbsolute(rawPath))) throw new Error(`${label} '${id}' requires ${canonicalizeFiles ? "a" : "an absolute"} non-empty path of at most ${MAX_PATH_BYTES} bytes without NUL.`);
|
|
36
|
+
let extensionPath = rawPath;
|
|
37
|
+
if (canonicalizeFiles) {
|
|
38
|
+
try {
|
|
39
|
+
extensionPath = fs.realpathSync(path.resolve(rawPath));
|
|
40
|
+
if (!fs.statSync(extensionPath).isFile()) throw new Error("not a file");
|
|
41
|
+
} catch (error) {
|
|
42
|
+
throw new Error(`${label} '${id}' is not an importable file: ${error instanceof Error ? error.message : String(error)}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (paths.has(extensionPath)) throw new Error(`${label} path '${extensionPath}' is duplicated.`);
|
|
46
|
+
ids.add(id);
|
|
47
|
+
paths.add(extensionPath);
|
|
48
|
+
return Object.freeze({ id, path: extensionPath });
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface Registry { version: 1; bySession: Map<string, RequiredChildExtensionSnapshot> }
|
|
53
|
+
|
|
54
|
+
function registry(): Registry {
|
|
55
|
+
const key = Symbol.for("pi-subagents.required-child-extensions.v1");
|
|
56
|
+
const root = globalThis as Record<PropertyKey, unknown>;
|
|
57
|
+
const existing = root[key];
|
|
58
|
+
if (existing === undefined) {
|
|
59
|
+
const created: Registry = { version: 1, bySession: new Map() };
|
|
60
|
+
root[key] = created;
|
|
61
|
+
return created;
|
|
62
|
+
}
|
|
63
|
+
if (!existing || typeof existing !== "object" || !("version" in existing) || existing.version !== 1 || !("bySession" in existing) || !(existing.bySession instanceof Map)) throw new Error("Malformed or unsupported required child extension registry.");
|
|
64
|
+
return { version: 1, bySession: existing.bySession };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Register one immutable host-required extension snapshot for a parent session. */
|
|
68
|
+
export function registerRequiredChildExtensions(input: RegisterRequiredChildExtensionsInput): RequiredChildExtensionRegistration {
|
|
69
|
+
if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).some((key) => key !== "sessionId" && key !== "extensions")) throw new Error("Required child extension registration requires only sessionId and extensions.");
|
|
70
|
+
if (typeof input.sessionId !== "string" || !input.sessionId || input.sessionId.trim() !== input.sessionId || input.sessionId.length > 256 || input.sessionId.includes("\0")) throw new Error("Required child extension registration requires a non-empty trimmed sessionId of at most 256 characters without NUL.");
|
|
71
|
+
const frozen = snapshotRequiredChildExtensions(input.extensions, "Required child extensions", true);
|
|
72
|
+
const store = registry();
|
|
73
|
+
if (store.bySession.has(input.sessionId)) throw new Error(`Required child extensions are already registered for session '${input.sessionId}'; dispose them first.`);
|
|
74
|
+
store.bySession.set(input.sessionId, frozen);
|
|
75
|
+
return { dispose() { if (store.bySession.get(input.sessionId) === frozen) store.bySession.delete(input.sessionId); } };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function resolveRequiredChildExtensions(sessionId: string | undefined): RequiredChildExtensionSnapshot {
|
|
79
|
+
if (!sessionId) return EMPTY_SNAPSHOT;
|
|
80
|
+
return registry().bySession.get(sessionId) ?? EMPTY_SNAPSHOT;
|
|
81
|
+
}
|
package/src/shared/settings.ts
CHANGED
|
@@ -32,8 +32,9 @@ export interface SequentialStep {
|
|
|
32
32
|
phase?: string;
|
|
33
33
|
label?: string;
|
|
34
34
|
as?: string;
|
|
35
|
-
outputSchema?: JsonSchemaObject;
|
|
35
|
+
outputSchema?: JsonSchemaObject | false;
|
|
36
36
|
cwd?: string;
|
|
37
|
+
machine?: string;
|
|
37
38
|
output?: OutputOverrideInput;
|
|
38
39
|
outputMode?: OutputMode;
|
|
39
40
|
reads?: string[] | false;
|
|
@@ -56,8 +57,9 @@ export interface ParallelTaskItem {
|
|
|
56
57
|
phase?: string;
|
|
57
58
|
label?: string;
|
|
58
59
|
as?: string;
|
|
59
|
-
outputSchema?: JsonSchemaObject;
|
|
60
|
+
outputSchema?: JsonSchemaObject | false;
|
|
60
61
|
cwd?: string;
|
|
62
|
+
machine?: string;
|
|
61
63
|
count?: number;
|
|
62
64
|
output?: OutputOverrideInput;
|
|
63
65
|
outputMode?: OutputMode;
|
|
@@ -110,6 +112,7 @@ export interface ParallelStep {
|
|
|
110
112
|
failFast?: boolean;
|
|
111
113
|
worktree?: boolean;
|
|
112
114
|
cwd?: string;
|
|
115
|
+
machine?: string;
|
|
113
116
|
agentContract?: AgentContract;
|
|
114
117
|
gateOn?: ChainGateLayer;
|
|
115
118
|
}
|
package/src/shared/shortcuts.ts
CHANGED
package/src/shared/types.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type { GlobalMissionIndexRecord, MissionRecord, MissionStoreConfig } from
|
|
|
16
16
|
import type { ExtensionBindings } from "../runs/shared/extension-bindings.ts";
|
|
17
17
|
import type { WorkflowChildPermitContext } from "./workflow-child-permit.ts";
|
|
18
18
|
import type { WatchdogWarningDetails } from "../watchdog/types.ts";
|
|
19
|
+
import type { RequiredChildExtensionSnapshot } from "./required-child-extensions.ts";
|
|
19
20
|
|
|
20
21
|
// ============================================================================
|
|
21
22
|
// Basic Types
|
|
@@ -230,6 +231,7 @@ export interface WorkflowReceipt {
|
|
|
230
231
|
state: WorkflowReceiptState;
|
|
231
232
|
createdAt: number;
|
|
232
233
|
entries: Record<string, WorkflowReceiptEntry>;
|
|
234
|
+
argsDigest?: string;
|
|
233
235
|
resource?: WorkflowResourceProvenance;
|
|
234
236
|
hostSteps?: HostStepNode[];
|
|
235
237
|
workflowChildren?: WorkflowChildSummary;
|
|
@@ -655,6 +657,12 @@ export type ProcessTreeTerminal =
|
|
|
655
657
|
processGroupId: number;
|
|
656
658
|
verifiedAt: number;
|
|
657
659
|
}
|
|
660
|
+
| {
|
|
661
|
+
state: "observed";
|
|
662
|
+
mechanism: "windows-taskkill";
|
|
663
|
+
pid: number;
|
|
664
|
+
verifiedAt: number;
|
|
665
|
+
}
|
|
658
666
|
| {
|
|
659
667
|
state: "unknown";
|
|
660
668
|
reason: "unsupported-platform" | "signal-failed" | "verification-failed";
|
|
@@ -800,6 +808,7 @@ export interface SteeringRecoveryDescriptor {
|
|
|
800
808
|
version: 1;
|
|
801
809
|
launchContractDigest?: string;
|
|
802
810
|
extensionBindings?: ExtensionBindings;
|
|
811
|
+
requiredExtensions?: RequiredChildExtensionSnapshot;
|
|
803
812
|
runFanoutBudget: RunFanoutBudgetDescriptor;
|
|
804
813
|
sourceRunId: string;
|
|
805
814
|
agentContract?: AgentContract;
|
|
@@ -812,7 +821,6 @@ export interface SteeringRecoveryDescriptor {
|
|
|
812
821
|
modelProvider?: string;
|
|
813
822
|
modelOverrideFromParent?: boolean;
|
|
814
823
|
modelOrigin?: "explicit" | "inherited" | "configured";
|
|
815
|
-
fallbackModels?: string[];
|
|
816
824
|
fast?: boolean;
|
|
817
825
|
thinking?: string;
|
|
818
826
|
thinkingCeiling?: ThinkingLevel;
|
|
@@ -916,7 +924,7 @@ export interface SubagentResultIntercomPayload {
|
|
|
916
924
|
// Progress Tracking
|
|
917
925
|
// ============================================================================
|
|
918
926
|
|
|
919
|
-
export interface ChildWatchdogWarningSummary extends Pick<WatchdogWarningDetails, "severity" | "category" | "summary" | "evidence" | "recommendedAction" | "displayedAt"> {
|
|
927
|
+
export interface ChildWatchdogWarningSummary extends Pick<WatchdogWarningDetails, "severity" | "importance" | "category" | "summary" | "evidence" | "recommendedAction" | "displayedAt"> {
|
|
920
928
|
/** True when a later assistant turn in the child followed the warning. */
|
|
921
929
|
addressed: boolean;
|
|
922
930
|
stalemate: boolean;
|
|
@@ -993,14 +1001,6 @@ interface ProgressSummary {
|
|
|
993
1001
|
// Results
|
|
994
1002
|
// ============================================================================
|
|
995
1003
|
|
|
996
|
-
export interface ModelAttempt {
|
|
997
|
-
model: string;
|
|
998
|
-
success: boolean;
|
|
999
|
-
exitCode?: number | null;
|
|
1000
|
-
error?: string;
|
|
1001
|
-
usage?: Usage;
|
|
1002
|
-
}
|
|
1003
|
-
|
|
1004
1004
|
export type AcceptanceLevel = "auto" | "none" | "attested" | "checked" | "verified";
|
|
1005
1005
|
|
|
1006
1006
|
export type AcceptanceEvidenceKind =
|
|
@@ -1028,6 +1028,10 @@ export interface AcceptanceVerifyCommand {
|
|
|
1028
1028
|
cwd?: string;
|
|
1029
1029
|
env?: Record<string, string>;
|
|
1030
1030
|
allowFailure?: boolean;
|
|
1031
|
+
/** When "json", a passing command's stdout is parsed and becomes the run's structured output. */
|
|
1032
|
+
output?: "json";
|
|
1033
|
+
/** Optional JSON Schema the parsed stdout must satisfy; only meaningful with `output: "json"`. */
|
|
1034
|
+
schema?: JsonSchemaObject;
|
|
1031
1035
|
}
|
|
1032
1036
|
|
|
1033
1037
|
export interface AcceptanceReviewGate {
|
|
@@ -1039,6 +1043,8 @@ export interface AcceptanceReviewGate {
|
|
|
1039
1043
|
export interface AcceptanceConfig {
|
|
1040
1044
|
level?: AcceptanceLevel;
|
|
1041
1045
|
report?: "on" | "off";
|
|
1046
|
+
/** Preserve an intentional launch-time staged index, while rejecting any terminal index change. */
|
|
1047
|
+
preserveStagedIndex?: true;
|
|
1042
1048
|
criteria?: Array<string | AcceptanceGate>;
|
|
1043
1049
|
evidence?: AcceptanceEvidenceKind[];
|
|
1044
1050
|
verify?: AcceptanceVerifyCommand[];
|
|
@@ -1063,6 +1069,7 @@ export interface ResolvedAcceptanceConfig {
|
|
|
1063
1069
|
inferredReason: string[];
|
|
1064
1070
|
criteria: ResolvedAcceptanceGate[];
|
|
1065
1071
|
evidence: AcceptanceEvidenceKind[];
|
|
1072
|
+
preserveStagedIndex?: true;
|
|
1066
1073
|
verify: AcceptanceVerifyCommand[];
|
|
1067
1074
|
review?: AcceptanceReviewGate | false;
|
|
1068
1075
|
stopRules: string[];
|
|
@@ -1121,6 +1128,10 @@ export interface AcceptanceVerifyResult {
|
|
|
1121
1128
|
diffHash: string;
|
|
1122
1129
|
};
|
|
1123
1130
|
artifactError?: string;
|
|
1131
|
+
/** Parsed stdout of a passing `output: "json"` command. */
|
|
1132
|
+
structuredOutput?: unknown;
|
|
1133
|
+
/** Why a passing `output: "json"` command still failed: invalid JSON, truncated stdout, or schema mismatch. */
|
|
1134
|
+
structuredOutputError?: string;
|
|
1124
1135
|
}
|
|
1125
1136
|
|
|
1126
1137
|
export interface AcceptanceReviewResult {
|
|
@@ -1187,10 +1198,13 @@ export interface LaunchResolvedChildExtensions {
|
|
|
1187
1198
|
disableAmbientExtensions: boolean;
|
|
1188
1199
|
runtime: string[];
|
|
1189
1200
|
configured: string[];
|
|
1201
|
+
/** Bounded host-supplied identities; paths are intentionally not exposed. */
|
|
1202
|
+
required: string[];
|
|
1190
1203
|
effective: string[];
|
|
1191
1204
|
omitted: {
|
|
1192
1205
|
runtime: number;
|
|
1193
1206
|
configured: number;
|
|
1207
|
+
required: number;
|
|
1194
1208
|
effective: number;
|
|
1195
1209
|
};
|
|
1196
1210
|
}
|
|
@@ -1261,16 +1275,16 @@ export interface SingleResult {
|
|
|
1261
1275
|
messages?: Message[];
|
|
1262
1276
|
usage: Usage;
|
|
1263
1277
|
model?: string;
|
|
1278
|
+
/** Authoritative before/after Git evidence captured by a pane-native remote machine. */
|
|
1279
|
+
nativeMachine?: { provider: "herdr"; machineId: string; initialGit?: HerdrRemoteGitStatus; finalGit?: HerdrRemoteGitStatus };
|
|
1264
1280
|
/** Effective thinking level used by this foreground child, when known. */
|
|
1265
1281
|
thinking?: string;
|
|
1266
|
-
|
|
1267
|
-
modelAttempts?: ModelAttempt[];
|
|
1282
|
+
requestedModel?: string;
|
|
1268
1283
|
controlEvents?: ControlEvent[];
|
|
1269
1284
|
error?: string;
|
|
1270
1285
|
/**
|
|
1271
1286
|
* True when the dispatch failed because the input exceeded the model's
|
|
1272
|
-
* context window.
|
|
1273
|
-
* same input on another model cannot succeed). Callers should treat this as
|
|
1287
|
+
* context window. Callers should treat this as
|
|
1274
1288
|
* a signal to reduce input size or re-decompose the task.
|
|
1275
1289
|
*/
|
|
1276
1290
|
contextOverflow?: boolean;
|
|
@@ -1381,10 +1395,11 @@ export interface AgentCapabilityRow {
|
|
|
1381
1395
|
executable: boolean;
|
|
1382
1396
|
restrictionSources?: string[];
|
|
1383
1397
|
aliases?: string[];
|
|
1384
|
-
runner: { type: "pi" } | { type: "external-cli"; adapter?: string; command: string; available: boolean; unavailableReason?: string; capabilities: ExternalCliCapabilities } | { type: "external-job"; provider: string; available?: boolean; capabilities: ExternalJobRunnerStatus["capabilities"] };
|
|
1398
|
+
runner: { type: "pi" } | { type: "external-cli"; adapter?: string; command: string; machine?: string; available: boolean; unavailableReason?: string; capabilities: ExternalCliCapabilities } | { type: "external-job"; provider: string; available?: boolean; capabilities: ExternalJobRunnerStatus["capabilities"] };
|
|
1385
1399
|
tools: { ambient: boolean; names: string[]; excludeTools?: string[]; mcpDirectTools: string[]; mutationTools?: string[] };
|
|
1386
|
-
model?: { value?: string;
|
|
1400
|
+
model?: { value?: string; thinking?: string | false };
|
|
1387
1401
|
execution?: { defaultAsync?: boolean; timeoutMs?: number };
|
|
1402
|
+
acceptance?: { policy?: AcceptanceInput; role?: AcceptanceRole };
|
|
1388
1403
|
output?: { path?: string; mode?: OutputMode };
|
|
1389
1404
|
extensions?: { names?: string[]; subagentOnly?: string[]; skills?: string[] };
|
|
1390
1405
|
}
|
|
@@ -1411,6 +1426,12 @@ export interface Details {
|
|
|
1411
1426
|
timedOut: true;
|
|
1412
1427
|
activeRunIds: string[];
|
|
1413
1428
|
activeProviderItems: Array<{ provider: string; id: string }>;
|
|
1429
|
+
} | {
|
|
1430
|
+
/** Non-terminal internal auto-drain yield; tracked work remains active. */
|
|
1431
|
+
reason: "supervisor_request";
|
|
1432
|
+
timedOut: false;
|
|
1433
|
+
activeRunIds: string[];
|
|
1434
|
+
activeProviderItems: Array<{ provider: string; id: string }>;
|
|
1414
1435
|
};
|
|
1415
1436
|
controlEvents?: ControlEvent[];
|
|
1416
1437
|
steering?: SteerActionResult;
|
|
@@ -1472,6 +1493,8 @@ export interface Details {
|
|
|
1472
1493
|
mission?: MissionRecord;
|
|
1473
1494
|
workflow?: {
|
|
1474
1495
|
value?: unknown;
|
|
1496
|
+
args?: Record<string, unknown>;
|
|
1497
|
+
argsDigest?: string;
|
|
1475
1498
|
resource?: WorkflowResourceProvenance;
|
|
1476
1499
|
preflightWarnings?: string[];
|
|
1477
1500
|
trace: Array<{
|
|
@@ -1707,6 +1730,26 @@ export type AgentRunnerConfig =
|
|
|
1707
1730
|
|
|
1708
1731
|
export type ExternalCliCapabilityNarrowing = Partial<Record<"steer" | "resume" | "structuredOutput" | "toolEvents" | "supervisor" | "forkContext" | "extensionBindings", false>>;
|
|
1709
1732
|
|
|
1733
|
+
export interface HerdrRemoteGitStatus {
|
|
1734
|
+
head?: string;
|
|
1735
|
+
branch?: string;
|
|
1736
|
+
dirty?: boolean;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
/** A Herdr saved SSH machine resolved for one launch. `cwd` is the directory on that machine. */
|
|
1740
|
+
export interface HerdrMachineReference {
|
|
1741
|
+
provider: "herdr";
|
|
1742
|
+
id: string;
|
|
1743
|
+
label?: string;
|
|
1744
|
+
target: string;
|
|
1745
|
+
session?: string;
|
|
1746
|
+
cwd: string;
|
|
1747
|
+
}
|
|
1748
|
+
|
|
1749
|
+
export interface ExternalCliMachineStatus extends HerdrMachineReference {
|
|
1750
|
+
remoteGit?: HerdrRemoteGitStatus;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1710
1753
|
export interface ExternalCliCapabilities {
|
|
1711
1754
|
stop: true;
|
|
1712
1755
|
steer: false;
|
|
@@ -1721,6 +1764,7 @@ export interface ExternalCliCapabilities {
|
|
|
1721
1764
|
export interface ExternalCliReceiptMetadata {
|
|
1722
1765
|
adapter: { id: "external-cli" | "codex-exec" | "codex-exec-writer" | "claude-code" | "claude-code-writer" | "cursor-agent" | "cursor-agent-writer" | "grok-build"; version: 1; executionMode: "one-shot-stdin" | "one-shot-prompt-file" };
|
|
1723
1766
|
capabilities: ExternalCliCapabilities;
|
|
1767
|
+
machine?: ExternalCliMachineStatus;
|
|
1724
1768
|
safety?:
|
|
1725
1769
|
| { sandbox: "read-only"; approvalPolicy: "never"; ephemeral: true }
|
|
1726
1770
|
| { access: "workspace-write"; sandbox: "workspace-write"; approvalPolicy: "never"; ephemeral: true }
|
|
@@ -1745,6 +1789,7 @@ export interface ExternalCliRunnerStatus {
|
|
|
1745
1789
|
capabilities: ExternalCliCapabilities;
|
|
1746
1790
|
unsupportedReasons: Record<Exclude<keyof ExternalCliCapabilities, "stop">, string>;
|
|
1747
1791
|
nonResumableReason: string;
|
|
1792
|
+
machine?: HerdrMachineReference;
|
|
1748
1793
|
}
|
|
1749
1794
|
|
|
1750
1795
|
export interface ExternalJobRunnerStatus {
|
|
@@ -1796,6 +1841,7 @@ export interface ExternalProcessStatus {
|
|
|
1796
1841
|
stderrBytes?: number;
|
|
1797
1842
|
stdoutTruncated?: boolean;
|
|
1798
1843
|
stderrTruncated?: boolean;
|
|
1844
|
+
machine?: ExternalCliMachineStatus;
|
|
1799
1845
|
}
|
|
1800
1846
|
|
|
1801
1847
|
export interface AsyncStatus {
|
|
@@ -1928,8 +1974,7 @@ export interface AsyncStatus {
|
|
|
1928
1974
|
thinking?: string;
|
|
1929
1975
|
contextLimit?: number;
|
|
1930
1976
|
thinkingCeiling?: ThinkingLevel;
|
|
1931
|
-
|
|
1932
|
-
modelAttempts?: ModelAttempt[];
|
|
1977
|
+
requestedModel?: string;
|
|
1933
1978
|
/** True when the child input exceeded the model context window. */
|
|
1934
1979
|
contextOverflow?: boolean;
|
|
1935
1980
|
totalCost?: CostSummary;
|
|
@@ -2070,7 +2115,7 @@ export interface ForegroundResumeChild {
|
|
|
2070
2115
|
/** Private bounded launch fields needed to preserve the child contract on resume. */
|
|
2071
2116
|
resumeContract?: {
|
|
2072
2117
|
modelResponseAliases?: Record<string, string[]>;
|
|
2073
|
-
outputSchema?: JsonSchemaObject;
|
|
2118
|
+
outputSchema?: JsonSchemaObject | false;
|
|
2074
2119
|
agentContract?: AgentContract;
|
|
2075
2120
|
acceptance?: AcceptanceInput;
|
|
2076
2121
|
output?: string | boolean;
|
|
@@ -2079,6 +2124,7 @@ export interface ForegroundResumeChild {
|
|
|
2079
2124
|
launchContractDigest?: string;
|
|
2080
2125
|
/** Private retained launch authority. Never project into status or result output. */
|
|
2081
2126
|
extensionBindings?: ExtensionBindings;
|
|
2127
|
+
requiredExtensions?: RequiredChildExtensionSnapshot;
|
|
2082
2128
|
launchResolvedExtensions?: LaunchResolvedChildExtensions;
|
|
2083
2129
|
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensions;
|
|
2084
2130
|
execution?: ExecutionProjection;
|
|
@@ -2256,8 +2302,8 @@ export interface SubagentState {
|
|
|
2256
2302
|
lastUiContext: ExtensionContext | null;
|
|
2257
2303
|
poller: NodeJS.Timeout | null;
|
|
2258
2304
|
completionSeen: Map<string, number>;
|
|
2259
|
-
/**
|
|
2260
|
-
completedResults?: Map<string, { seenAt: number; completion: WaitCompletion }>;
|
|
2305
|
+
/** Session-owned terminal result payloads observed by the result watcher, keyed by run id and pruned by the completion TTL. */
|
|
2306
|
+
completedResults?: Map<string, { sessionId: string; seenAt: number; completion: WaitCompletion }>;
|
|
2261
2307
|
watcher: FSWatcher | null;
|
|
2262
2308
|
watcherRestartTimer: ReturnType<typeof setTimeout> | null;
|
|
2263
2309
|
resultFileCoalescer: {
|
|
@@ -2360,6 +2406,8 @@ export interface RunSyncOptions {
|
|
|
2360
2406
|
unknownAgentDiagnosticContext?: import("../agents/agents.ts").UnknownAgentDiagnosticContext;
|
|
2361
2407
|
/** Session factory for the in-process child; defaults to the process-wide factory. */
|
|
2362
2408
|
childSessionFactory?: import("../runs/shared/child-session.ts").ChildSessionFactory;
|
|
2409
|
+
/** Invoking parent registry inherited only by its local foreground launch. */
|
|
2410
|
+
parentProviderRegistry?: import("../runs/shared/child-session.ts").ParentProviderRegistry;
|
|
2363
2411
|
/** The launching executor's own child runtime when it is itself an in-process child. */
|
|
2364
2412
|
childRuntime?: import("../runs/shared/child-runtime-config.ts").ChildRuntimeConfig;
|
|
2365
2413
|
/** Fires once the child session exists and can be steered. */
|
|
@@ -2371,6 +2419,10 @@ export interface RunSyncOptions {
|
|
|
2371
2419
|
/** Resolved launch context for this child. */
|
|
2372
2420
|
context?: "fresh" | "fork";
|
|
2373
2421
|
cwd?: string;
|
|
2422
|
+
/** Resolved pane-native saved-machine placement. */
|
|
2423
|
+
machine?: HerdrMachineReference;
|
|
2424
|
+
/** Explicit read override resolved by the remote ambient agent profile. */
|
|
2425
|
+
remoteReads?: string[] | false;
|
|
2374
2426
|
/** Original cwd input retained for launch diagnostics. */
|
|
2375
2427
|
requestedCwd?: string;
|
|
2376
2428
|
signal?: AbortSignal;
|
|
@@ -2431,6 +2483,7 @@ export interface RunSyncOptions {
|
|
|
2431
2483
|
/** Override the agent's default thinking level for this run */
|
|
2432
2484
|
thinkingOverride?: AgentConfig["thinking"];
|
|
2433
2485
|
thinkingCeiling?: ThinkingLevel;
|
|
2486
|
+
requiredExtensions?: RequiredChildExtensionSnapshot;
|
|
2434
2487
|
extensionBindings?: ExtensionBindings;
|
|
2435
2488
|
/** Package-internal one-use authorization for one foreground workflow child. */
|
|
2436
2489
|
workflowChildPermitLaunch?: WorkflowChildPermitContext;
|
|
@@ -2443,7 +2496,7 @@ export interface RunSyncOptions {
|
|
|
2443
2496
|
runtimeSnapshotHost?: import("../runs/shared/mcp-direct-tool-allowlist.ts").McpRuntimeSnapshotHost;
|
|
2444
2497
|
/** Builtin tool names the host runtime provides; used to intersect agent-declared tools. */
|
|
2445
2498
|
hostAvailableBuiltins?: readonly string[];
|
|
2446
|
-
/** Optional subagent model-scope enforcement
|
|
2499
|
+
/** Optional subagent model-scope enforcement. */
|
|
2447
2500
|
modelScope?: ModelScopeRule | ModelScopeRule[];
|
|
2448
2501
|
/** Skills to make available (overrides agent default if provided) */
|
|
2449
2502
|
skills?: string[];
|
|
@@ -2505,11 +2558,6 @@ export interface ScheduledRunsConfig {
|
|
|
2505
2558
|
storeRoot?: string;
|
|
2506
2559
|
}
|
|
2507
2560
|
|
|
2508
|
-
export interface ModelExclusionsConfig {
|
|
2509
|
-
/** Default duration in milliseconds. A lower configured value also shortens active cached exclusions. */
|
|
2510
|
-
defaultTtlMs?: number;
|
|
2511
|
-
}
|
|
2512
|
-
|
|
2513
2561
|
export type FleetViewPlacement = "aboveEditor" | "belowEditor";
|
|
2514
2562
|
|
|
2515
2563
|
export const FLEET_KEYBINDING_ACTIONS = [
|
|
@@ -2572,8 +2620,6 @@ export interface ExtensionConfig {
|
|
|
2572
2620
|
fleetKeybindings?: FleetKeybindingsConfig;
|
|
2573
2621
|
/** Show the under-editor async runs widget. Defaults to true, including when FleetView is enabled. */
|
|
2574
2622
|
asyncWidget?: boolean;
|
|
2575
|
-
/** Configure the process-wide TTL policy for persisted model exclusions. */
|
|
2576
|
-
modelExclusions?: ModelExclusionsConfig;
|
|
2577
2623
|
/** Exact provider/model candidates mapped to operator-declared equivalent response IDs. Empty arrays add no accepted IDs. */
|
|
2578
2624
|
modelResponseAliases?: Record<string, string[]>;
|
|
2579
2625
|
/** Tool description variant registered for the parent-facing subagent tool. Defaults to split metadata. */
|
|
@@ -2618,6 +2664,12 @@ export interface ExtensionConfig {
|
|
|
2618
2664
|
* are rejected with an error.
|
|
2619
2665
|
*/
|
|
2620
2666
|
toolTimeoutMs?: number;
|
|
2667
|
+
/**
|
|
2668
|
+
* Global default for the async single-agent `checkpointBeforeDeadlineMs` launch option: the runner requests that
|
|
2669
|
+
* the child checkpoint and stop this many milliseconds before its run deadline (best-effort). The call param wins; values that
|
|
2670
|
+
* leave no run time before the checkpoint disarm it.
|
|
2671
|
+
*/
|
|
2672
|
+
checkpointBeforeDeadlineMs?: number;
|
|
2621
2673
|
control?: ControlConfig;
|
|
2622
2674
|
completionBatch?: CompletionBatchConfig;
|
|
2623
2675
|
toolBudget?: ToolBudgetConfig;
|
|
@@ -25,7 +25,6 @@ import { resolveAsyncStatusChild } from "../runs/shared/child-identity.ts";
|
|
|
25
25
|
import { readStatus } from "../shared/utils.ts";
|
|
26
26
|
import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
|
|
27
27
|
import { readWorkflowReceipt } from "../workflows/workflow-receipt.ts";
|
|
28
|
-
import { FLEET_OPEN_SHORTCUT } from "../shared/shortcuts.ts";
|
|
29
28
|
import type { SlashSubagentResponse, SlashSubagentUpdate } from "./slash-bridge.ts";
|
|
30
29
|
import { registerPromptWorkflowCommands } from "./prompt-workflows.ts";
|
|
31
30
|
import { openSubagentsAdmin } from "./subagents-admin.ts";
|
|
@@ -976,11 +975,6 @@ export function registerSlashCommands(
|
|
|
976
975
|
handler: async (_args, ctx) => showFleet(ctx),
|
|
977
976
|
});
|
|
978
977
|
|
|
979
|
-
pi.registerShortcut(FLEET_OPEN_SHORTCUT, {
|
|
980
|
-
description: "Open subagent fleet inspector",
|
|
981
|
-
handler: async (ctx) => showFleet(ctx),
|
|
982
|
-
});
|
|
983
|
-
|
|
984
978
|
const detachForegroundRun = (args: string, ctx: ExtensionContext): void => {
|
|
985
979
|
const id = args.trim();
|
|
986
980
|
let control: ReturnType<typeof selectForegroundDetachControl>;
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
type BuiltinAgentOverrideBase,
|
|
12
12
|
} from "../agents/agents.ts";
|
|
13
13
|
import { serializeAgent } from "../agents/agent-serializer.ts";
|
|
14
|
+
import { mergeRuntimeAgents, type RuntimeAgentOwner } from "../agents/runtime-agent-registry.ts";
|
|
14
15
|
import { editableAgentConfig, preservedAgentFrontmatterFields } from "../agents/agent-management.ts";
|
|
15
16
|
import { findModelInfo, getSupportedThinkingLevels, toModelInfo } from "../shared/model-info.ts";
|
|
16
17
|
import { SelectorComponent, type SelectorItem, type SelectorResult } from "./selector.ts";
|
|
@@ -28,11 +29,13 @@ function sourceRank(source: AgentConfig["source"]): number {
|
|
|
28
29
|
return 3;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
function allVisibleAgents(cwd: string): AgentConfig[] {
|
|
32
|
+
function allVisibleAgents(pi: RuntimeAgentOwner, cwd: string): AgentConfig[] {
|
|
32
33
|
const d = discoverAgentsAll(cwd);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
const allConfigured = [...d.project, ...d.user, ...d.package, ...d.builtin];
|
|
35
|
+
const visibleConfigured = allConfigured.filter((agent) => !agent.disabled);
|
|
36
|
+
// Disabled definitions remain in collision checks even though the panel hides them.
|
|
37
|
+
const agents = mergeRuntimeAgents(pi, { agents: visibleConfigured }, allConfigured).agents;
|
|
38
|
+
return agents.sort((a, b) => a.name.localeCompare(b.name) || sourceRank(a.source) - sourceRank(b.source));
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
function agentLabel(agent: AgentConfig): string {
|
|
@@ -91,7 +94,6 @@ async function liveAvailableModels(ctx: ExtensionContext) {
|
|
|
91
94
|
function buildBuiltinBase(agent: AgentConfig): BuiltinAgentOverrideBase {
|
|
92
95
|
return {
|
|
93
96
|
...(agent.model !== undefined ? { model: agent.model } : {}),
|
|
94
|
-
...(agent.fallbackModels !== undefined ? { fallbackModels: [...agent.fallbackModels] } : {}),
|
|
95
97
|
...(agent.thinking !== undefined ? { thinking: agent.thinking } : {}),
|
|
96
98
|
systemPromptMode: agent.systemPromptMode,
|
|
97
99
|
inheritProjectContext: agent.inheritProjectContext,
|
|
@@ -146,6 +148,9 @@ function isReadOnlyExtraAgent(agent: AgentConfig): boolean {
|
|
|
146
148
|
}
|
|
147
149
|
|
|
148
150
|
function readOnlyAgentMessage(agent: AgentConfig, field: EditableOverrideField): string | undefined {
|
|
151
|
+
if (agent.source === "runtime") {
|
|
152
|
+
return `Cannot update '${agent.name}' ${field} because that agent is runtime-registered by an extension; edit its source definition instead.`;
|
|
153
|
+
}
|
|
149
154
|
if (agent.source === "package") {
|
|
150
155
|
return `Cannot update '${agent.name}' ${field} because that field is owned by its read-only package definition.`;
|
|
151
156
|
}
|
|
@@ -154,8 +159,8 @@ function readOnlyAgentMessage(agent: AgentConfig, field: EditableOverrideField):
|
|
|
154
159
|
: undefined;
|
|
155
160
|
}
|
|
156
161
|
|
|
157
|
-
async function selectAgent(ctx: ExtensionContext, args: string): Promise<AgentSelection> {
|
|
158
|
-
const agents = allVisibleAgents(ctx.cwd);
|
|
162
|
+
async function selectAgent(pi: RuntimeAgentOwner, ctx: ExtensionContext, args: string): Promise<AgentSelection> {
|
|
163
|
+
const agents = allVisibleAgents(pi, ctx.cwd);
|
|
159
164
|
const requestedName = args.trim().split(/\s+/)[0] ?? "";
|
|
160
165
|
if (agents.length === 0) return { kind: "not-found", agents, requestedName: requestedName || undefined };
|
|
161
166
|
|
|
@@ -189,7 +194,6 @@ function metadataFor(agent: AgentConfig): string {
|
|
|
189
194
|
lines.push(`Package: ${agent.packageName}`);
|
|
190
195
|
}
|
|
191
196
|
lines.push(`Model: ${agent.model ?? "default / inherit"}`);
|
|
192
|
-
if (agent.fallbackModels?.length) lines.push(`Fallback models: ${agent.fallbackModels.join(", ")}`);
|
|
193
197
|
if (agent.thinking !== undefined) lines.push(`Thinking: ${agent.thinking === false ? "off" : agent.thinking}`);
|
|
194
198
|
if (tools.length) lines.push(`Tools: ${tools.join(", ")}`);
|
|
195
199
|
if (agent.excludeTools?.length) lines.push(`Excluded tools: ${agent.excludeTools.join(", ")}`);
|
|
@@ -390,7 +394,7 @@ async function editSystemPrompt(ctx: ExtensionContext, agent: AgentConfig): Prom
|
|
|
390
394
|
}
|
|
391
395
|
|
|
392
396
|
export async function openSubagentsAdmin(pi: ExtensionAPI, ctx: ExtensionContext, args = ""): Promise<void> {
|
|
393
|
-
const selection = await selectAgent(ctx, args);
|
|
397
|
+
const selection = await selectAgent(pi, ctx, args);
|
|
394
398
|
if (selection.kind === "cancelled") return;
|
|
395
399
|
if (selection.kind === "ambiguous") {
|
|
396
400
|
sendAdminMessage(pi, `Subagent '${selection.requestedName}' is ambiguous. Choose a scope in interactive mode:\n${selection.matches.map((agent) => `- ${agent.source}: ${agent.filePath}`).join("\n")}`);
|