pi-subagents 0.38.0 → 0.40.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 +38 -0
- package/README.md +85 -13
- package/agents/worker.md +1 -0
- package/package.json +1 -1
- package/prompts/review-loop.md +1 -1
- package/skills/pi-subagents/SKILL.md +4 -3
- package/skills/pi-subagents/references/execution-controls.md +22 -3
- package/skills/pi-subagents/references/management-authoring-rpc.md +5 -1
- package/skills/pi-subagents/references/prompting-and-roles.md +17 -3
- package/src/agents/agent-management.ts +71 -30
- package/src/agents/agent-serializer.ts +4 -0
- package/src/agents/agents.ts +60 -1
- package/src/api/preflight.ts +16 -12
- package/src/extension/chain-validation.ts +17 -1
- package/src/extension/rpc.ts +2 -0
- package/src/extension/schemas.ts +16 -3
- package/src/extension/tool-description.ts +6 -5
- package/src/intercom/result-intercom.ts +33 -4
- package/src/runs/background/async-execution.ts +63 -16
- package/src/runs/background/async-job-tracker.ts +5 -1
- package/src/runs/background/async-resume.ts +1 -0
- package/src/runs/background/async-status.ts +18 -2
- package/src/runs/background/chain-append.ts +48 -5
- package/src/runs/background/control-channel.ts +60 -0
- package/src/runs/background/notify.ts +26 -4
- package/src/runs/background/result-watcher.ts +20 -3
- package/src/runs/background/run-status.ts +29 -3
- package/src/runs/background/subagent-runner.ts +302 -18
- package/src/runs/foreground/async-stop-action.ts +65 -0
- package/src/runs/foreground/chain-execution.ts +143 -43
- package/src/runs/foreground/execution.ts +384 -202
- package/src/runs/foreground/foreground-control.ts +30 -0
- package/src/runs/foreground/subagent-executor.ts +314 -77
- package/src/runs/shared/capability-ceiling.ts +51 -19
- package/src/runs/shared/chain-outputs.ts +3 -1
- package/src/runs/shared/dynamic-fanout.ts +1 -1
- package/src/runs/shared/nested-events.ts +97 -20
- package/src/runs/shared/parallel-utils.ts +43 -12
- package/src/runs/shared/pi-args.ts +45 -3
- package/src/runs/shared/process-signal.ts +19 -0
- package/src/runs/shared/run-history.ts +45 -9
- package/src/runs/shared/runtime-acknowledged-extensions.ts +71 -0
- package/src/runs/shared/subagent-prompt-runtime.ts +30 -0
- package/src/runs/shared/usage-budget.ts +65 -0
- package/src/runs/shared/workflow-graph.ts +26 -1
- package/src/shared/settings.ts +17 -1
- package/src/shared/types.ts +124 -8
- package/src/shared/utils.ts +12 -1
- package/src/slash/slash-commands.ts +43 -1
- package/src/slash/slash-live-state.ts +5 -3
- package/src/tui/fleet-status.ts +12 -2
- package/src/tui/fleet.ts +181 -8
- package/src/tui/render.ts +4 -2
- package/src/watchdog/register-main.ts +14 -7
- package/src/watchdog/review.ts +4 -3
- package/src/watchdog/runtime.ts +170 -17
- package/src/watchdog/scope.ts +62 -0
- package/src/watchdog/settings.ts +41 -1
- package/src/watchdog/types.ts +10 -0
|
@@ -18,6 +18,8 @@ import {
|
|
|
18
18
|
type AsyncStatus,
|
|
19
19
|
type ChainOutputMap,
|
|
20
20
|
type CostSummary,
|
|
21
|
+
type LaunchResolvedChildExtensionsV1,
|
|
22
|
+
type RuntimeAcknowledgedChildExtensionsV1,
|
|
21
23
|
type ModelAttempt,
|
|
22
24
|
type NestedRouteInfo,
|
|
23
25
|
type NestedRunSummary,
|
|
@@ -25,6 +27,8 @@ import {
|
|
|
25
27
|
type ResolvedTurnBudget,
|
|
26
28
|
type ResolvedToolBudget,
|
|
27
29
|
type SubagentRunMode,
|
|
30
|
+
type SubagentOutputState,
|
|
31
|
+
type UsageBudgetConfig,
|
|
28
32
|
type ToolBudgetState,
|
|
29
33
|
type TurnBudgetState,
|
|
30
34
|
type Usage,
|
|
@@ -35,6 +39,7 @@ import {
|
|
|
35
39
|
DEFAULT_MAX_OUTPUT,
|
|
36
40
|
type MaxOutputConfig,
|
|
37
41
|
SUBAGENT_LIFECYCLE_ARTIFACT_VERSION,
|
|
42
|
+
POLL_INTERVAL_MS,
|
|
38
43
|
truncateOutput,
|
|
39
44
|
getSubagentDepthEnv,
|
|
40
45
|
} from "../../shared/types.ts";
|
|
@@ -49,6 +54,7 @@ import {
|
|
|
49
54
|
import {
|
|
50
55
|
type RunnerSubagentStep as SubagentStep,
|
|
51
56
|
type RunnerStep,
|
|
57
|
+
isCheckpointRunnerStep,
|
|
52
58
|
isDynamicRunnerGroup,
|
|
53
59
|
isParallelGroup,
|
|
54
60
|
flattenSteps,
|
|
@@ -58,9 +64,11 @@ import {
|
|
|
58
64
|
DEFAULT_GLOBAL_CONCURRENCY_LIMIT,
|
|
59
65
|
Semaphore,
|
|
60
66
|
} from "../shared/parallel-utils.ts";
|
|
61
|
-
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
67
|
+
import { applyThinkingSuffix, buildPiArgs, cleanupTempDir, projectLaunchResolvedChildExtensions, resolvePiLaunchToolPlan } from "../shared/pi-args.ts";
|
|
68
|
+
import { readRuntimeAcknowledgedExtensions } from "../shared/runtime-acknowledged-extensions.ts";
|
|
62
69
|
import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/chain-outputs.ts";
|
|
63
70
|
import { createStructuredOutputRuntime, readStructuredOutput } from "../shared/structured-output.ts";
|
|
71
|
+
import { formatProcessSignalError, isUnexplainedProcessSignal } from "../shared/process-signal.ts";
|
|
64
72
|
import { readChildToolDiagnosticError } from "../shared/tool-availability.ts";
|
|
65
73
|
import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
|
|
66
74
|
import { nestedSummaryFromAsyncStatus, projectNestedEvents, resolveNestedAsyncDir, writeNestedEvent } from "../shared/nested-events.ts";
|
|
@@ -106,9 +114,10 @@ import { resolveSubagentIntercomTarget } from "../../intercom/intercom-bridge.ts
|
|
|
106
114
|
import { acceptanceFailureMessage, aggregateAcceptanceReport, buildSkippedAcceptanceLedger, evaluateAcceptance, formatAcceptancePrompt, resolveEffectiveAcceptance, stripAcceptanceReport } from "../shared/acceptance.ts";
|
|
107
115
|
import { attachContractProjections, isAgentContractV1 } from "../shared/agent-contract.ts";
|
|
108
116
|
import { waitForImportedAsyncRoot } from "./chain-root-attachment.ts";
|
|
109
|
-
import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests } from "./chain-append.ts";
|
|
117
|
+
import { appendRunnerStepsToStatus, consumeChainAppendRequests, countPendingChainAppendRequests, statusStepDescription } from "./chain-append.ts";
|
|
110
118
|
import { appendTurnBudgetSystemPrompt, formatTurnBudgetOutput, initialTurnBudgetState, turnBudgetDecision, turnBudgetDeferredNote, turnBudgetDeferredState, turnBudgetExceededMessage, turnBudgetSoftNote, turnBudgetState } from "../shared/turn-budget.ts";
|
|
111
119
|
import { initialToolBudgetState, toolBudgetState } from "../shared/tool-budget.ts";
|
|
120
|
+
import { usageBudgetExceededMessage, usageBudgetState } from "../shared/usage-budget.ts";
|
|
112
121
|
import { formatParallelHandoffError, formatParallelHandoffReference, parallelHandoffPath, writeParallelHandoffGroup } from "../shared/parallel-handoff.ts";
|
|
113
122
|
import { resolveWatchdogConfig } from "../../watchdog/settings.ts";
|
|
114
123
|
import { createBoundedByteTail, createBoundedLineReader, formatProtocolOutputLimit, MAX_CHILD_STDERR_BYTES, projectChildLifecycle, type ChildLifecycleAction, type ProtocolOutputLimit } from "../shared/child-protocol.ts";
|
|
@@ -156,12 +165,15 @@ interface SubagentRunConfig {
|
|
|
156
165
|
deadlineAt?: number;
|
|
157
166
|
turnBudget?: ResolvedTurnBudget;
|
|
158
167
|
toolBudget?: ResolvedToolBudget;
|
|
168
|
+
usageBudget?: UsageBudgetConfig;
|
|
159
169
|
revivalLease?: SessionLeaseRequest;
|
|
160
170
|
revivalLeaseToken?: string;
|
|
161
171
|
/** Global cap on simultaneously-running subagent tasks within this run. */
|
|
162
172
|
globalConcurrencyLimit?: number;
|
|
163
173
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
164
174
|
launchContractDigest?: string;
|
|
175
|
+
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
176
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
165
177
|
runnerProcessInstanceId?: string;
|
|
166
178
|
}
|
|
167
179
|
|
|
@@ -170,7 +182,10 @@ interface StepResult {
|
|
|
170
182
|
context?: "fresh" | "fork";
|
|
171
183
|
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
172
184
|
capabilityAudit?: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit;
|
|
185
|
+
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
186
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
173
187
|
output: string;
|
|
188
|
+
outputState?: SubagentOutputState;
|
|
174
189
|
error?: string;
|
|
175
190
|
protocolError?: ProtocolOutputLimit;
|
|
176
191
|
success: boolean;
|
|
@@ -179,6 +194,7 @@ interface StepResult {
|
|
|
179
194
|
interrupted?: boolean;
|
|
180
195
|
timedOut?: boolean;
|
|
181
196
|
stopped?: boolean;
|
|
197
|
+
processSignal?: string | null;
|
|
182
198
|
turnBudget?: TurnBudgetState;
|
|
183
199
|
turnBudgetExceeded?: boolean;
|
|
184
200
|
wrapUpRequested?: boolean;
|
|
@@ -408,6 +424,7 @@ interface RunPiStreamingResult {
|
|
|
408
424
|
error?: string;
|
|
409
425
|
protocolError?: ProtocolOutputLimit;
|
|
410
426
|
finalOutput: string;
|
|
427
|
+
outputState: SubagentOutputState;
|
|
411
428
|
interrupted?: boolean;
|
|
412
429
|
timedOut?: boolean;
|
|
413
430
|
stopped?: boolean;
|
|
@@ -418,6 +435,7 @@ interface RunPiStreamingResult {
|
|
|
418
435
|
toolBudgetBlocked?: boolean;
|
|
419
436
|
observedMutationAttempt?: boolean;
|
|
420
437
|
watchdog?: ChildWatchdogStateSnapshot;
|
|
438
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
421
439
|
processInstanceId: string;
|
|
422
440
|
processCloseObservedAt?: number;
|
|
423
441
|
processSignal?: string | null;
|
|
@@ -802,7 +820,15 @@ function runPiStreaming(
|
|
|
802
820
|
const stderr = stderrTail.text();
|
|
803
821
|
const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
|
|
804
822
|
const finalError = error ?? assistantError;
|
|
805
|
-
const forcedDrainAfterFinalSuccess = forcedTerminationSignal && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
|
|
823
|
+
const forcedDrainAfterFinalSuccess = Boolean(forcedTerminationSignal || signal) && (cleanTerminalAssistantStopReceived || agentSettledReceived) && !finalError;
|
|
824
|
+
const signalError = isUnexplainedProcessSignal({
|
|
825
|
+
processSignal: signal,
|
|
826
|
+
interrupted,
|
|
827
|
+
timedOut,
|
|
828
|
+
stopped,
|
|
829
|
+
turnBudgetExceeded,
|
|
830
|
+
forcedDrainAfterFinalSuccess,
|
|
831
|
+
}) ? formatProcessSignalError(signal!) : undefined;
|
|
806
832
|
resolve({
|
|
807
833
|
stderr,
|
|
808
834
|
exitCode: timedOut || stopped ? 1 : turnBudgetExceeded ? 1 : interrupted || forcedDrainAfterFinalSuccess ? 0 : forcedTerminationSignal || signal ? (exitCode ?? 1) : exitCode,
|
|
@@ -811,9 +837,10 @@ function runPiStreaming(
|
|
|
811
837
|
toolCount,
|
|
812
838
|
durationMs: Date.now() - startedAt,
|
|
813
839
|
model,
|
|
814
|
-
error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError,
|
|
840
|
+
error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : interrupted || forcedDrainAfterFinalSuccess ? undefined : finalError ?? signalError,
|
|
815
841
|
protocolError,
|
|
816
842
|
finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput,
|
|
843
|
+
outputState: finalOutput.trim() ? "present" : "absent",
|
|
817
844
|
interrupted,
|
|
818
845
|
timedOut,
|
|
819
846
|
stopped,
|
|
@@ -847,7 +874,7 @@ function runPiStreaming(
|
|
|
847
874
|
const stderr = stderrTail.text();
|
|
848
875
|
const finalOutput = getFinalOutput(messages) || rawStdoutTail.text().trim();
|
|
849
876
|
const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
|
|
850
|
-
resolve({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, model, error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput, timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState, processInstanceId });
|
|
877
|
+
resolve({ stderr, exitCode: 1, messages, usage, toolCount, durationMs: Date.now() - startedAt, model, error: stopped ? (stopMessage ?? "Subagent stopped by user.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? turnBudgetMessage : error ?? assistantError ?? spawnErrorMessage, protocolError, finalOutput: (timedOut || stopped) && !finalOutput.trim() ? (stopped ? stopMessage ?? "Subagent stopped by user." : timeoutMessage ?? "Subagent timed out.") : finalOutput, outputState: finalOutput.trim() ? "present" : "absent", timedOut, stopped, turnBudget, turnBudgetExceeded, wrapUpRequested: turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined, observedMutationAttempt, watchdog: childWatchdogState, processInstanceId });
|
|
851
878
|
});
|
|
852
879
|
});
|
|
853
880
|
}
|
|
@@ -1006,6 +1033,8 @@ async function runSingleStep(
|
|
|
1006
1033
|
context?: "fresh" | "fork";
|
|
1007
1034
|
agentContract?: import("../../shared/types.ts").AgentContract;
|
|
1008
1035
|
launchContractDigest?: string;
|
|
1036
|
+
launchResolvedExtensions?: LaunchResolvedChildExtensionsV1;
|
|
1037
|
+
runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1;
|
|
1009
1038
|
output: string;
|
|
1010
1039
|
exitCode: number | null;
|
|
1011
1040
|
error?: string;
|
|
@@ -1146,6 +1175,7 @@ async function runSingleStep(
|
|
|
1146
1175
|
: [undefined];
|
|
1147
1176
|
const attemptedModels: string[] = [];
|
|
1148
1177
|
let capabilityAudit: import("../shared/capability-ceiling.ts").SubagentCapabilityAudit | undefined;
|
|
1178
|
+
let launchResolvedExtensions = step.launchResolvedExtensions;
|
|
1149
1179
|
const modelAttempts: ModelAttempt[] = [];
|
|
1150
1180
|
const writerProcesses: Array<{ processInstanceId: string; kind: "pi-writer"; attempt: number; closeObservedAt: number; exitCode: number | null; signal: string | null }> = [];
|
|
1151
1181
|
let writerAttemptCount = 0;
|
|
@@ -1182,7 +1212,7 @@ async function runSingleStep(
|
|
|
1182
1212
|
childIndex: ctx.flatIndex,
|
|
1183
1213
|
})
|
|
1184
1214
|
: undefined;
|
|
1185
|
-
const { args, env, tempDir, toolDiagnosticPath, capabilityAudit: attemptCapabilityAudit } = buildPiArgs({
|
|
1215
|
+
const { args, env, tempDir, toolDiagnosticPath, runtimeAcknowledgedExtensionsPath, capabilityAudit: attemptCapabilityAudit } = buildPiArgs({
|
|
1186
1216
|
parentSessionId: step.parentSessionId,
|
|
1187
1217
|
baseArgs: ["--mode", "json", "-p"],
|
|
1188
1218
|
task,
|
|
@@ -1231,6 +1261,7 @@ async function runSingleStep(
|
|
|
1231
1261
|
capabilityCeiling: step.capabilityCeiling ?? ctx.capabilityCeiling,
|
|
1232
1262
|
inheritedCapabilityCeiling: decodeSubagentCapabilityCeiling(process.env[SUBAGENT_CAPABILITY_CEILING_ENV]),
|
|
1233
1263
|
});
|
|
1264
|
+
launchResolvedExtensions = projectLaunchResolvedChildExtensions(toolPlan);
|
|
1234
1265
|
actualLaunchContractDigest = launchBindingDigest({
|
|
1235
1266
|
definitionDigest: step.definitionDigest,
|
|
1236
1267
|
task: step.launchBindingTask ?? task,
|
|
@@ -1303,6 +1334,7 @@ async function runSingleStep(
|
|
|
1303
1334
|
const toolAvailabilityError = run.exitCode === 0 && !run.error
|
|
1304
1335
|
? readChildToolDiagnosticError(toolDiagnosticPath)
|
|
1305
1336
|
: undefined;
|
|
1337
|
+
const runtimeAcknowledgedExtensions = readRuntimeAcknowledgedExtensions(runtimeAcknowledgedExtensionsPath);
|
|
1306
1338
|
cleanupTempDir(tempDir);
|
|
1307
1339
|
|
|
1308
1340
|
const hiddenError = run.exitCode === 0 && !run.error && !toolAvailabilityError ? detectSubagentError(run.messages) : null;
|
|
@@ -1357,6 +1389,13 @@ async function runSingleStep(
|
|
|
1357
1389
|
: run.error && run.exitCode === 0
|
|
1358
1390
|
? 1
|
|
1359
1391
|
: run.exitCode;
|
|
1392
|
+
const signalError = run.exitCode !== 0 && isUnexplainedProcessSignal({
|
|
1393
|
+
processSignal: run.processSignal,
|
|
1394
|
+
interrupted: run.interrupted,
|
|
1395
|
+
timedOut: run.timedOut,
|
|
1396
|
+
stopped: run.stopped,
|
|
1397
|
+
turnBudgetExceeded: run.turnBudgetExceeded,
|
|
1398
|
+
}) ? formatProcessSignalError(run.processSignal!) : undefined;
|
|
1360
1399
|
const error = toolAvailabilityError
|
|
1361
1400
|
?? completionGuardError
|
|
1362
1401
|
?? structuredError
|
|
@@ -1365,7 +1404,7 @@ async function runSingleStep(
|
|
|
1365
1404
|
? hiddenError.details
|
|
1366
1405
|
? `${hiddenError.errorType} failed (exit ${effectiveExitCode}): ${hiddenError.details}`
|
|
1367
1406
|
: `${hiddenError.errorType} failed with exit code ${effectiveExitCode}`
|
|
1368
|
-
: run.error || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined));
|
|
1407
|
+
: run.error || signalError || (run.exitCode !== 0 && run.stderr.trim() ? run.stderr.trim() : undefined));
|
|
1369
1408
|
const attempt: ModelAttempt = {
|
|
1370
1409
|
model: candidate ?? run.model ?? step.model ?? "default",
|
|
1371
1410
|
success: effectiveExitCode === 0 && !error,
|
|
@@ -1383,7 +1422,7 @@ async function runSingleStep(
|
|
|
1383
1422
|
toolBudgetBlocked = Boolean(blockedMessage);
|
|
1384
1423
|
toolBudget = toolBudgetState(step.toolBudget, toolMessages.length, blockedMessage ? (blockedMessage as { toolName?: string }).toolName : undefined);
|
|
1385
1424
|
}
|
|
1386
|
-
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect ? { effects: { fileMutation: fileMutationEffect } } : {}) } as RunPiStreamingResult & { structuredOutput?: unknown; agentContract?: import("../../shared/types.ts").AgentContract; effects?: import("../../shared/types.ts").EffectsProjection };
|
|
1425
|
+
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput, runtimeAcknowledgedExtensions, ...(step.agentContract ? { agentContract: step.agentContract } : {}), ...(fileMutationEffect ? { effects: { fileMutation: fileMutationEffect } } : {}) } as RunPiStreamingResult & { structuredOutput?: unknown; agentContract?: import("../../shared/types.ts").AgentContract; effects?: import("../../shared/types.ts").EffectsProjection };
|
|
1387
1426
|
if (run.turnBudgetExceeded) break modelAttemptsLoop;
|
|
1388
1427
|
if (run.stopped || run.timedOut || ctx.timeoutSignal?.aborted || ctx.stopSignal?.aborted || ctx.skipAcceptance?.()) break modelAttemptsLoop;
|
|
1389
1428
|
if (attempt.success || completionGuardTriggered) break modelAttemptsLoop;
|
|
@@ -1461,6 +1500,13 @@ async function runSingleStep(
|
|
|
1461
1500
|
const childWrittenOutput = step.outputPath
|
|
1462
1501
|
? extractChildWrittenOutput(finalResult?.messages, step.outputPath, step.cwd ?? ctx.cwd)
|
|
1463
1502
|
: undefined;
|
|
1503
|
+
const outputState: SubagentOutputState = finalResult?.outputState === "present"
|
|
1504
|
+
|| (finalResult as (RunPiStreamingResult & { structuredOutput?: unknown }) | undefined)?.structuredOutput !== undefined
|
|
1505
|
+
|| Boolean(childWrittenOutput?.trim())
|
|
1506
|
+
? "present"
|
|
1507
|
+
: resolvedOutput.savedPath
|
|
1508
|
+
? "unknown"
|
|
1509
|
+
: finalResult?.outputState ?? "unknown";
|
|
1464
1510
|
const finalizedOutput = finalizeSingleOutput({
|
|
1465
1511
|
fullOutput: outputForSummary,
|
|
1466
1512
|
outputPath: step.outputPath,
|
|
@@ -1533,6 +1579,8 @@ async function runSingleStep(
|
|
|
1533
1579
|
acceptance: effectiveAcceptance,
|
|
1534
1580
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
1535
1581
|
launchContractDigest: actualLaunchContractDigest,
|
|
1582
|
+
launchResolvedExtensions,
|
|
1583
|
+
...((finalResult as (RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }) | undefined)?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: (finalResult as RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }).runtimeAcknowledgedExtensions } : {}),
|
|
1536
1584
|
...(transcriptWriter ? { transcriptPath: artifactPaths.transcriptPath } : {}),
|
|
1537
1585
|
transcriptError: transcriptWriter?.getError(),
|
|
1538
1586
|
skills: step.skills,
|
|
@@ -1549,6 +1597,7 @@ async function runSingleStep(
|
|
|
1549
1597
|
...(step.agentContract ? { agentContract: step.agentContract } : {}),
|
|
1550
1598
|
launchContractDigest: actualLaunchContractDigest,
|
|
1551
1599
|
output: outputForSummary,
|
|
1600
|
+
outputState,
|
|
1552
1601
|
exitCode: effectiveFinalExitCode,
|
|
1553
1602
|
error: effectiveFinalError,
|
|
1554
1603
|
protocolError: finalResult?.protocolError,
|
|
@@ -1564,6 +1613,7 @@ async function runSingleStep(
|
|
|
1564
1613
|
interrupted: timedOutAfterAcceptance || stoppedAfterAcceptance || turnBudgetExceeded ? false : finalResult?.interrupted,
|
|
1565
1614
|
timedOut: timedOutAfterAcceptance ? true : finalResult?.timedOut,
|
|
1566
1615
|
stopped: stoppedAfterAcceptance ? true : finalResult?.stopped,
|
|
1616
|
+
processSignal: finalResult?.processSignal,
|
|
1567
1617
|
turnBudget,
|
|
1568
1618
|
turnBudgetExceeded: turnBudgetExceeded || undefined,
|
|
1569
1619
|
wrapUpRequested: finalResult?.wrapUpRequested || turnBudget?.outcome === "wrap-up-requested" || turnBudget?.outcome === "termination-deferred" || turnBudgetExceeded || undefined,
|
|
@@ -1577,6 +1627,8 @@ async function runSingleStep(
|
|
|
1577
1627
|
acceptance: effectiveAcceptance,
|
|
1578
1628
|
watchdog: finalResult?.watchdog,
|
|
1579
1629
|
...(capabilityAudit ? { capabilityCeiling: capabilityAudit.ceiling, capabilityAudit } : {}),
|
|
1630
|
+
launchResolvedExtensions,
|
|
1631
|
+
...((finalResult as (RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }) | undefined)?.runtimeAcknowledgedExtensions ? { runtimeAcknowledgedExtensions: (finalResult as RunPiStreamingResult & { runtimeAcknowledgedExtensions?: RuntimeAcknowledgedChildExtensionsV1 }).runtimeAcknowledgedExtensions } : {}),
|
|
1580
1632
|
writerProcesses,
|
|
1581
1633
|
writerAttemptCount,
|
|
1582
1634
|
};
|
|
@@ -1585,6 +1637,7 @@ async function runSingleStep(
|
|
|
1585
1637
|
|
|
1586
1638
|
type RunnerStatusStep = NonNullable<AsyncStatus["steps"]>[number] & {
|
|
1587
1639
|
exitCode?: number | null;
|
|
1640
|
+
description?: string;
|
|
1588
1641
|
};
|
|
1589
1642
|
|
|
1590
1643
|
function appendCapabilityCeilingAppliedEvent(eventsPath: string, runId: string, stepIndex: number, agent: string, result: StepResult): void {
|
|
@@ -1782,6 +1835,10 @@ async function runSubagent(
|
|
|
1782
1835
|
let timedOut = false;
|
|
1783
1836
|
let stopped = false;
|
|
1784
1837
|
let turnBudgetExceeded = false;
|
|
1838
|
+
let usageBudgetExceeded = false;
|
|
1839
|
+
let checkpointRejected = false;
|
|
1840
|
+
let pendingCheckpointDecision: "approved" | "rejected" | undefined;
|
|
1841
|
+
let wakeCheckpointDecision: (() => void) | undefined;
|
|
1785
1842
|
const timeoutMessage = config.timeoutMs !== undefined ? `Subagent timed out after ${config.timeoutMs}ms.` : undefined;
|
|
1786
1843
|
const stopMessage = "Subagent stopped by user.";
|
|
1787
1844
|
const timeoutAbortController = new AbortController();
|
|
@@ -1796,6 +1853,19 @@ async function runSubagent(
|
|
|
1796
1853
|
let flatStepCount = 0;
|
|
1797
1854
|
for (let stepIndex = 0; stepIndex < steps.length; stepIndex++) {
|
|
1798
1855
|
const step = steps[stepIndex]!;
|
|
1856
|
+
if (isCheckpointRunnerStep(step)) {
|
|
1857
|
+
initialStatusSteps.push({
|
|
1858
|
+
agent: `checkpoint:${step.checkpoint}`,
|
|
1859
|
+
phase: step.phase,
|
|
1860
|
+
label: step.label ?? step.checkpoint,
|
|
1861
|
+
status: "pending",
|
|
1862
|
+
checkpoint: { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending", stepIndex },
|
|
1863
|
+
recentTools: [],
|
|
1864
|
+
recentOutput: [],
|
|
1865
|
+
});
|
|
1866
|
+
flatStepCount++;
|
|
1867
|
+
continue;
|
|
1868
|
+
}
|
|
1799
1869
|
if (isParallelGroup(step)) {
|
|
1800
1870
|
parallelGroups.push({ start: flatStepCount, count: step.parallel.length, stepIndex });
|
|
1801
1871
|
for (const task of step.parallel) {
|
|
@@ -1803,6 +1873,7 @@ async function runSubagent(
|
|
|
1803
1873
|
const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: taskFlatIndex, flatStepCount: initialFlatStepCount });
|
|
1804
1874
|
initialStatusSteps.push({
|
|
1805
1875
|
agent: task.agent,
|
|
1876
|
+
...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
|
|
1806
1877
|
...(task.context ? { context: task.context } : {}),
|
|
1807
1878
|
phase: task.phase,
|
|
1808
1879
|
label: task.label,
|
|
@@ -1810,6 +1881,7 @@ async function runSubagent(
|
|
|
1810
1881
|
structured: task.structured,
|
|
1811
1882
|
...(task.agentContract ? { agentContract: task.agentContract } : {}),
|
|
1812
1883
|
...(task.launchContractDigest ? { launchContractDigest: task.launchContractDigest } : {}),
|
|
1884
|
+
...(task.launchResolvedExtensions ? { launchResolvedExtensions: task.launchResolvedExtensions } : {}),
|
|
1813
1885
|
...(task.capabilityCeiling ? { capabilityCeiling: task.capabilityCeiling } : {}),
|
|
1814
1886
|
status: "pending",
|
|
1815
1887
|
...(task.toolBudget ? { toolBudget: initialToolBudgetState(task.toolBudget) } : {}),
|
|
@@ -1846,6 +1918,7 @@ async function runSubagent(
|
|
|
1846
1918
|
const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: step.agent, flatIndex: stepFlatIndex, flatStepCount: initialFlatStepCount });
|
|
1847
1919
|
initialStatusSteps.push({
|
|
1848
1920
|
agent: step.agent,
|
|
1921
|
+
...(statusStepDescription(step.task) ? { description: statusStepDescription(step.task) } : {}),
|
|
1849
1922
|
...(step.context ? { context: step.context } : {}),
|
|
1850
1923
|
phase: step.phase,
|
|
1851
1924
|
label: step.label,
|
|
@@ -1853,6 +1926,7 @@ async function runSubagent(
|
|
|
1853
1926
|
structured: step.structured,
|
|
1854
1927
|
...(step.agentContract ? { agentContract: step.agentContract } : {}),
|
|
1855
1928
|
...(step.launchContractDigest ? { launchContractDigest: step.launchContractDigest } : {}),
|
|
1929
|
+
...(step.launchResolvedExtensions ? { launchResolvedExtensions: step.launchResolvedExtensions } : {}),
|
|
1856
1930
|
...(step.capabilityCeiling ? { capabilityCeiling: step.capabilityCeiling } : {}),
|
|
1857
1931
|
status: "pending",
|
|
1858
1932
|
...(step.toolBudget ? { toolBudget: initialToolBudgetState(step.toolBudget) } : {}),
|
|
@@ -1891,6 +1965,7 @@ async function runSubagent(
|
|
|
1891
1965
|
...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
|
|
1892
1966
|
...(config.turnBudget ? { turnBudget: initialTurnBudgetState(config.turnBudget) } : {}),
|
|
1893
1967
|
...(config.toolBudget ? { toolBudget: initialToolBudgetState(config.toolBudget) } : {}),
|
|
1968
|
+
...(config.usageBudget ? { usageBudget: usageBudgetState(config.usageBudget, undefined) } : {}),
|
|
1894
1969
|
pid: process.pid,
|
|
1895
1970
|
cwd,
|
|
1896
1971
|
currentStep: 0,
|
|
@@ -1898,6 +1973,7 @@ async function runSubagent(
|
|
|
1898
1973
|
parallelGroups,
|
|
1899
1974
|
workflowGraph: config.workflowGraph,
|
|
1900
1975
|
...(config.launchContractDigest ? { launchContractDigest: config.launchContractDigest } : {}),
|
|
1976
|
+
...(config.launchResolvedExtensions ? { launchResolvedExtensions: config.launchResolvedExtensions } : {}),
|
|
1901
1977
|
...(config.capabilityCeiling ? { capabilityCeiling: config.capabilityCeiling } : {}),
|
|
1902
1978
|
...(config.runnerProcessInstanceId ? { processTerminal: { version: 1 as const, state: "pending" as const, runId: id, runnerProcessInstanceId: config.runnerProcessInstanceId } } : {}),
|
|
1903
1979
|
steps: initialStatusSteps,
|
|
@@ -1908,6 +1984,23 @@ async function runSubagent(
|
|
|
1908
1984
|
|
|
1909
1985
|
fs.mkdirSync(asyncDir, { recursive: true });
|
|
1910
1986
|
writeAtomicJson(statusPath, statusPayload);
|
|
1987
|
+
let pendingParallelUsageCost: CostSummary = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
1988
|
+
const currentUsageTotals = (): CostSummary => {
|
|
1989
|
+
const cost = results.reduce<CostSummary>((sum, result) => ({
|
|
1990
|
+
inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? result.usage?.input ?? 0),
|
|
1991
|
+
outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? result.usage?.output ?? 0),
|
|
1992
|
+
costUsd: sum.costUsd + (result.totalCost?.costUsd ?? result.usage?.cost ?? 0),
|
|
1993
|
+
}), { inputTokens: pendingParallelUsageCost.inputTokens, outputTokens: pendingParallelUsageCost.outputTokens, costUsd: pendingParallelUsageCost.costUsd });
|
|
1994
|
+
return {
|
|
1995
|
+
inputTokens: Math.max(cost.inputTokens, statusPayload.totalTokens?.input ?? 0),
|
|
1996
|
+
outputTokens: Math.max(cost.outputTokens, statusPayload.totalTokens?.output ?? 0),
|
|
1997
|
+
costUsd: cost.costUsd,
|
|
1998
|
+
};
|
|
1999
|
+
};
|
|
2000
|
+
const refreshUsageBudget = () => {
|
|
2001
|
+
statusPayload.usageBudget = usageBudgetState(config.usageBudget, currentUsageTotals());
|
|
2002
|
+
return statusPayload.usageBudget;
|
|
2003
|
+
};
|
|
1911
2004
|
const emitNestedSelfEvent = (type: "subagent.nested.updated" | "subagent.nested.completed"): void => {
|
|
1912
2005
|
if (!config.nestedRoute || !config.nestedSelf) return;
|
|
1913
2006
|
try {
|
|
@@ -1933,9 +2026,9 @@ async function runSubagent(
|
|
|
1933
2026
|
const refreshWorkflowGraph = (): void => {
|
|
1934
2027
|
if (!config.workflowGraph) return;
|
|
1935
2028
|
const graph = structuredClone(statusPayload.workflowGraph ?? config.workflowGraph);
|
|
1936
|
-
const normalize = (status: RunnerStatusStep["status"]): "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached" => {
|
|
2029
|
+
const normalize = (status: RunnerStatusStep["status"]): "pending" | "running" | "completed" | "failed" | "paused" | "stopped" | "detached" | "rejected" => {
|
|
1937
2030
|
if (status === "complete" || status === "completed") return "completed";
|
|
1938
|
-
if (status === "running" || status === "failed" || status === "paused" || status === "stopped" || status === "pending") return status;
|
|
2031
|
+
if (status === "running" || status === "failed" || status === "paused" || status === "stopped" || status === "pending" || status === "rejected") return status;
|
|
1939
2032
|
return "pending";
|
|
1940
2033
|
};
|
|
1941
2034
|
const updateNode = (node: NonNullable<typeof graph.nodes>[number]): void => {
|
|
@@ -1945,6 +2038,7 @@ async function runSubagent(
|
|
|
1945
2038
|
node.status = normalize(step.status);
|
|
1946
2039
|
node.error = step.error;
|
|
1947
2040
|
node.acceptanceStatus = step.acceptance?.status;
|
|
2041
|
+
node.checkpoint = step.checkpoint;
|
|
1948
2042
|
}
|
|
1949
2043
|
if (statusPayload.currentStep === node.flatIndex) graph.currentNodeId = node.id;
|
|
1950
2044
|
}
|
|
@@ -1953,10 +2047,11 @@ async function runSubagent(
|
|
|
1953
2047
|
if (node.children.every((child) => child.status === "completed")) node.status = "completed";
|
|
1954
2048
|
else if (node.children.some((child) => child.status === "running")) node.status = "running";
|
|
1955
2049
|
else if (node.children.some((child) => child.status === "stopped")) node.status = "stopped";
|
|
2050
|
+
else if (node.children.some((child) => child.status === "rejected")) node.status = "rejected";
|
|
1956
2051
|
else if (node.children.some((child) => child.status === "failed")) node.status = "failed";
|
|
1957
2052
|
else if (node.children.some((child) => child.status === "paused")) node.status = "paused";
|
|
1958
2053
|
}
|
|
1959
|
-
if (node.error && node.status !== "stopped") node.status = "failed";
|
|
2054
|
+
if (node.error && node.status !== "stopped" && node.status !== "rejected") node.status = "failed";
|
|
1960
2055
|
};
|
|
1961
2056
|
for (const node of graph.nodes) updateNode(node);
|
|
1962
2057
|
statusPayload.workflowGraph = graph;
|
|
@@ -2604,6 +2699,7 @@ async function runSubagent(
|
|
|
2604
2699
|
const totalInput = statusPayload.totalTokens?.input ?? 0;
|
|
2605
2700
|
const totalOutput = statusPayload.totalTokens?.output ?? 0;
|
|
2606
2701
|
statusPayload.totalTokens = { input: totalInput + input, output: totalOutput + output, total: totalInput + totalOutput + input + output };
|
|
2702
|
+
refreshUsageBudget();
|
|
2607
2703
|
}
|
|
2608
2704
|
statusPayload.turnCount = Math.max(statusPayload.turnCount ?? 0, step.turnCount);
|
|
2609
2705
|
updateStepTurnBudget(
|
|
@@ -2789,6 +2885,10 @@ async function runSubagent(
|
|
|
2789
2885
|
onInterrupt: interruptRunner,
|
|
2790
2886
|
onTimeout: timeoutRunner,
|
|
2791
2887
|
onStop: stopRunner,
|
|
2888
|
+
onCheckpointDecision: (decision) => {
|
|
2889
|
+
pendingCheckpointDecision = decision;
|
|
2890
|
+
wakeCheckpointDecision?.();
|
|
2891
|
+
},
|
|
2792
2892
|
onSteer: (request) => {
|
|
2793
2893
|
const targetStep = request.targetIndex !== undefined ? statusPayload.steps[request.targetIndex] : undefined;
|
|
2794
2894
|
if (targetStep?.status === "pending") {
|
|
@@ -2839,14 +2939,95 @@ async function runSubagent(
|
|
|
2839
2939
|
|
|
2840
2940
|
let flatIndex = 0;
|
|
2841
2941
|
let stepCursor = 0;
|
|
2942
|
+
const waitForCheckpointDecision = async (): Promise<"approved" | "rejected" | undefined> => {
|
|
2943
|
+
while (!pendingCheckpointDecision && !interrupted && !timedOut && !stopped) {
|
|
2944
|
+
await new Promise<void>((resolve) => {
|
|
2945
|
+
wakeCheckpointDecision = resolve;
|
|
2946
|
+
const timer = setTimeout(resolve, POLL_INTERVAL_MS);
|
|
2947
|
+
timer.unref?.();
|
|
2948
|
+
});
|
|
2949
|
+
wakeCheckpointDecision = undefined;
|
|
2950
|
+
}
|
|
2951
|
+
const decision = pendingCheckpointDecision;
|
|
2952
|
+
pendingCheckpointDecision = undefined;
|
|
2953
|
+
return decision;
|
|
2954
|
+
};
|
|
2842
2955
|
|
|
2843
2956
|
while (true) {
|
|
2844
2957
|
if (interrupted || timedOut || stopped || turnBudgetExceeded) break;
|
|
2845
2958
|
consumePendingAppendRequests();
|
|
2846
2959
|
if (stepCursor >= steps.length) break;
|
|
2960
|
+
refreshUsageBudget();
|
|
2961
|
+
if (statusPayload.usageBudget?.exhausted) {
|
|
2962
|
+
usageBudgetExceeded = true;
|
|
2963
|
+
statusPayload.state = "failed";
|
|
2964
|
+
statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
2965
|
+
statusPayload.currentStep = flatIndex;
|
|
2966
|
+
statusPayload.lastUpdate = Date.now();
|
|
2967
|
+
writeStatusPayload();
|
|
2968
|
+
break;
|
|
2969
|
+
}
|
|
2847
2970
|
const stepIndex = stepCursor++;
|
|
2848
2971
|
const step = steps[stepIndex]!;
|
|
2849
2972
|
|
|
2973
|
+
if (isCheckpointRunnerStep(step)) {
|
|
2974
|
+
const now = Date.now();
|
|
2975
|
+
const statusStep = statusPayload.steps[flatIndex];
|
|
2976
|
+
const checkpoint = { name: step.checkpoint, ...(step.message ? { message: step.message } : {}), status: "pending" as const, stepIndex };
|
|
2977
|
+
statusPayload.state = "paused";
|
|
2978
|
+
statusPayload.currentStep = flatIndex;
|
|
2979
|
+
statusPayload.checkpoint = checkpoint;
|
|
2980
|
+
statusPayload.activityState = undefined;
|
|
2981
|
+
statusPayload.lastUpdate = now;
|
|
2982
|
+
if (statusStep) {
|
|
2983
|
+
statusStep.status = "paused";
|
|
2984
|
+
statusStep.startedAt = now;
|
|
2985
|
+
statusStep.checkpoint = checkpoint;
|
|
2986
|
+
}
|
|
2987
|
+
writeStatusPayload();
|
|
2988
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.paused", ts: now, runId: id, stepIndex, checkpoint }));
|
|
2989
|
+
const decision = await waitForCheckpointDecision();
|
|
2990
|
+
if (decision === "approved") {
|
|
2991
|
+
const approvedAt = Date.now();
|
|
2992
|
+
const approved = { ...checkpoint, status: "approved" as const, approvedAt };
|
|
2993
|
+
statusPayload.state = "running";
|
|
2994
|
+
statusPayload.checkpoint = approved;
|
|
2995
|
+
if (statusStep) {
|
|
2996
|
+
statusStep.status = "complete";
|
|
2997
|
+
statusStep.endedAt = approvedAt;
|
|
2998
|
+
statusStep.durationMs = approvedAt - now;
|
|
2999
|
+
statusStep.exitCode = 0;
|
|
3000
|
+
statusStep.checkpoint = approved;
|
|
3001
|
+
}
|
|
3002
|
+
statusPayload.lastUpdate = approvedAt;
|
|
3003
|
+
writeStatusPayload();
|
|
3004
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.approved", ts: approvedAt, runId: id, stepIndex, checkpoint: approved }));
|
|
3005
|
+
flatIndex++;
|
|
3006
|
+
continue;
|
|
3007
|
+
}
|
|
3008
|
+
if (decision === "rejected") {
|
|
3009
|
+
const rejectedAt = Date.now();
|
|
3010
|
+
const rejected = { ...checkpoint, status: "rejected" as const, rejectedAt };
|
|
3011
|
+
checkpointRejected = true;
|
|
3012
|
+
statusPayload.state = "rejected";
|
|
3013
|
+
statusPayload.error = `Checkpoint '${step.checkpoint}' rejected.`;
|
|
3014
|
+
statusPayload.checkpoint = rejected;
|
|
3015
|
+
if (statusStep) {
|
|
3016
|
+
statusStep.status = "rejected";
|
|
3017
|
+
statusStep.error = statusPayload.error;
|
|
3018
|
+
statusStep.endedAt = rejectedAt;
|
|
3019
|
+
statusStep.durationMs = rejectedAt - now;
|
|
3020
|
+
statusStep.exitCode = 1;
|
|
3021
|
+
statusStep.checkpoint = rejected;
|
|
3022
|
+
}
|
|
3023
|
+
statusPayload.lastUpdate = rejectedAt;
|
|
3024
|
+
writeStatusPayload();
|
|
3025
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.checkpoint.rejected", ts: rejectedAt, runId: id, stepIndex, checkpoint: rejected }));
|
|
3026
|
+
break;
|
|
3027
|
+
}
|
|
3028
|
+
break;
|
|
3029
|
+
}
|
|
3030
|
+
|
|
2850
3031
|
if (isDynamicRunnerGroup(step)) {
|
|
2851
3032
|
const groupStartFlatIndex = flatIndex;
|
|
2852
3033
|
let materialized: ReturnType<typeof materializeDynamicParallelStep>;
|
|
@@ -2991,12 +3172,14 @@ async function runSubagent(
|
|
|
2991
3172
|
const transcriptPath = resolveAsyncStepTranscriptPath({ artifactsDir, artifactConfig, runId: id, agent: task.agent, flatIndex: groupStartFlatIndex + itemIndex, flatStepCount: dynamicFlatStepCount });
|
|
2992
3173
|
return {
|
|
2993
3174
|
agent: task.agent,
|
|
3175
|
+
...(statusStepDescription(task.task) ? { description: statusStepDescription(task.task) } : {}),
|
|
2994
3176
|
...(task.context ? { context: task.context } : {}),
|
|
2995
3177
|
phase: task.phase ?? step.phase,
|
|
2996
3178
|
label: task.label,
|
|
2997
3179
|
outputName: undefined,
|
|
2998
3180
|
structured: Boolean(task.structuredOutputSchema),
|
|
2999
3181
|
...(task.agentContract ? { agentContract: task.agentContract } : {}),
|
|
3182
|
+
...(task.launchResolvedExtensions ? { launchResolvedExtensions: task.launchResolvedExtensions } : {}),
|
|
3000
3183
|
...(task.capabilityCeiling ? { capabilityCeiling: task.capabilityCeiling } : {}),
|
|
3001
3184
|
status: "pending",
|
|
3002
3185
|
...(task.sessionFile ? { sessionFile: task.sessionFile } : {}),
|
|
@@ -3057,6 +3240,22 @@ async function runSubagent(
|
|
|
3057
3240
|
let aborted = false;
|
|
3058
3241
|
const parallelResults = await mapConcurrent(dynamicSteps, concurrency, async (task, taskIdx) => {
|
|
3059
3242
|
const fi = groupStartFlatIndex + taskIdx;
|
|
3243
|
+
refreshUsageBudget();
|
|
3244
|
+
if (statusPayload.usageBudget?.exhausted) {
|
|
3245
|
+
const skippedAt = Date.now();
|
|
3246
|
+
const message = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
3247
|
+
statusPayload.steps[fi].status = "failed";
|
|
3248
|
+
statusPayload.steps[fi].error = message;
|
|
3249
|
+
statusPayload.steps[fi].startedAt = skippedAt;
|
|
3250
|
+
statusPayload.steps[fi].endedAt = skippedAt;
|
|
3251
|
+
statusPayload.steps[fi].durationMs = 0;
|
|
3252
|
+
statusPayload.steps[fi].exitCode = 1;
|
|
3253
|
+
statusPayload.lastUpdate = skippedAt;
|
|
3254
|
+
usageBudgetExceeded = true;
|
|
3255
|
+
writeStatusPayload();
|
|
3256
|
+
appendJsonl(eventsPath, JSON.stringify({ type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0 }));
|
|
3257
|
+
return { agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true };
|
|
3258
|
+
}
|
|
3060
3259
|
if (timedOut) return timedOutStepResult(task.agent, task.context);
|
|
3061
3260
|
if (stopped) return stoppedStepResult(task.agent, task.context);
|
|
3062
3261
|
if (interrupted) return pausedStepResult(task.agent, task.context);
|
|
@@ -3140,11 +3339,21 @@ async function runSubagent(
|
|
|
3140
3339
|
statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
|
|
3141
3340
|
statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
|
|
3142
3341
|
statusPayload.steps[fi].totalCost = singleResult.totalCost;
|
|
3342
|
+
if (singleResult.totalCost) {
|
|
3343
|
+
pendingParallelUsageCost = {
|
|
3344
|
+
inputTokens: pendingParallelUsageCost.inputTokens + singleResult.totalCost.inputTokens,
|
|
3345
|
+
outputTokens: pendingParallelUsageCost.outputTokens + singleResult.totalCost.outputTokens,
|
|
3346
|
+
costUsd: pendingParallelUsageCost.costUsd + singleResult.totalCost.costUsd,
|
|
3347
|
+
};
|
|
3348
|
+
refreshUsageBudget();
|
|
3349
|
+
}
|
|
3143
3350
|
statusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error;
|
|
3144
3351
|
statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
|
|
3145
3352
|
statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
|
|
3146
3353
|
statusPayload.steps[fi].agentContract = singleResult.agentContract;
|
|
3147
3354
|
statusPayload.steps[fi].launchContractDigest = singleResult.launchContractDigest;
|
|
3355
|
+
statusPayload.steps[fi].launchResolvedExtensions = singleResult.launchResolvedExtensions;
|
|
3356
|
+
statusPayload.steps[fi].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
|
|
3148
3357
|
statusPayload.steps[fi].effects = singleResult.effects;
|
|
3149
3358
|
statusPayload.steps[fi].execution = singleResult.execution;
|
|
3150
3359
|
statusPayload.steps[fi].review = singleResult.review;
|
|
@@ -3176,7 +3385,10 @@ async function runSubagent(
|
|
|
3176
3385
|
context: pr.context,
|
|
3177
3386
|
agentContract: pr.agentContract,
|
|
3178
3387
|
launchContractDigest: pr.launchContractDigest,
|
|
3388
|
+
launchResolvedExtensions: pr.launchResolvedExtensions,
|
|
3389
|
+
runtimeAcknowledgedExtensions: pr.runtimeAcknowledgedExtensions,
|
|
3179
3390
|
output: pr.output,
|
|
3391
|
+
outputState: pr.outputState,
|
|
3180
3392
|
error: pr.error,
|
|
3181
3393
|
protocolError: pr.protocolError,
|
|
3182
3394
|
success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
|
|
@@ -3211,6 +3423,8 @@ async function runSubagent(
|
|
|
3211
3423
|
capabilityAudit: pr.capabilityAudit,
|
|
3212
3424
|
});
|
|
3213
3425
|
}
|
|
3426
|
+
pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
3427
|
+
refreshUsageBudget();
|
|
3214
3428
|
const collection = collectDynamicResults(step as Parameters<typeof collectDynamicResults>[0], materialized.items, parallelResults);
|
|
3215
3429
|
const failures = parallelResults.filter((result) => result.exitCode !== 0 && result.exitCode !== -1);
|
|
3216
3430
|
const acceptanceFailures = parallelResults
|
|
@@ -3376,6 +3590,25 @@ async function runSubagent(
|
|
|
3376
3590
|
concurrency,
|
|
3377
3591
|
async (task, taskIdx) => {
|
|
3378
3592
|
const fi = groupStartFlatIndex + taskIdx;
|
|
3593
|
+
refreshUsageBudget();
|
|
3594
|
+
if (statusPayload.usageBudget?.exhausted) {
|
|
3595
|
+
const skippedAt = Date.now();
|
|
3596
|
+
const message = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
3597
|
+
statusPayload.steps[fi].status = "failed";
|
|
3598
|
+
statusPayload.steps[fi].error = message;
|
|
3599
|
+
statusPayload.steps[fi].startedAt = skippedAt;
|
|
3600
|
+
statusPayload.steps[fi].endedAt = skippedAt;
|
|
3601
|
+
statusPayload.steps[fi].durationMs = 0;
|
|
3602
|
+
statusPayload.steps[fi].exitCode = 1;
|
|
3603
|
+
statusPayload.steps[fi].activityState = undefined;
|
|
3604
|
+
statusPayload.lastUpdate = skippedAt;
|
|
3605
|
+
usageBudgetExceeded = true;
|
|
3606
|
+
writeStatusPayload();
|
|
3607
|
+
appendJsonl(eventsPath, JSON.stringify({
|
|
3608
|
+
type: "subagent.step.failed", ts: skippedAt, runId: id, stepIndex: fi, agent: task.agent, exitCode: 1, durationMs: 0,
|
|
3609
|
+
}));
|
|
3610
|
+
return { agent: task.agent, context: task.context, output: message, error: message, exitCode: 1 as number | null, skipped: true };
|
|
3611
|
+
}
|
|
3379
3612
|
if (timedOut) return timedOutStepResult(task.agent, task.context);
|
|
3380
3613
|
if (stopped) return stoppedStepResult(task.agent, task.context);
|
|
3381
3614
|
if (interrupted) return pausedStepResult(task.agent, task.context);
|
|
@@ -3481,10 +3714,20 @@ async function runSubagent(
|
|
|
3481
3714
|
statusPayload.steps[fi].attemptedModels = singleResult.attemptedModels;
|
|
3482
3715
|
statusPayload.steps[fi].modelAttempts = singleResult.modelAttempts;
|
|
3483
3716
|
statusPayload.steps[fi].totalCost = singleResult.totalCost;
|
|
3717
|
+
if (singleResult.totalCost) {
|
|
3718
|
+
pendingParallelUsageCost = {
|
|
3719
|
+
inputTokens: pendingParallelUsageCost.inputTokens + singleResult.totalCost.inputTokens,
|
|
3720
|
+
outputTokens: pendingParallelUsageCost.outputTokens + singleResult.totalCost.outputTokens,
|
|
3721
|
+
costUsd: pendingParallelUsageCost.costUsd + singleResult.totalCost.costUsd,
|
|
3722
|
+
};
|
|
3723
|
+
refreshUsageBudget();
|
|
3724
|
+
}
|
|
3484
3725
|
statusPayload.steps[fi].error = stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error;
|
|
3485
3726
|
statusPayload.steps[fi].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[fi].transcriptPath;
|
|
3486
3727
|
statusPayload.steps[fi].transcriptError = singleResult.transcriptError;
|
|
3487
3728
|
statusPayload.steps[fi].agentContract = singleResult.agentContract;
|
|
3729
|
+
statusPayload.steps[fi].launchResolvedExtensions = singleResult.launchResolvedExtensions;
|
|
3730
|
+
statusPayload.steps[fi].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
|
|
3488
3731
|
statusPayload.steps[fi].effects = singleResult.effects;
|
|
3489
3732
|
statusPayload.steps[fi].execution = singleResult.execution;
|
|
3490
3733
|
statusPayload.steps[fi].review = singleResult.review;
|
|
@@ -3552,7 +3795,9 @@ async function runSubagent(
|
|
|
3552
3795
|
context: pr.context,
|
|
3553
3796
|
agentContract: pr.agentContract,
|
|
3554
3797
|
launchContractDigest: pr.launchContractDigest,
|
|
3798
|
+
launchResolvedExtensions: pr.launchResolvedExtensions,
|
|
3555
3799
|
output: pr.output,
|
|
3800
|
+
outputState: pr.outputState,
|
|
3556
3801
|
error: pr.error,
|
|
3557
3802
|
protocolError: pr.protocolError,
|
|
3558
3803
|
success: pr.stopped !== true && pr.interrupted !== true && pr.exitCode === 0,
|
|
@@ -3585,6 +3830,8 @@ async function runSubagent(
|
|
|
3585
3830
|
watchdog: pr.watchdog,
|
|
3586
3831
|
});
|
|
3587
3832
|
}
|
|
3833
|
+
pendingParallelUsageCost = { inputTokens: 0, outputTokens: 0, costUsd: 0 };
|
|
3834
|
+
refreshUsageBudget();
|
|
3588
3835
|
for (let t = 0; t < group.parallel.length; t++) {
|
|
3589
3836
|
const outputName = group.parallel[t]?.outputName;
|
|
3590
3837
|
if (outputName) outputs[outputName] = outputEntryFromAsyncResult({
|
|
@@ -3624,7 +3871,13 @@ async function runSubagent(
|
|
|
3624
3871
|
cleanup,
|
|
3625
3872
|
results: parallelResults.map((result) => ({
|
|
3626
3873
|
agent: result.agent,
|
|
3627
|
-
status: result.stopped
|
|
3874
|
+
status: result.stopped || (result.exitCode !== 0 && isUnexplainedProcessSignal({
|
|
3875
|
+
processSignal: result.processSignal,
|
|
3876
|
+
interrupted: result.interrupted,
|
|
3877
|
+
timedOut: result.timedOut,
|
|
3878
|
+
stopped: result.stopped,
|
|
3879
|
+
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
3880
|
+
})) ? "stopped" : result.interrupted ? "paused" : result.exitCode === 0 ? "completed" : "failed",
|
|
3628
3881
|
summary: result.output || result.error || "(no output)",
|
|
3629
3882
|
...(result.artifactPaths?.outputPath ? { outputPath: result.artifactPaths.outputPath } : {}),
|
|
3630
3883
|
...(result.structuredOutput !== undefined ? { structuredOutput: result.structuredOutput } : {}),
|
|
@@ -3728,7 +3981,10 @@ async function runSubagent(
|
|
|
3728
3981
|
context: singleResult.context,
|
|
3729
3982
|
agentContract: singleResult.agentContract,
|
|
3730
3983
|
launchContractDigest: singleResult.launchContractDigest,
|
|
3984
|
+
launchResolvedExtensions: singleResult.launchResolvedExtensions,
|
|
3985
|
+
runtimeAcknowledgedExtensions: singleResult.runtimeAcknowledgedExtensions,
|
|
3731
3986
|
output: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.output,
|
|
3987
|
+
outputState: singleResult.outputState,
|
|
3732
3988
|
error: stopped || childStopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : singleResult.error,
|
|
3733
3989
|
protocolError: singleResult.protocolError,
|
|
3734
3990
|
success: !stopped && !childStopped && !timedOut && singleResult.interrupted !== true && singleResult.exitCode === 0,
|
|
@@ -3818,6 +4074,8 @@ async function runSubagent(
|
|
|
3818
4074
|
statusPayload.steps[flatIndex].transcriptPath = singleResult.transcriptPath ?? statusPayload.steps[flatIndex].transcriptPath;
|
|
3819
4075
|
statusPayload.steps[flatIndex].transcriptError = singleResult.transcriptError;
|
|
3820
4076
|
statusPayload.steps[flatIndex].agentContract = singleResult.agentContract;
|
|
4077
|
+
statusPayload.steps[flatIndex].launchResolvedExtensions = singleResult.launchResolvedExtensions;
|
|
4078
|
+
statusPayload.steps[flatIndex].runtimeAcknowledgedExtensions = singleResult.runtimeAcknowledgedExtensions;
|
|
3821
4079
|
statusPayload.steps[flatIndex].effects = singleResult.effects;
|
|
3822
4080
|
statusPayload.steps[flatIndex].execution = singleResult.execution;
|
|
3823
4081
|
statusPayload.steps[flatIndex].review = singleResult.review;
|
|
@@ -3888,6 +4146,7 @@ async function runSubagent(
|
|
|
3888
4146
|
}
|
|
3889
4147
|
|
|
3890
4148
|
const resultMode = config.resultMode ?? statusPayload.mode;
|
|
4149
|
+
const singleRuntimeAcknowledgedExtensions = results.length === 1 ? results[0]?.runtimeAcknowledgedExtensions : undefined;
|
|
3891
4150
|
const totalCost = results.reduce<CostSummary>((sum, result) => ({
|
|
3892
4151
|
inputTokens: sum.inputTokens + (result.totalCost?.inputTokens ?? 0),
|
|
3893
4152
|
outputTokens: sum.outputTokens + (result.totalCost?.outputTokens ?? 0),
|
|
@@ -3938,7 +4197,14 @@ async function runSubagent(
|
|
|
3938
4197
|
clearTimeout(timeoutTimer);
|
|
3939
4198
|
timeoutTimer = undefined;
|
|
3940
4199
|
}
|
|
3941
|
-
|
|
4200
|
+
const signalTerminated = !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.some((result) => result.exitCode !== 0 && isUnexplainedProcessSignal({
|
|
4201
|
+
processSignal: result.processSignal,
|
|
4202
|
+
interrupted: result.interrupted,
|
|
4203
|
+
timedOut: result.timedOut,
|
|
4204
|
+
stopped: result.stopped,
|
|
4205
|
+
turnBudgetExceeded: result.turnBudgetExceeded,
|
|
4206
|
+
}));
|
|
4207
|
+
statusPayload.state = checkpointRejected ? "rejected" : stopped || signalTerminated ? "stopped" : timedOut || turnBudgetExceeded || usageBudgetExceeded || statusPayload.error ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed";
|
|
3942
4208
|
closeSteerInbox(asyncDir, statusPayload.state);
|
|
3943
4209
|
disposeControlInbox();
|
|
3944
4210
|
for (const request of consumeSteerRequests(asyncDir)) deliverSteerRequest(request);
|
|
@@ -3960,6 +4226,8 @@ async function runSubagent(
|
|
|
3960
4226
|
if (stopped) {
|
|
3961
4227
|
statusPayload.stopped = true;
|
|
3962
4228
|
statusPayload.error = stopMessage;
|
|
4229
|
+
} else if (signalTerminated && !statusPayload.error) {
|
|
4230
|
+
statusPayload.error = results.find((result) => result.processSignal)?.error;
|
|
3963
4231
|
}
|
|
3964
4232
|
if (timedOut) {
|
|
3965
4233
|
statusPayload.timedOut = true;
|
|
@@ -3969,10 +4237,15 @@ async function runSubagent(
|
|
|
3969
4237
|
const budget = statusPayload.turnBudget;
|
|
3970
4238
|
statusPayload.error = budget ? turnBudgetExceededMessage(budget, budget.turnCount) : "Subagent exceeded turn budget.";
|
|
3971
4239
|
}
|
|
4240
|
+
if (usageBudgetExceeded && statusPayload.usageBudget && !statusPayload.error) {
|
|
4241
|
+
statusPayload.error = usageBudgetExceededMessage(statusPayload.usageBudget);
|
|
4242
|
+
}
|
|
3972
4243
|
statusPayload.endedAt = runEndedAt;
|
|
3973
4244
|
statusPayload.lastUpdate = runEndedAt;
|
|
3974
4245
|
statusPayload.sessionFile = effectiveSessionFile;
|
|
4246
|
+
if (singleRuntimeAcknowledgedExtensions) statusPayload.runtimeAcknowledgedExtensions = singleRuntimeAcknowledgedExtensions;
|
|
3975
4247
|
statusPayload.totalCost = finalTotalCost;
|
|
4248
|
+
statusPayload.usageBudget = usageBudgetState(config.usageBudget, currentUsageTotals());
|
|
3976
4249
|
statusPayload.shareUrl = shareUrl;
|
|
3977
4250
|
statusPayload.gistUrl = gistUrl;
|
|
3978
4251
|
statusPayload.shareError = shareError;
|
|
@@ -3994,6 +4267,7 @@ async function runSubagent(
|
|
|
3994
4267
|
durationMs: runEndedAt - overallStartTime,
|
|
3995
4268
|
totalTokens: statusPayload.totalTokens,
|
|
3996
4269
|
totalCost: finalTotalCost,
|
|
4270
|
+
usageBudget: statusPayload.usageBudget,
|
|
3997
4271
|
}),
|
|
3998
4272
|
);
|
|
3999
4273
|
writeRunLog(logPath, {
|
|
@@ -4021,9 +4295,9 @@ async function runSubagent(
|
|
|
4021
4295
|
id,
|
|
4022
4296
|
agent: agentName,
|
|
4023
4297
|
mode: resultMode,
|
|
4024
|
-
success: !stopped && !timedOut && !turnBudgetExceeded && !interrupted && results.every((r) => r.success),
|
|
4025
|
-
state: stopped ? "stopped" : timedOut || turnBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
|
|
4026
|
-
summary: stopped ? stopMessage : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? (statusPayload.error ?? "Subagent exceeded turn budget.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
|
|
4298
|
+
success: !checkpointRejected && !stopped && !timedOut && !turnBudgetExceeded && !usageBudgetExceeded && !interrupted && !signalTerminated && results.every((r) => r.success),
|
|
4299
|
+
state: checkpointRejected ? "rejected" : stopped || signalTerminated ? "stopped" : timedOut || turnBudgetExceeded || usageBudgetExceeded ? "failed" : interrupted ? "paused" : results.every((r) => r.success) ? "complete" : "failed",
|
|
4300
|
+
summary: checkpointRejected ? (statusPayload.error ?? "Checkpoint rejected.") : stopped ? stopMessage : signalTerminated ? (statusPayload.error ?? "Subagent process terminated by signal.") : timedOut ? (timeoutMessage ?? "Subagent timed out.") : turnBudgetExceeded ? (statusPayload.error ?? "Subagent exceeded turn budget.") : usageBudgetExceeded ? (statusPayload.error ?? "Usage budget exhausted.") : interrupted ? "Paused after interrupt. Waiting for explicit next action." : summary,
|
|
4027
4301
|
...(config.timeoutMs !== undefined ? { timeoutMs: config.timeoutMs } : {}),
|
|
4028
4302
|
...(config.deadlineAt !== undefined ? { deadlineAt: config.deadlineAt } : {}),
|
|
4029
4303
|
...(statusPayload.turnBudget ? { turnBudget: statusPayload.turnBudget } : {}),
|
|
@@ -4031,11 +4305,14 @@ async function runSubagent(
|
|
|
4031
4305
|
...(statusPayload.wrapUpRequested ? { wrapUpRequested: true } : {}),
|
|
4032
4306
|
...(statusPayload.toolBudget ? { toolBudget: statusPayload.toolBudget } : {}),
|
|
4033
4307
|
...(statusPayload.toolBudgetBlocked ? { toolBudgetBlocked: true } : {}),
|
|
4034
|
-
...(
|
|
4308
|
+
...(statusPayload.usageBudget ? { usageBudget: statusPayload.usageBudget } : {}),
|
|
4309
|
+
...(statusPayload.checkpoint ? { checkpoint: statusPayload.checkpoint } : {}),
|
|
4310
|
+
...(stopped ? { stopped: true, error: stopMessage } : timedOut ? { timedOut: true, error: timeoutMessage ?? "Subagent timed out." } : turnBudgetExceeded ? { error: statusPayload.error ?? "Subagent exceeded turn budget." } : usageBudgetExceeded ? { error: statusPayload.error ?? "Usage budget exhausted." } : {}),
|
|
4035
4311
|
results: results.map((r) => ({
|
|
4036
4312
|
agent: r.agent,
|
|
4037
4313
|
context: r.context,
|
|
4038
4314
|
output: r.output,
|
|
4315
|
+
outputState: r.outputState,
|
|
4039
4316
|
error: r.error,
|
|
4040
4317
|
protocolError: r.protocolError,
|
|
4041
4318
|
success: r.success,
|
|
@@ -4043,6 +4320,7 @@ async function runSubagent(
|
|
|
4043
4320
|
interrupted: r.interrupted || undefined,
|
|
4044
4321
|
timedOut: r.timedOut || undefined,
|
|
4045
4322
|
stopped: r.stopped || undefined,
|
|
4323
|
+
processSignal: r.processSignal || undefined,
|
|
4046
4324
|
turnBudget: r.turnBudget,
|
|
4047
4325
|
turnBudgetExceeded: r.turnBudgetExceeded || undefined,
|
|
4048
4326
|
wrapUpRequested: r.wrapUpRequested || undefined,
|
|
@@ -4060,6 +4338,8 @@ async function runSubagent(
|
|
|
4060
4338
|
transcriptError: r.transcriptError,
|
|
4061
4339
|
agentContract: r.agentContract,
|
|
4062
4340
|
launchContractDigest: r.launchContractDigest,
|
|
4341
|
+
launchResolvedExtensions: r.launchResolvedExtensions,
|
|
4342
|
+
runtimeAcknowledgedExtensions: r.runtimeAcknowledgedExtensions,
|
|
4063
4343
|
execution: r.execution,
|
|
4064
4344
|
review: r.review,
|
|
4065
4345
|
effects: r.effects,
|
|
@@ -4076,16 +4356,20 @@ async function runSubagent(
|
|
|
4076
4356
|
parallelHandoff: statusPayload.parallelHandoff,
|
|
4077
4357
|
capabilityCeiling: statusPayload.capabilityCeiling,
|
|
4078
4358
|
capabilityAudit: statusPayload.capabilityAudit,
|
|
4079
|
-
exitCode: stopped || timedOut || turnBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
|
|
4359
|
+
exitCode: checkpointRejected || stopped || timedOut || turnBudgetExceeded || usageBudgetExceeded ? 1 : interrupted || results.every((r) => r.success) ? 0 : 1,
|
|
4080
4360
|
timestamp: runEndedAt,
|
|
4081
4361
|
durationMs: runEndedAt - overallStartTime,
|
|
4082
4362
|
totalTokens: statusPayload.totalTokens,
|
|
4083
4363
|
totalCost: finalTotalCost,
|
|
4364
|
+
usageBudget: statusPayload.usageBudget,
|
|
4365
|
+
checkpoint: statusPayload.checkpoint,
|
|
4084
4366
|
truncated,
|
|
4085
4367
|
artifactsDir,
|
|
4086
4368
|
cwd,
|
|
4087
4369
|
asyncDir,
|
|
4088
4370
|
launchContractDigest: config.launchContractDigest,
|
|
4371
|
+
launchResolvedExtensions: config.launchResolvedExtensions,
|
|
4372
|
+
runtimeAcknowledgedExtensions: singleRuntimeAcknowledgedExtensions,
|
|
4089
4373
|
sessionId: config.sessionId,
|
|
4090
4374
|
sessionFile: effectiveSessionFile,
|
|
4091
4375
|
intercomTarget: config.controlIntercomTarget,
|