pi-subagents 0.67.0 → 0.68.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 +70 -0
- package/README.md +1 -1
- package/docs/agents.md +37 -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 +15 -12
- package/docs/watchdog.md +10 -12
- package/docs/workflows.md +11 -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 +4 -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 +184 -71
- package/src/agents/chain-serializer.ts +5 -0
- package/src/agents/runtime-agent-registry.ts +7 -6
- 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 +16 -5
- package/src/extension/tool-description.ts +8 -7
- 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 +396 -275
- 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 +91 -218
- package/src/runs/foreground/foreground-history.ts +2 -1
- package/src/runs/foreground/subagent-executor.ts +266 -80
- package/src/runs/shared/acceptance.ts +34 -10
- 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 +3 -3
- 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 +70 -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 +42 -3
- 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
|
@@ -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 =
|
|
@@ -1187,10 +1187,13 @@ export interface LaunchResolvedChildExtensions {
|
|
|
1187
1187
|
disableAmbientExtensions: boolean;
|
|
1188
1188
|
runtime: string[];
|
|
1189
1189
|
configured: string[];
|
|
1190
|
+
/** Bounded host-supplied identities; paths are intentionally not exposed. */
|
|
1191
|
+
required: string[];
|
|
1190
1192
|
effective: string[];
|
|
1191
1193
|
omitted: {
|
|
1192
1194
|
runtime: number;
|
|
1193
1195
|
configured: number;
|
|
1196
|
+
required: number;
|
|
1194
1197
|
effective: number;
|
|
1195
1198
|
};
|
|
1196
1199
|
}
|
|
@@ -1261,16 +1264,16 @@ export interface SingleResult {
|
|
|
1261
1264
|
messages?: Message[];
|
|
1262
1265
|
usage: Usage;
|
|
1263
1266
|
model?: string;
|
|
1267
|
+
/** Authoritative before/after Git evidence captured by a pane-native remote machine. */
|
|
1268
|
+
nativeMachine?: { provider: "herdr"; machineId: string; initialGit?: HerdrRemoteGitStatus; finalGit?: HerdrRemoteGitStatus };
|
|
1264
1269
|
/** Effective thinking level used by this foreground child, when known. */
|
|
1265
1270
|
thinking?: string;
|
|
1266
|
-
|
|
1267
|
-
modelAttempts?: ModelAttempt[];
|
|
1271
|
+
requestedModel?: string;
|
|
1268
1272
|
controlEvents?: ControlEvent[];
|
|
1269
1273
|
error?: string;
|
|
1270
1274
|
/**
|
|
1271
1275
|
* 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
|
|
1276
|
+
* context window. Callers should treat this as
|
|
1274
1277
|
* a signal to reduce input size or re-decompose the task.
|
|
1275
1278
|
*/
|
|
1276
1279
|
contextOverflow?: boolean;
|
|
@@ -1381,10 +1384,11 @@ export interface AgentCapabilityRow {
|
|
|
1381
1384
|
executable: boolean;
|
|
1382
1385
|
restrictionSources?: string[];
|
|
1383
1386
|
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"] };
|
|
1387
|
+
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
1388
|
tools: { ambient: boolean; names: string[]; excludeTools?: string[]; mcpDirectTools: string[]; mutationTools?: string[] };
|
|
1386
|
-
model?: { value?: string;
|
|
1389
|
+
model?: { value?: string; thinking?: string | false };
|
|
1387
1390
|
execution?: { defaultAsync?: boolean; timeoutMs?: number };
|
|
1391
|
+
acceptance?: { policy?: AcceptanceInput; role?: AcceptanceRole };
|
|
1388
1392
|
output?: { path?: string; mode?: OutputMode };
|
|
1389
1393
|
extensions?: { names?: string[]; subagentOnly?: string[]; skills?: string[] };
|
|
1390
1394
|
}
|
|
@@ -1411,6 +1415,12 @@ export interface Details {
|
|
|
1411
1415
|
timedOut: true;
|
|
1412
1416
|
activeRunIds: string[];
|
|
1413
1417
|
activeProviderItems: Array<{ provider: string; id: string }>;
|
|
1418
|
+
} | {
|
|
1419
|
+
/** Non-terminal internal auto-drain yield; tracked work remains active. */
|
|
1420
|
+
reason: "supervisor_request";
|
|
1421
|
+
timedOut: false;
|
|
1422
|
+
activeRunIds: string[];
|
|
1423
|
+
activeProviderItems: Array<{ provider: string; id: string }>;
|
|
1414
1424
|
};
|
|
1415
1425
|
controlEvents?: ControlEvent[];
|
|
1416
1426
|
steering?: SteerActionResult;
|
|
@@ -1472,6 +1482,8 @@ export interface Details {
|
|
|
1472
1482
|
mission?: MissionRecord;
|
|
1473
1483
|
workflow?: {
|
|
1474
1484
|
value?: unknown;
|
|
1485
|
+
args?: Record<string, unknown>;
|
|
1486
|
+
argsDigest?: string;
|
|
1475
1487
|
resource?: WorkflowResourceProvenance;
|
|
1476
1488
|
preflightWarnings?: string[];
|
|
1477
1489
|
trace: Array<{
|
|
@@ -1707,6 +1719,26 @@ export type AgentRunnerConfig =
|
|
|
1707
1719
|
|
|
1708
1720
|
export type ExternalCliCapabilityNarrowing = Partial<Record<"steer" | "resume" | "structuredOutput" | "toolEvents" | "supervisor" | "forkContext" | "extensionBindings", false>>;
|
|
1709
1721
|
|
|
1722
|
+
export interface HerdrRemoteGitStatus {
|
|
1723
|
+
head?: string;
|
|
1724
|
+
branch?: string;
|
|
1725
|
+
dirty?: boolean;
|
|
1726
|
+
}
|
|
1727
|
+
|
|
1728
|
+
/** A Herdr saved SSH machine resolved for one launch. `cwd` is the directory on that machine. */
|
|
1729
|
+
export interface HerdrMachineReference {
|
|
1730
|
+
provider: "herdr";
|
|
1731
|
+
id: string;
|
|
1732
|
+
label?: string;
|
|
1733
|
+
target: string;
|
|
1734
|
+
session?: string;
|
|
1735
|
+
cwd: string;
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
export interface ExternalCliMachineStatus extends HerdrMachineReference {
|
|
1739
|
+
remoteGit?: HerdrRemoteGitStatus;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1710
1742
|
export interface ExternalCliCapabilities {
|
|
1711
1743
|
stop: true;
|
|
1712
1744
|
steer: false;
|
|
@@ -1721,6 +1753,7 @@ export interface ExternalCliCapabilities {
|
|
|
1721
1753
|
export interface ExternalCliReceiptMetadata {
|
|
1722
1754
|
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
1755
|
capabilities: ExternalCliCapabilities;
|
|
1756
|
+
machine?: ExternalCliMachineStatus;
|
|
1724
1757
|
safety?:
|
|
1725
1758
|
| { sandbox: "read-only"; approvalPolicy: "never"; ephemeral: true }
|
|
1726
1759
|
| { access: "workspace-write"; sandbox: "workspace-write"; approvalPolicy: "never"; ephemeral: true }
|
|
@@ -1745,6 +1778,7 @@ export interface ExternalCliRunnerStatus {
|
|
|
1745
1778
|
capabilities: ExternalCliCapabilities;
|
|
1746
1779
|
unsupportedReasons: Record<Exclude<keyof ExternalCliCapabilities, "stop">, string>;
|
|
1747
1780
|
nonResumableReason: string;
|
|
1781
|
+
machine?: HerdrMachineReference;
|
|
1748
1782
|
}
|
|
1749
1783
|
|
|
1750
1784
|
export interface ExternalJobRunnerStatus {
|
|
@@ -1796,6 +1830,7 @@ export interface ExternalProcessStatus {
|
|
|
1796
1830
|
stderrBytes?: number;
|
|
1797
1831
|
stdoutTruncated?: boolean;
|
|
1798
1832
|
stderrTruncated?: boolean;
|
|
1833
|
+
machine?: ExternalCliMachineStatus;
|
|
1799
1834
|
}
|
|
1800
1835
|
|
|
1801
1836
|
export interface AsyncStatus {
|
|
@@ -1928,8 +1963,7 @@ export interface AsyncStatus {
|
|
|
1928
1963
|
thinking?: string;
|
|
1929
1964
|
contextLimit?: number;
|
|
1930
1965
|
thinkingCeiling?: ThinkingLevel;
|
|
1931
|
-
|
|
1932
|
-
modelAttempts?: ModelAttempt[];
|
|
1966
|
+
requestedModel?: string;
|
|
1933
1967
|
/** True when the child input exceeded the model context window. */
|
|
1934
1968
|
contextOverflow?: boolean;
|
|
1935
1969
|
totalCost?: CostSummary;
|
|
@@ -2070,7 +2104,7 @@ export interface ForegroundResumeChild {
|
|
|
2070
2104
|
/** Private bounded launch fields needed to preserve the child contract on resume. */
|
|
2071
2105
|
resumeContract?: {
|
|
2072
2106
|
modelResponseAliases?: Record<string, string[]>;
|
|
2073
|
-
outputSchema?: JsonSchemaObject;
|
|
2107
|
+
outputSchema?: JsonSchemaObject | false;
|
|
2074
2108
|
agentContract?: AgentContract;
|
|
2075
2109
|
acceptance?: AcceptanceInput;
|
|
2076
2110
|
output?: string | boolean;
|
|
@@ -2079,6 +2113,7 @@ export interface ForegroundResumeChild {
|
|
|
2079
2113
|
launchContractDigest?: string;
|
|
2080
2114
|
/** Private retained launch authority. Never project into status or result output. */
|
|
2081
2115
|
extensionBindings?: ExtensionBindings;
|
|
2116
|
+
requiredExtensions?: RequiredChildExtensionSnapshot;
|
|
2082
2117
|
launchResolvedExtensions?: LaunchResolvedChildExtensions;
|
|
2083
2118
|
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensions;
|
|
2084
2119
|
execution?: ExecutionProjection;
|
|
@@ -2256,8 +2291,8 @@ export interface SubagentState {
|
|
|
2256
2291
|
lastUiContext: ExtensionContext | null;
|
|
2257
2292
|
poller: NodeJS.Timeout | null;
|
|
2258
2293
|
completionSeen: Map<string, number>;
|
|
2259
|
-
/**
|
|
2260
|
-
completedResults?: Map<string, { seenAt: number; completion: WaitCompletion }>;
|
|
2294
|
+
/** Session-owned terminal result payloads observed by the result watcher, keyed by run id and pruned by the completion TTL. */
|
|
2295
|
+
completedResults?: Map<string, { sessionId: string; seenAt: number; completion: WaitCompletion }>;
|
|
2261
2296
|
watcher: FSWatcher | null;
|
|
2262
2297
|
watcherRestartTimer: ReturnType<typeof setTimeout> | null;
|
|
2263
2298
|
resultFileCoalescer: {
|
|
@@ -2360,6 +2395,8 @@ export interface RunSyncOptions {
|
|
|
2360
2395
|
unknownAgentDiagnosticContext?: import("../agents/agents.ts").UnknownAgentDiagnosticContext;
|
|
2361
2396
|
/** Session factory for the in-process child; defaults to the process-wide factory. */
|
|
2362
2397
|
childSessionFactory?: import("../runs/shared/child-session.ts").ChildSessionFactory;
|
|
2398
|
+
/** Invoking parent registry inherited only by its local foreground launch. */
|
|
2399
|
+
parentProviderRegistry?: import("../runs/shared/child-session.ts").ParentProviderRegistry;
|
|
2363
2400
|
/** The launching executor's own child runtime when it is itself an in-process child. */
|
|
2364
2401
|
childRuntime?: import("../runs/shared/child-runtime-config.ts").ChildRuntimeConfig;
|
|
2365
2402
|
/** Fires once the child session exists and can be steered. */
|
|
@@ -2371,6 +2408,10 @@ export interface RunSyncOptions {
|
|
|
2371
2408
|
/** Resolved launch context for this child. */
|
|
2372
2409
|
context?: "fresh" | "fork";
|
|
2373
2410
|
cwd?: string;
|
|
2411
|
+
/** Resolved pane-native saved-machine placement. */
|
|
2412
|
+
machine?: HerdrMachineReference;
|
|
2413
|
+
/** Explicit read override resolved by the remote ambient agent profile. */
|
|
2414
|
+
remoteReads?: string[] | false;
|
|
2374
2415
|
/** Original cwd input retained for launch diagnostics. */
|
|
2375
2416
|
requestedCwd?: string;
|
|
2376
2417
|
signal?: AbortSignal;
|
|
@@ -2431,6 +2472,7 @@ export interface RunSyncOptions {
|
|
|
2431
2472
|
/** Override the agent's default thinking level for this run */
|
|
2432
2473
|
thinkingOverride?: AgentConfig["thinking"];
|
|
2433
2474
|
thinkingCeiling?: ThinkingLevel;
|
|
2475
|
+
requiredExtensions?: RequiredChildExtensionSnapshot;
|
|
2434
2476
|
extensionBindings?: ExtensionBindings;
|
|
2435
2477
|
/** Package-internal one-use authorization for one foreground workflow child. */
|
|
2436
2478
|
workflowChildPermitLaunch?: WorkflowChildPermitContext;
|
|
@@ -2443,7 +2485,7 @@ export interface RunSyncOptions {
|
|
|
2443
2485
|
runtimeSnapshotHost?: import("../runs/shared/mcp-direct-tool-allowlist.ts").McpRuntimeSnapshotHost;
|
|
2444
2486
|
/** Builtin tool names the host runtime provides; used to intersect agent-declared tools. */
|
|
2445
2487
|
hostAvailableBuiltins?: readonly string[];
|
|
2446
|
-
/** Optional subagent model-scope enforcement
|
|
2488
|
+
/** Optional subagent model-scope enforcement. */
|
|
2447
2489
|
modelScope?: ModelScopeRule | ModelScopeRule[];
|
|
2448
2490
|
/** Skills to make available (overrides agent default if provided) */
|
|
2449
2491
|
skills?: string[];
|
|
@@ -2505,11 +2547,6 @@ export interface ScheduledRunsConfig {
|
|
|
2505
2547
|
storeRoot?: string;
|
|
2506
2548
|
}
|
|
2507
2549
|
|
|
2508
|
-
export interface ModelExclusionsConfig {
|
|
2509
|
-
/** Default duration in milliseconds. A lower configured value also shortens active cached exclusions. */
|
|
2510
|
-
defaultTtlMs?: number;
|
|
2511
|
-
}
|
|
2512
|
-
|
|
2513
2550
|
export type FleetViewPlacement = "aboveEditor" | "belowEditor";
|
|
2514
2551
|
|
|
2515
2552
|
export const FLEET_KEYBINDING_ACTIONS = [
|
|
@@ -2572,8 +2609,6 @@ export interface ExtensionConfig {
|
|
|
2572
2609
|
fleetKeybindings?: FleetKeybindingsConfig;
|
|
2573
2610
|
/** Show the under-editor async runs widget. Defaults to true, including when FleetView is enabled. */
|
|
2574
2611
|
asyncWidget?: boolean;
|
|
2575
|
-
/** Configure the process-wide TTL policy for persisted model exclusions. */
|
|
2576
|
-
modelExclusions?: ModelExclusionsConfig;
|
|
2577
2612
|
/** Exact provider/model candidates mapped to operator-declared equivalent response IDs. Empty arrays add no accepted IDs. */
|
|
2578
2613
|
modelResponseAliases?: Record<string, string[]>;
|
|
2579
2614
|
/** Tool description variant registered for the parent-facing subagent tool. Defaults to split metadata. */
|
|
@@ -2618,6 +2653,12 @@ export interface ExtensionConfig {
|
|
|
2618
2653
|
* are rejected with an error.
|
|
2619
2654
|
*/
|
|
2620
2655
|
toolTimeoutMs?: number;
|
|
2656
|
+
/**
|
|
2657
|
+
* Global default for the async single-agent `checkpointBeforeDeadlineMs` launch option: the runner requests that
|
|
2658
|
+
* the child checkpoint and stop this many milliseconds before its run deadline (best-effort). The call param wins; values that
|
|
2659
|
+
* leave no run time before the checkpoint disarm it.
|
|
2660
|
+
*/
|
|
2661
|
+
checkpointBeforeDeadlineMs?: number;
|
|
2621
2662
|
control?: ControlConfig;
|
|
2622
2663
|
completionBatch?: CompletionBatchConfig;
|
|
2623
2664
|
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")}`);
|
package/src/tui/render.ts
CHANGED
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
WIDGET_KEY,
|
|
27
27
|
} from "../shared/types.ts";
|
|
28
28
|
import { previewDisplayText, sanitizeDisplayText, truncateDisplayText } from "../shared/display-text.ts";
|
|
29
|
-
import {
|
|
29
|
+
import { formatShortcutLabel } from "../shared/shortcuts.ts";
|
|
30
30
|
import { formatContextUsage, formatTokens, formatUsage, formatDuration, formatModelThinking, formatToolCall, formatTokenUsage, shortenPath } from "../shared/formatters.ts";
|
|
31
31
|
import { getDisplayItems, getSingleResultOutput, PROMPT_REDACTED } from "../shared/utils.ts";
|
|
32
32
|
import { flatToLogicalStepIndex } from "../runs/background/parallel-groups.ts";
|
|
@@ -95,11 +95,11 @@ function liveDetailKeyText(): string {
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
export function liveDetailHintText(): string {
|
|
98
|
-
return `Press ${liveDetailKeyText()} for live detail
|
|
98
|
+
return `Press ${liveDetailKeyText()} for live detail`;
|
|
99
99
|
}
|
|
100
100
|
|
|
101
101
|
function workflowDetailHintText(): string {
|
|
102
|
-
return `Press ${liveDetailKeyText()} for details
|
|
102
|
+
return `Press ${liveDetailKeyText()} for details`;
|
|
103
103
|
}
|
|
104
104
|
|
|
105
105
|
function foregroundSingleHintText(shortcut?: string): string {
|
|
@@ -2545,6 +2545,10 @@ function buildSingleLineWidgetLines(jobs: AsyncJobState[], theme: Theme, width:
|
|
|
2545
2545
|
if (counts.failed.length > 0) parts.push(`${counts.failed.length} failed`);
|
|
2546
2546
|
if (counts.stopped.length > 0) parts.push(`${counts.stopped.length} stopped`);
|
|
2547
2547
|
if (counts.paused.length > 0) parts.push(`${counts.paused.length} paused`);
|
|
2548
|
+
for (const status of ["partial", "rejected"] as const) {
|
|
2549
|
+
const count = jobs.filter((job) => job.status === status).length;
|
|
2550
|
+
if (count > 0) parts.push(`${count} ${status}`);
|
|
2551
|
+
}
|
|
2548
2552
|
if (!hasActive && counts.complete.length > 0) parts.push(`${counts.complete.length}/${jobs.length} done`);
|
|
2549
2553
|
return [truncLine(`${theme.fg(hasActive ? "accent" : "dim", glyph)} ${theme.fg(hasActive ? "accent" : "dim", "subagents")} (${parts.join(", ") || `${jobs.length} total`})`, width)];
|
|
2550
2554
|
}
|
|
@@ -2817,6 +2821,7 @@ function buildWidgetComponent(jobs: AsyncJobState[], ui: ExtensionContext["ui"])
|
|
|
2817
2821
|
let cachedExpanded: boolean | undefined;
|
|
2818
2822
|
let cachedLines: string[] | undefined;
|
|
2819
2823
|
let cachedCoverage = "[]";
|
|
2824
|
+
let collapsed = false;
|
|
2820
2825
|
const invalidate = (): void => {
|
|
2821
2826
|
cachedLines = undefined;
|
|
2822
2827
|
resetWidgetLayoutSession();
|
|
@@ -2830,6 +2835,14 @@ function buildWidgetComponent(jobs: AsyncJobState[], ui: ExtensionContext["ui"])
|
|
|
2830
2835
|
};
|
|
2831
2836
|
asyncWidgetUpdates.set(ui, update);
|
|
2832
2837
|
const component = Object.assign(container, {
|
|
2838
|
+
// Only the mouse fields used here, without requiring newer Pi type exports.
|
|
2839
|
+
handleMouse(event: { type: string; button: string; y: number; shift: boolean; alt: boolean; ctrl: boolean }) {
|
|
2840
|
+
if (event.type !== "click" || event.button !== "left" || event.y !== 0) return undefined;
|
|
2841
|
+
if (event.shift || event.alt || event.ctrl) return undefined;
|
|
2842
|
+
collapsed = !collapsed;
|
|
2843
|
+
invalidate();
|
|
2844
|
+
return { handled: true };
|
|
2845
|
+
},
|
|
2833
2846
|
dispose(): void {
|
|
2834
2847
|
if (asyncWidgetUpdates.get(ui) === update) asyncWidgetUpdates.delete(ui);
|
|
2835
2848
|
if (asyncWidgetInvalidations.get(ui) === invalidate) asyncWidgetInvalidations.delete(ui);
|
|
@@ -2872,7 +2885,10 @@ function buildWidgetComponent(jobs: AsyncJobState[], ui: ExtensionContext["ui"])
|
|
|
2872
2885
|
cachedRenderWidth = renderWidth;
|
|
2873
2886
|
cachedFrame = frame;
|
|
2874
2887
|
cachedExpanded = expanded;
|
|
2875
|
-
cachedLines =
|
|
2888
|
+
cachedLines = (collapsed
|
|
2889
|
+
? buildSingleLineWidgetLines(jobs, theme, width, frame)
|
|
2890
|
+
: fitAdaptiveWidgetLines(roots, buildLines, theme, width, expanded, frame, projectionFor)
|
|
2891
|
+
).map((line) => paddedWidgetLine(line, renderWidth));
|
|
2876
2892
|
return cachedLines;
|
|
2877
2893
|
};
|
|
2878
2894
|
return component;
|
|
@@ -3468,9 +3484,6 @@ export function renderSubagentResult(
|
|
|
3468
3484
|
if (r.skillsWarning) {
|
|
3469
3485
|
c.addChild(new Text(fit(theme.fg("warning", `Warning: ${r.skillsWarning}`)), 0, 0));
|
|
3470
3486
|
}
|
|
3471
|
-
if (r.attemptedModels && r.attemptedModels.length > 1) {
|
|
3472
|
-
c.addChild(new Text(fit(theme.fg("dim", `Fallbacks: ${r.attemptedModels.join(" → ")}`)), 0, 0));
|
|
3473
|
-
}
|
|
3474
3487
|
c.addChild(new Text(fit(theme.fg("dim", formatUsage(r.usage, r.model))), 0, 0));
|
|
3475
3488
|
if (r.sessionFile) {
|
|
3476
3489
|
c.addChild(new Text(fit(theme.fg("dim", `Session: ${shortenPath(r.sessionFile)}`)), 0, 0));
|
|
@@ -3647,9 +3660,6 @@ export function renderSubagentResult(
|
|
|
3647
3660
|
if (r.skillsWarning) {
|
|
3648
3661
|
c.addChild(new Text(fit(theme.fg("warning", ` Warning: ${r.skillsWarning}`)), 0, 0));
|
|
3649
3662
|
}
|
|
3650
|
-
if (r.attemptedModels && r.attemptedModels.length > 1) {
|
|
3651
|
-
c.addChild(new Text(fit(theme.fg("dim", ` fallbacks: ${r.attemptedModels.join(" → ")}`)), 0, 0));
|
|
3652
|
-
}
|
|
3653
3663
|
|
|
3654
3664
|
if (rRunning && rProg) {
|
|
3655
3665
|
if (rProg.skills?.length) {
|