pi-subagents 0.64.0 → 0.65.1
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 +65 -0
- package/README.md +2 -2
- package/agents/reviewer.md +1 -1
- package/agents/scout.md +1 -1
- package/docs/agents.md +19 -17
- package/docs/configuration.md +23 -15
- package/docs/extension-api.md +18 -6
- package/docs/missions.md +2 -0
- package/docs/observability.md +10 -12
- package/docs/tool-reference.md +15 -8
- package/docs/watchdog.md +1 -1
- package/docs/workflows.md +13 -3
- package/package.json +5 -4
- package/runner-server-preload.mjs +13 -0
- package/skills/pi-subagents/SKILL.md +2 -1
- package/skills/pi-subagents/references/constraints-and-recipes.md +1 -1
- package/skills/pi-subagents/references/execution-controls.md +7 -3
- package/skills/pi-subagents/references/multi-lane-orchestration.md +2 -0
- package/src/agents/agent-management.ts +47 -15
- package/src/api/capability-ceiling.ts +0 -1
- package/src/api/{pi-args.ts → child-tool-plan.ts} +1 -1
- package/src/api/preflight.ts +7 -4
- package/src/extension/config.ts +4 -2
- package/src/extension/doctor.ts +2 -10
- package/src/extension/fanout-child.ts +9 -11
- package/src/extension/index.ts +58 -7
- package/src/extension/public-execution.ts +14 -0
- package/src/extension/rpc.ts +3 -2
- package/src/extension/schemas.ts +3 -2
- package/src/extension/tool-description.ts +13 -8
- package/src/integrations/pi-web-session-liveness.ts +73 -0
- package/src/intercom/native-supervisor-channel.ts +159 -95
- package/src/intercom/supervisor-ui.ts +244 -0
- package/src/missions/workflow-state.ts +37 -16
- package/src/runs/background/async-execution.ts +51 -25
- package/src/runs/background/async-job-tracker.ts +11 -0
- package/src/runs/background/async-resume.ts +14 -3
- package/src/runs/background/async-retention.ts +9 -0
- package/src/runs/background/control-channel.ts +2 -204
- package/src/runs/background/notify.ts +2 -0
- package/src/runs/background/process-terminal.ts +1 -1
- package/src/runs/background/retained-nested-route-tracker.ts +96 -0
- package/src/runs/background/run-child-session.ts +614 -0
- package/src/runs/background/run-status.ts +0 -1
- package/src/runs/background/runner-aliases.ts +152 -0
- package/src/runs/background/runner-child-sessions.ts +31 -0
- package/src/runs/background/scheduled-runs.ts +18 -4
- package/src/runs/background/subagent-runner.ts +203 -901
- package/src/runs/foreground/async-steering-action.ts +1 -17
- package/src/runs/foreground/execution.ts +204 -378
- package/src/runs/foreground/foreground-control.ts +4 -0
- package/src/runs/foreground/foreground-history.ts +3 -1
- package/src/runs/foreground/prompt-audit.ts +9 -5
- package/src/runs/foreground/subagent-executor.ts +161 -91
- package/src/runs/foreground/workflow-foreground-steering.ts +24 -98
- package/src/runs/shared/abort-recovery.ts +3 -3
- package/src/runs/shared/acceptance.ts +14 -1
- package/src/runs/shared/capability-ceiling.ts +1 -2
- package/src/runs/shared/child-hooks.ts +25 -0
- package/src/runs/shared/child-identity.ts +13 -2
- package/src/runs/shared/child-launch.ts +314 -0
- package/src/runs/shared/child-lifecycle.ts +25 -0
- package/src/runs/shared/child-runtime-config.ts +126 -0
- package/src/runs/shared/child-session.ts +337 -0
- package/src/runs/shared/child-tool-plan.ts +530 -0
- package/src/runs/shared/claude-code-adapter.ts +5 -1
- package/src/runs/shared/completion-guard.ts +1 -1
- package/src/runs/shared/external-cli-preflight.ts +16 -0
- package/src/runs/shared/llm-intent-arbiter.ts +20 -11
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +5 -4
- package/src/runs/shared/model-exclusions.ts +84 -15
- package/src/runs/shared/model-fallback.ts +78 -6
- package/src/runs/shared/nested-events.ts +32 -48
- package/src/runs/shared/nested-path.ts +0 -14
- package/src/runs/shared/orca-progress-tabs.ts +12 -7
- package/src/runs/shared/parallel-utils.ts +1 -2
- package/src/runs/shared/permissions.ts +0 -13
- package/src/runs/shared/process-signal.ts +4 -1
- package/src/runs/shared/run-fanout-budget.ts +0 -13
- package/src/runs/shared/runtime-acknowledged-extensions.ts +0 -27
- package/src/runs/shared/structured-output.ts +17 -4
- package/src/runs/shared/subagent-control.ts +2 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +87 -384
- package/src/runs/shared/tool-availability.ts +18 -62
- package/src/runs/shared/tool-budget.ts +0 -14
- package/src/runs/shared/worktree-cleanup-plan.ts +31 -9
- package/src/runs/shared/worktree.ts +192 -40
- package/src/shared/child-session-name.ts +1 -1
- package/src/shared/jsonl-writer.ts +11 -0
- package/src/shared/model-response-aliases.ts +13 -0
- package/src/shared/thinking-ceiling.ts +0 -6
- package/src/shared/types.ts +63 -28
- package/src/shared/utils.ts +6 -4
- package/src/shared/watch-strategy.ts +2 -0
- package/src/slash/slash-commands.ts +0 -6
- package/src/tui/fleet-status.ts +1 -1
- package/src/tui/fleet.ts +0 -1
- package/src/tui/render.ts +254 -41
- package/src/watchdog/child-status.ts +0 -1
- package/src/watchdog/register-child.ts +12 -12
- package/src/workflows/scripted-workflow.ts +80 -7
- package/src/workflows/workflow-checklist.ts +4 -3
- package/src/runs/shared/child-protocol.ts +0 -415
- package/src/runs/shared/pi-args.ts +0 -1059
- package/src/runs/shared/subagent-startup-retry.ts +0 -116
- package/src/shared/post-exit-stdio-guard.ts +0 -85
|
@@ -8,6 +8,7 @@ export interface DrainableSource {
|
|
|
8
8
|
export interface JsonlWriteStream {
|
|
9
9
|
write(chunk: string): boolean;
|
|
10
10
|
once(event: "drain", listener: () => void): JsonlWriteStream;
|
|
11
|
+
on?(event: "error", listener: (error: Error) => void): JsonlWriteStream;
|
|
11
12
|
end(callback?: () => void): void;
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -50,6 +51,16 @@ export function createJsonlWriter(
|
|
|
50
51
|
let closed = false;
|
|
51
52
|
let bytesWritten = 0;
|
|
52
53
|
const maxBytes = deps.maxBytes ?? DEFAULT_MAX_JSONL_BYTES;
|
|
54
|
+
// The mirror is best effort: a stream that cannot open or write (for example
|
|
55
|
+
// because its directory was removed) must not surface as an uncaught error.
|
|
56
|
+
stream.on?.("error", () => {
|
|
57
|
+
closed = true;
|
|
58
|
+
stream = undefined;
|
|
59
|
+
if (backpressured) {
|
|
60
|
+
backpressured = false;
|
|
61
|
+
source.resume();
|
|
62
|
+
}
|
|
63
|
+
});
|
|
53
64
|
|
|
54
65
|
return {
|
|
55
66
|
writeLine(line: string) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function validateModelResponseAliases(value: unknown, label = "config.modelResponseAliases"): void {
|
|
2
|
+
if (value === undefined) return;
|
|
3
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be a JSON object`);
|
|
4
|
+
for (const [candidate, aliases] of Object.entries(value)) {
|
|
5
|
+
const slash = candidate.indexOf("/");
|
|
6
|
+
if (slash <= 0 || !candidate.slice(0, slash).trim() || !candidate.slice(slash + 1).trim()) {
|
|
7
|
+
throw new Error(`${label} key ${JSON.stringify(candidate)} must be a non-empty provider/model ID`);
|
|
8
|
+
}
|
|
9
|
+
if (!Array.isArray(aliases) || aliases.some((alias) => typeof alias !== "string" || !alias.trim())) {
|
|
10
|
+
throw new Error(`${label}[${JSON.stringify(candidate)}] must be an array of non-empty response ID strings`);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { resolveEffectiveThinking, THINKING_LEVELS, type ThinkingLevel } from "./model-info.ts";
|
|
2
2
|
export type { ThinkingLevel } from "./model-info.ts";
|
|
3
3
|
|
|
4
|
-
export const SUBAGENT_THINKING_CEILING_ENV = "PI_SUBAGENT_THINKING_CEILING";
|
|
5
|
-
|
|
6
4
|
const thinkingLevelRanks = new Map<ThinkingLevel, number>(THINKING_LEVELS.map((level, index) => [level, index]));
|
|
7
5
|
|
|
8
6
|
export function parseThinkingLevel(value: unknown, field = "thinking level"): ThinkingLevel {
|
|
@@ -26,10 +24,6 @@ export function intersectThinkingCeilings(...ceilings: Array<ThinkingLevel | und
|
|
|
26
24
|
return active.reduce((lowest, ceiling) => compareThinkingLevels(ceiling, lowest) < 0 ? ceiling : lowest);
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
export function decodeThinkingCeiling(value: string | undefined): ThinkingLevel | undefined {
|
|
30
|
-
if (value === undefined || value === "") return undefined;
|
|
31
|
-
return parseThinkingLevel(value, "inherited thinking ceiling");
|
|
32
|
-
}
|
|
33
27
|
|
|
34
28
|
export interface ThinkingCeilingCheck {
|
|
35
29
|
model?: string;
|
package/src/shared/types.ts
CHANGED
|
@@ -369,6 +369,7 @@ export interface ControlEvent {
|
|
|
369
369
|
tokens?: number;
|
|
370
370
|
toolCount?: number;
|
|
371
371
|
currentTool?: string;
|
|
372
|
+
toolCallId?: string;
|
|
372
373
|
currentToolDurationMs?: number;
|
|
373
374
|
currentPath?: string;
|
|
374
375
|
elapsedMs?: number;
|
|
@@ -778,6 +779,8 @@ export interface RunFanoutRejection extends RunFanoutBudgetSnapshot {
|
|
|
778
779
|
}
|
|
779
780
|
|
|
780
781
|
export interface SteeringRecoveryDescriptor {
|
|
782
|
+
/** Captured response identity authority; absence means no declared aliases on revival. */
|
|
783
|
+
modelResponseAliases?: Record<string, string[]>;
|
|
781
784
|
version: 1;
|
|
782
785
|
launchContractDigest?: string;
|
|
783
786
|
extensionBindings?: ExtensionBindings;
|
|
@@ -786,6 +789,8 @@ export interface SteeringRecoveryDescriptor {
|
|
|
786
789
|
agentContract?: AgentContract;
|
|
787
790
|
agent: string;
|
|
788
791
|
sessionFile?: string;
|
|
792
|
+
/** Git ref used to allocate managed worktrees for this run. */
|
|
793
|
+
baseRef?: string;
|
|
789
794
|
cwd: string;
|
|
790
795
|
model?: string;
|
|
791
796
|
modelProvider?: string;
|
|
@@ -1159,15 +1164,6 @@ export interface AcceptanceLedger {
|
|
|
1159
1164
|
};
|
|
1160
1165
|
}
|
|
1161
1166
|
|
|
1162
|
-
export interface ProtocolOutputLimit {
|
|
1163
|
-
code: "protocol_output_limit";
|
|
1164
|
-
stream: "stdout" | "stderr";
|
|
1165
|
-
limitBytes: number;
|
|
1166
|
-
observedBytes: number;
|
|
1167
|
-
diagnosticPrefix: string;
|
|
1168
|
-
diagnosticTail: string;
|
|
1169
|
-
}
|
|
1170
|
-
|
|
1171
1167
|
export interface LaunchResolvedChildExtensionsV1 {
|
|
1172
1168
|
version: 1;
|
|
1173
1169
|
/** This is parent-resolved launch intent, not child-runtime acknowledgement that extensions loaded. */
|
|
@@ -1262,7 +1258,6 @@ export interface SingleResult {
|
|
|
1262
1258
|
* a signal to reduce input size or re-decompose the task.
|
|
1263
1259
|
*/
|
|
1264
1260
|
contextOverflow?: boolean;
|
|
1265
|
-
protocolError?: ProtocolOutputLimit;
|
|
1266
1261
|
sessionFile?: string;
|
|
1267
1262
|
skills?: string[];
|
|
1268
1263
|
skillsWarning?: string;
|
|
@@ -1369,7 +1364,7 @@ export interface AgentCapabilityRow {
|
|
|
1369
1364
|
executable: boolean;
|
|
1370
1365
|
restrictionSources?: string[];
|
|
1371
1366
|
aliases?: string[];
|
|
1372
|
-
runner: { type: "pi" } | { type: "external-cli"; adapter?: string; capabilities: ExternalCliCapabilities } | { type: "external-job"; provider: string; available?: boolean; capabilities: ExternalJobRunnerStatus["capabilities"] };
|
|
1367
|
+
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"] };
|
|
1373
1368
|
tools: { ambient: boolean; names: string[]; excludeTools?: string[]; mcpDirectTools: string[]; mutationTools?: string[] };
|
|
1374
1369
|
model?: { value?: string; fallbackModels?: string[]; thinking?: string | false };
|
|
1375
1370
|
execution?: { defaultAsync?: boolean; timeoutMs?: number };
|
|
@@ -2054,6 +2049,7 @@ export interface ForegroundResumeChild {
|
|
|
2054
2049
|
agentContract?: AgentContract;
|
|
2055
2050
|
/** Private bounded launch fields needed to preserve the child contract on resume. */
|
|
2056
2051
|
resumeContract?: {
|
|
2052
|
+
modelResponseAliases?: Record<string, string[]>;
|
|
2057
2053
|
outputSchema?: JsonSchemaObject;
|
|
2058
2054
|
agentContract?: AgentContract;
|
|
2059
2055
|
acceptance?: AcceptanceInput;
|
|
@@ -2107,6 +2103,18 @@ export interface ForegroundChildControl {
|
|
|
2107
2103
|
toolCount?: number;
|
|
2108
2104
|
interrupt?: () => boolean;
|
|
2109
2105
|
detach?: () => boolean;
|
|
2106
|
+
/** Steer the live in-process child session; undefined until the session exists. */
|
|
2107
|
+
steer?: (input: ForegroundSteerInput) => Promise<ForegroundSteerOutcome>;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
export interface ForegroundSteerInput {
|
|
2111
|
+
message: string;
|
|
2112
|
+
mode?: "steer" | "follow_up" | "auto";
|
|
2113
|
+
}
|
|
2114
|
+
|
|
2115
|
+
export interface ForegroundSteerOutcome {
|
|
2116
|
+
state: "delivered" | "queued" | "failed";
|
|
2117
|
+
reason?: string;
|
|
2110
2118
|
}
|
|
2111
2119
|
|
|
2112
2120
|
export interface ForegroundRunControl {
|
|
@@ -2115,8 +2123,6 @@ export interface ForegroundRunControl {
|
|
|
2115
2123
|
parentWorkflowRunId?: string;
|
|
2116
2124
|
/** Stable workflow lane key for this live foreground child. */
|
|
2117
2125
|
workflowKey?: string;
|
|
2118
|
-
/** Private control root used to steer a live workflow-owned child. */
|
|
2119
|
-
workflowSteeringDir?: string;
|
|
2120
2126
|
/** Originating parent session; required for public fleet projection. */
|
|
2121
2127
|
sessionId?: string;
|
|
2122
2128
|
mode: SubagentRunMode;
|
|
@@ -2158,6 +2164,7 @@ export interface ForegroundRunControl {
|
|
|
2158
2164
|
nestedChildren?: NestedRunSummary[];
|
|
2159
2165
|
interrupt?: () => boolean;
|
|
2160
2166
|
detach?: () => boolean;
|
|
2167
|
+
steer?: ForegroundChildControl["steer"];
|
|
2161
2168
|
}
|
|
2162
2169
|
|
|
2163
2170
|
export interface WaitSubscriptionRecord {
|
|
@@ -2197,6 +2204,8 @@ export interface SubagentState {
|
|
|
2197
2204
|
trustedSessionFileRoot?: string;
|
|
2198
2205
|
/** Live async session roots created by this parent executor, keyed by run id. */
|
|
2199
2206
|
liveAsyncSessionRoots?: Map<string, string>;
|
|
2207
|
+
/** Foreground nested routes retained after their direct parent settles, keyed by root run id. */
|
|
2208
|
+
retainedForegroundNestedRoutes?: Map<string, NestedRouteInfo>;
|
|
2200
2209
|
/** Last valid parent session model observed for this session; used when continuation contexts omit ctx.model. */
|
|
2201
2210
|
lastParentModel?: { provider: string; id: string };
|
|
2202
2211
|
subagentInProgress?: boolean;
|
|
@@ -2318,17 +2327,25 @@ export interface SubagentChildStatusEvent {
|
|
|
2318
2327
|
// Execution Options
|
|
2319
2328
|
// ============================================================================
|
|
2320
2329
|
|
|
2330
|
+
/** Live controls for one in-process foreground child session. */
|
|
2331
|
+
export interface ForegroundChildSessionControls {
|
|
2332
|
+
steer: (text: string) => Promise<void>;
|
|
2333
|
+
followUp: (text: string) => Promise<void>;
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2321
2336
|
export interface RunSyncOptions {
|
|
2322
2337
|
/** Exact discovery provenance for an unknown-agent error; omission uses defensive fallback discovery. */
|
|
2323
2338
|
unknownAgentDiagnosticContext?: import("../agents/agents.ts").UnknownAgentDiagnosticContext;
|
|
2339
|
+
/** Session factory for the in-process child; defaults to the process-wide factory. */
|
|
2340
|
+
childSessionFactory?: import("../runs/shared/child-session.ts").ChildSessionFactory;
|
|
2341
|
+
/** The launching executor's own child runtime when it is itself an in-process child. */
|
|
2342
|
+
childRuntime?: import("../runs/shared/child-runtime-config.ts").ChildRuntimeConfig;
|
|
2343
|
+
/** Fires once the child session exists and can be steered. */
|
|
2344
|
+
onChildSession?: (controls: ForegroundChildSessionControls) => void;
|
|
2324
2345
|
/** Opt-in global permission rules; missing tools remain allowed. */
|
|
2325
2346
|
permissions?: import("../runs/shared/permissions.ts").PermissionConfig;
|
|
2326
2347
|
/** Session id of the direct parent session for permission-system ask forwarding. */
|
|
2327
2348
|
parentSessionId?: string;
|
|
2328
|
-
/** Private prompt-runtime steering transport for workflow-owned foreground children. */
|
|
2329
|
-
steerInboxDir?: string;
|
|
2330
|
-
steerCapabilityPath?: string;
|
|
2331
|
-
steerAckDir?: string;
|
|
2332
2349
|
/** Resolved launch context for this child. */
|
|
2333
2350
|
context?: "fresh" | "fork";
|
|
2334
2351
|
cwd?: string;
|
|
@@ -2397,6 +2414,7 @@ export interface RunSyncOptions {
|
|
|
2397
2414
|
workflowChildPermitLaunch?: WorkflowChildPermitContext;
|
|
2398
2415
|
/** Registry models available for heuristic bare-model resolution */
|
|
2399
2416
|
availableModels?: Array<{ provider: string; id: string; fullId: string; contextWindow?: number }>;
|
|
2417
|
+
modelResponseAliases?: Record<string, string[]>;
|
|
2400
2418
|
/** Current parent-session provider to prefer for ambiguous bare model ids */
|
|
2401
2419
|
preferredModelProvider?: string;
|
|
2402
2420
|
/** Parent Pi event host used to snapshot runtime-registered MCP servers before child launch. */
|
|
@@ -2410,6 +2428,7 @@ export interface RunSyncOptions {
|
|
|
2410
2428
|
schemaPath: string;
|
|
2411
2429
|
outputPath: string;
|
|
2412
2430
|
acceptanceReportPath?: string;
|
|
2431
|
+
acceptanceReportRequired?: boolean;
|
|
2413
2432
|
};
|
|
2414
2433
|
agentContract?: AgentContract;
|
|
2415
2434
|
acceptance?: AcceptanceInput;
|
|
@@ -2531,6 +2550,8 @@ export interface ExtensionConfig {
|
|
|
2531
2550
|
asyncWidget?: boolean;
|
|
2532
2551
|
/** Configure the process-wide TTL policy for persisted model exclusions. */
|
|
2533
2552
|
modelExclusions?: ModelExclusionsConfig;
|
|
2553
|
+
/** Exact provider/model candidates mapped to operator-declared equivalent response IDs. Empty arrays add no accepted IDs. */
|
|
2554
|
+
modelResponseAliases?: Record<string, string[]>;
|
|
2534
2555
|
/** Tool description variant registered for the parent-facing subagent tool. Defaults to split metadata. */
|
|
2535
2556
|
toolDescriptionMode?: ToolDescriptionMode;
|
|
2536
2557
|
/** Inline chat rendering for the subagent tool. Defaults to rich. */
|
|
@@ -2765,8 +2786,17 @@ export function normalizeMaxSubagentDepth(value: unknown): number | undefined {
|
|
|
2765
2786
|
return normalizeNonNegativeInteger(value);
|
|
2766
2787
|
}
|
|
2767
2788
|
|
|
2768
|
-
|
|
2769
|
-
|
|
2789
|
+
/** Depth context of the executor's own child runtime, when it runs as an in-process child. */
|
|
2790
|
+
export interface SubagentDepthContext {
|
|
2791
|
+
depth: number;
|
|
2792
|
+
maxDepth?: number;
|
|
2793
|
+
}
|
|
2794
|
+
|
|
2795
|
+
/** Operator override for the top-level parent; children inherit their limit through their runtime config. */
|
|
2796
|
+
export const SUBAGENT_MAX_DEPTH_ENV = "PI_SUBAGENT_MAX_DEPTH";
|
|
2797
|
+
|
|
2798
|
+
export function resolveCurrentMaxSubagentDepth(configMaxDepth?: number, runtime?: SubagentDepthContext): number {
|
|
2799
|
+
return normalizeMaxSubagentDepth(runtime ? runtime.maxDepth : process.env[SUBAGENT_MAX_DEPTH_ENV])
|
|
2770
2800
|
?? normalizeMaxSubagentDepth(configMaxDepth)
|
|
2771
2801
|
?? DEFAULT_SUBAGENT_MAX_DEPTH;
|
|
2772
2802
|
}
|
|
@@ -2777,19 +2807,24 @@ export function resolveChildMaxSubagentDepth(parentMaxDepth: number, agentMaxDep
|
|
|
2777
2807
|
return normalizedAgent === undefined ? normalizedParent : Math.min(normalizedParent, normalizedAgent);
|
|
2778
2808
|
}
|
|
2779
2809
|
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
const
|
|
2783
|
-
|
|
2810
|
+
/** Depth of the executor itself: 0 for a top-level parent, its own child depth otherwise. */
|
|
2811
|
+
export function resolveCurrentSubagentDepth(runtime?: SubagentDepthContext): number {
|
|
2812
|
+
const depth = runtime ? runtime.depth : 0;
|
|
2813
|
+
return Number.isFinite(depth) ? depth : 0;
|
|
2814
|
+
}
|
|
2815
|
+
|
|
2816
|
+
export function checkSubagentDepth(configMaxDepth?: number, runtime?: SubagentDepthContext): { blocked: boolean; depth: number; maxDepth: number } {
|
|
2817
|
+
const depth = resolveCurrentSubagentDepth(runtime);
|
|
2818
|
+
const maxDepth = resolveCurrentMaxSubagentDepth(configMaxDepth, runtime);
|
|
2819
|
+
const blocked = depth >= maxDepth;
|
|
2784
2820
|
return { blocked, depth, maxDepth };
|
|
2785
2821
|
}
|
|
2786
2822
|
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
const nextDepth = Number.isFinite(parentDepth) ? parentDepth + 1 : 1;
|
|
2823
|
+
/** Depth context handed to a child launched by an executor at `runtime` (undefined for a top-level parent). */
|
|
2824
|
+
export function resolveChildDepth(maxDepth?: number, runtime?: SubagentDepthContext): Required<SubagentDepthContext> {
|
|
2790
2825
|
return {
|
|
2791
|
-
|
|
2792
|
-
|
|
2826
|
+
depth: resolveCurrentSubagentDepth(runtime) + 1,
|
|
2827
|
+
maxDepth: normalizeMaxSubagentDepth(maxDepth) ?? resolveCurrentMaxSubagentDepth(undefined, runtime),
|
|
2793
2828
|
};
|
|
2794
2829
|
}
|
|
2795
2830
|
|
package/src/shared/utils.ts
CHANGED
|
@@ -135,6 +135,9 @@ function isNotFoundError(error: unknown): boolean {
|
|
|
135
135
|
* Read async job status from disk (with mtime-based caching)
|
|
136
136
|
*/
|
|
137
137
|
export function readStatus(asyncDir: string): AsyncStatus | null {
|
|
138
|
+
if (Buffer.byteLength(path.basename(asyncDir), "utf-8") > 255) {
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
138
141
|
const statusPath = path.join(asyncDir, "status.json");
|
|
139
142
|
|
|
140
143
|
let stat: fs.Stats;
|
|
@@ -413,10 +416,9 @@ export function compactForegroundDetails(details: Details): Details {
|
|
|
413
416
|
*
|
|
414
417
|
* The completed-compaction helpers above bail out while a child is still
|
|
415
418
|
* `running`, so a long or deeply nested fan-out streams full, unbounded progress on
|
|
416
|
-
* every tick.
|
|
417
|
-
*
|
|
418
|
-
*
|
|
419
|
-
* `protocol_output_limit`.
|
|
419
|
+
* every tick. The parent records every streamed `tool_execution_update` in its
|
|
420
|
+
* transcript and `events.jsonl`, so an unbounded running snapshot grows those
|
|
421
|
+
* artifacts and the live display state without bound.
|
|
420
422
|
*
|
|
421
423
|
* These bound the STREAMED snapshot only. The final returned result keeps the full
|
|
422
424
|
* live progress and message transcript, and every live-display consumer already
|
|
@@ -2,9 +2,11 @@ export type FileWatchPurpose =
|
|
|
2
2
|
| "result-delivery"
|
|
3
3
|
| "supervisor-channel"
|
|
4
4
|
| "async-job-tracker"
|
|
5
|
+
| "retained-nested-route-tracker"
|
|
5
6
|
| "runner-control-inbox"
|
|
6
7
|
| "child-steering-inbox";
|
|
7
8
|
|
|
8
9
|
export function shouldUseNativeFsWatch(_purpose: FileWatchPurpose, platform: NodeJS.Platform = process.platform): boolean {
|
|
10
|
+
if (_purpose === "retained-nested-route-tracker" && platform === "win32") return false;
|
|
9
11
|
return platform !== "darwin";
|
|
10
12
|
}
|
|
@@ -21,7 +21,6 @@ import { formatTokens, shortenPath } from "../shared/formatters.ts";
|
|
|
21
21
|
import { listAsyncRuns, formatAsyncRunProgressLabel, type AsyncRunSummary } from "../runs/background/async-status.ts";
|
|
22
22
|
import { encodeInspectReply, handleInspectRpcArgs, INSPECT_WIDGET_KEY } from "../runs/background/inspect-rpc.ts";
|
|
23
23
|
import { listScheduledRunSummaries } from "../runs/background/scheduled-runs.ts";
|
|
24
|
-
import { SUBAGENT_FANOUT_CHILD_ENV } from "../runs/shared/pi-args.ts";
|
|
25
24
|
import { resolveAsyncStatusChild } from "../runs/shared/child-identity.ts";
|
|
26
25
|
import { readStatus } from "../shared/utils.ts";
|
|
27
26
|
import { getArtifactPaths, getArtifactsDir } from "../shared/artifacts.ts";
|
|
@@ -1030,11 +1029,6 @@ export function registerSlashCommands(
|
|
|
1030
1029
|
return;
|
|
1031
1030
|
}
|
|
1032
1031
|
|
|
1033
|
-
if (process.env[SUBAGENT_FANOUT_CHILD_ENV] === "1") {
|
|
1034
|
-
sendSlashText(pi, "Selector unavailable in child-safe fanout mode. Pass an explicit current-session top-level async run id, for example `/subagents-stop <run-id>` or `subagent({ action: \"stop\", id: \"<run-id>\" })`.");
|
|
1035
|
-
return;
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
1032
|
let targets: StopSelectorTarget[];
|
|
1039
1033
|
try {
|
|
1040
1034
|
targets = discoverStopTargets(ctx, state);
|
package/src/tui/fleet-status.ts
CHANGED
|
@@ -666,7 +666,7 @@ export class SubagentFleetStatus {
|
|
|
666
666
|
const capacity = this.state.activeAsyncCapacity;
|
|
667
667
|
const hasNativeRows = workEntries.some((entry) => !entry.external);
|
|
668
668
|
const showNativeSummary = hasNativeRows || Boolean(capacity?.used);
|
|
669
|
-
const asyncRuns = capacity && showNativeSummary ? `Async runs ${capacity.used}/${capacity.limit || "∞"}` : "";
|
|
669
|
+
const asyncRuns = capacity && showNativeSummary && (capacity.used > 0 || capacity.limit > 0) ? `Async runs ${capacity.used}/${capacity.limit || "∞"}` : "";
|
|
670
670
|
const activeEntries = activeLeafAgentCount(workEntries);
|
|
671
671
|
const noun = workEntries.some((entry) => entry.external) ? "job" : "agent";
|
|
672
672
|
const agents = activeEntries > 0 ? `${activeEntries} active ${noun}${activeEntries === 1 ? "" : "s"}` : "";
|
package/src/tui/fleet.ts
CHANGED
|
@@ -204,7 +204,6 @@ export function collectFleetSnapshot(
|
|
|
204
204
|
if (!control.parentWorkflowRunId
|
|
205
205
|
|| !workflowParentIds.has(control.parentWorkflowRunId)
|
|
206
206
|
|| !belongsToCurrentSession(control.sessionId, state.currentSessionId)
|
|
207
|
-
|| !control.workflowSteeringDir
|
|
208
207
|
|| activeChildCount === 0) continue;
|
|
209
208
|
liveWorkflowForegroundControls.add(control);
|
|
210
209
|
workflowForegroundChildCounts.set(control.parentWorkflowRunId, (workflowForegroundChildCounts.get(control.parentWorkflowRunId) ?? 0) + activeChildCount);
|