@sema-agent/core 7.5.2 → 7.6.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 +41 -0
- package/dist/agents/cascade.d.ts +2 -2
- package/dist/agents/cascade.js +12 -10
- package/dist/agents/repair-loop.d.ts +5 -3
- package/dist/agents/repair-loop.js +13 -15
- package/dist/agents/subagent.d.ts +24 -42
- package/dist/agents/subagent.js +119 -105
- package/dist/agents/suspend-guard.d.ts +31 -19
- package/dist/agents/suspend-guard.js +14 -8
- package/dist/agents/teacher.js +9 -9
- package/dist/agents/team.d.ts +4 -3
- package/dist/agents/team.js +10 -8
- package/dist/agents/verify.d.ts +3 -3
- package/dist/agents/verify.js +17 -17
- package/dist/core/a2a.js +2 -1
- package/dist/core/ask-origin.d.ts +60 -7
- package/dist/core/ask-origin.js +26 -1
- package/dist/core/checkpoint-store.d.ts +78 -76
- package/dist/core/checkpoint-store.js +17 -1
- package/dist/core/gate-outcome.d.ts +189 -0
- package/dist/core/gate-outcome.js +70 -0
- package/dist/core/hooks.d.ts +18 -92
- package/dist/core/hooks.js +88 -85
- package/dist/core/mcp-failure.d.ts +104 -0
- package/dist/core/mcp-failure.js +128 -0
- package/dist/core/mcp.d.ts +21 -77
- package/dist/core/mcp.js +76 -150
- package/dist/core/pause-registry.d.ts +131 -0
- package/dist/core/pause-registry.js +27 -0
- package/dist/core/runner/assemble-result.d.ts +32 -41
- package/dist/core/runner/assemble-result.js +55 -74
- package/dist/core/runner/contracts.d.ts +46 -64
- package/dist/core/runner/denial-limit-arms.d.ts +1 -1
- package/dist/core/runner/denial-limit-arms.js +3 -3
- package/dist/core/runner/gate-exit.d.ts +74 -0
- package/dist/core/runner/gate-exit.js +55 -0
- package/dist/core/runner/park-commit.d.ts +17 -23
- package/dist/core/runner/park-commit.js +14 -15
- package/dist/core/runner/prepare-ask-lane.d.ts +0 -3
- package/dist/core/runner/prepare-ask-lane.js +3 -5
- package/dist/core/runner/prepare-boundary-parks.d.ts +3 -6
- package/dist/core/runner/prepare-boundary-parks.js +3 -3
- package/dist/core/runner/prepare-caps-and-workflow.js +1 -1
- package/dist/core/runner/prepare-gate-stations.d.ts +4 -7
- package/dist/core/runner/prepare-gate-stations.js +29 -54
- package/dist/core/runner/prepare-inherited-gate.js +1 -1
- package/dist/core/runner/prepare-memory.d.ts +44 -26
- package/dist/core/runner/prepare-park-ask.d.ts +2 -4
- package/dist/core/runner/prepare-park-ask.js +5 -5
- package/dist/core/runner/prepare-task.js +8 -9
- package/dist/core/runner/prepare-wiring-manifest.d.ts +7 -15
- package/dist/core/runner/prepare-wiring-manifest.js +9 -10
- package/dist/core/runner/runtask.d.ts +16 -31
- package/dist/core/runner/runtask.js +109 -120
- package/dist/core/runner/terminal-projection.d.ts +22 -0
- package/dist/core/runner/terminal-projection.js +28 -0
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +4 -1
- package/dist/core/store-contracts/checkpoint-store-contract.js +8 -2
- package/dist/core/terminal-cause.d.ts +137 -0
- package/dist/core/terminal-cause.js +9 -0
- package/dist/core/tool-policy.d.ts +43 -139
- package/dist/core/tool-policy.js +79 -112
- package/dist/core/types.d.ts +67 -164
- package/dist/core/wiring-manifest.d.ts +6 -3
- package/dist/core/workflow-journal-store.js +3 -4
- package/dist/engine/harness/agent-harness.d.ts +1 -1
- package/dist/index.d.ts +10 -7
- package/dist/index.js +8 -5
- package/dist/orchestration/builtin-workflows.d.ts +2 -2
- package/dist/orchestration/builtin-workflows.js +1 -1
- package/dist/orchestration/goal.js +8 -7
- package/dist/orchestration/run-spec.js +5 -3
- package/dist/orchestration/run-workflow-tool.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.js +4 -4
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-governance.js +4 -2
- package/dist/orchestration/workflow-primitives.d.ts +1 -1
- package/dist/orchestration/workflow-primitives.js +1 -1
- package/dist/orchestration/workflow.d.ts +11 -0
- package/dist/orchestration/workflow.js +64 -39
- package/dist/prompts/supervisor.d.ts +1 -1
- package/dist/prompts/supervisor.js +3 -3
- package/dist/scenarios/scenario-registry.js +1 -1
- package/package.json +3 -1
- package/test/export-surface.snapshot.json +74 -22
package/dist/agents/subagent.js
CHANGED
|
@@ -14,7 +14,8 @@ import { resolveToolSubset, toolNameAllowed } from "./tool-filter.js";
|
|
|
14
14
|
import { builtinAgentDefinitions } from "./builtin-agents.js";
|
|
15
15
|
import { SUBAGENT_PROMPT } from "../prompts/default.js";
|
|
16
16
|
import { hasSessionFork } from "../core/session.js";
|
|
17
|
-
import { isDurablePause } from "./suspend-guard.js";
|
|
17
|
+
import { isDurablePause, pauseFamily } from "./suspend-guard.js";
|
|
18
|
+
import { terminalProjection } from "../core/runner/terminal-projection.js";
|
|
18
19
|
import { delimitUntrusted, inlineUntrusted } from "../core/untrusted-text.js";
|
|
19
20
|
import { createSafeNotifier } from "../core/safe-notify.js";
|
|
20
21
|
import { boundedRedactedSummary } from "../core/untrusted-egress.js";
|
|
@@ -23,7 +24,6 @@ import { addWorktree } from "../core/git-worktree-env.js";
|
|
|
23
24
|
import { shellQuote } from "../tools/fs/search.js";
|
|
24
25
|
import { BG_AGENT_REAP_STOP_ERROR } from "../core/task-registry.js";
|
|
25
26
|
import { readDurableOrgAdmission } from "../core/memory-admission.js";
|
|
26
|
-
import { extractErrorCode } from "../brain/errors.js";
|
|
27
27
|
import { governanceRetryClass } from "../core/governance-codes.js";
|
|
28
28
|
import { RETAIN_DEFAULT_TTL_MS, RETAIN_DEFAULT_MAX, RUNNING_AGENT_OBSERVE_EVERY_BEATS, DELEGATION_MAX_CONCURRENT_DEFAULT, DELEGATION_MAX_PER_SESSION_DEFAULT } from "../config/defaults.js";
|
|
29
29
|
function rollupDelegatedCost(stats, nested) {
|
|
@@ -349,39 +349,54 @@ function configError(message, code) {
|
|
|
349
349
|
e.code = code;
|
|
350
350
|
return e;
|
|
351
351
|
}
|
|
352
|
-
export
|
|
353
|
-
|
|
352
|
+
export const SUBAGENT_ERROR_KINDS = ["rate_limit", "timeout", "network", "logic", "governance", "unknown"];
|
|
353
|
+
const SUBAGENT_ERROR_KIND_BY_CODE = {
|
|
354
|
+
rate_limit: "rate_limit",
|
|
355
|
+
server: "network",
|
|
356
|
+
network: "network",
|
|
357
|
+
"limits.max_walltime_exceeded": "timeout",
|
|
358
|
+
};
|
|
359
|
+
const SUBAGENT_RETRYABLE = {
|
|
360
|
+
rate_limit: true,
|
|
361
|
+
timeout: true,
|
|
362
|
+
network: true,
|
|
363
|
+
logic: false,
|
|
364
|
+
governance: false,
|
|
365
|
+
unknown: false,
|
|
366
|
+
};
|
|
367
|
+
export function classifySubagentError(terminal) {
|
|
368
|
+
if (terminal.kind !== "failed")
|
|
354
369
|
return undefined;
|
|
355
|
-
const code =
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return { errorKind, retryable: errorKind === "governance" ? governanceClass === "transient" : errorKind !== "logic" };
|
|
370
|
+
const code = terminal.code;
|
|
371
|
+
if (code === undefined)
|
|
372
|
+
return { errorKind: "unknown", retryable: SUBAGENT_RETRYABLE.unknown };
|
|
373
|
+
const own = SUBAGENT_ERROR_KIND_BY_CODE[code];
|
|
374
|
+
if (own !== undefined)
|
|
375
|
+
return { errorKind: own, retryable: SUBAGENT_RETRYABLE[own] };
|
|
376
|
+
const governanceClass = governanceRetryClass(code);
|
|
377
|
+
if (governanceClass !== undefined)
|
|
378
|
+
return { errorKind: "governance", retryable: governanceClass === "transient" };
|
|
379
|
+
return { errorKind: "logic", retryable: SUBAGENT_RETRYABLE.logic };
|
|
380
|
+
}
|
|
381
|
+
function thrownErrorCode(e) {
|
|
382
|
+
const code = e !== null && typeof e === "object" ? e.code : undefined;
|
|
383
|
+
return typeof code === "string" ? code : undefined;
|
|
370
384
|
}
|
|
371
385
|
export function completedAgentCard(child, extras) {
|
|
386
|
+
const face = terminalProjection(child.terminal);
|
|
372
387
|
return {
|
|
373
388
|
type: "agent",
|
|
374
389
|
...(extras.attestation !== undefined ? { attestation: extras.attestation } : {}),
|
|
375
390
|
...(extras.subagentType !== undefined ? { subagent_type: extras.subagentType } : {}),
|
|
376
|
-
status:
|
|
391
|
+
status: face.status,
|
|
377
392
|
taskId: child.taskId,
|
|
378
393
|
sessionId: child.sessionId,
|
|
379
394
|
result: child.result,
|
|
380
395
|
...(child.salvagedOutput !== undefined ? { salvagedOutput: child.salvagedOutput } : {}),
|
|
381
396
|
...(child.structuredOutput !== undefined ? { structuredOutput: child.structuredOutput } : {}),
|
|
382
|
-
...(
|
|
383
|
-
...(
|
|
384
|
-
...(
|
|
397
|
+
...(face.blockedReason !== undefined ? { blockedReason: face.blockedReason } : {}),
|
|
398
|
+
...(face.errorMessage !== undefined ? { errorMessage: face.errorMessage } : {}),
|
|
399
|
+
...(face.errorCode !== undefined ? { errorCode: face.errorCode } : {}),
|
|
385
400
|
...providerFaultField(child),
|
|
386
401
|
...(child.retryAfterMs !== undefined ? { retryAfterMs: child.retryAfterMs } : {}),
|
|
387
402
|
...(child.degraded !== undefined ? { degraded: child.degraded } : {}),
|
|
@@ -397,16 +412,15 @@ export function completedAgentCard(child, extras) {
|
|
|
397
412
|
export const SUBAGENT_SUSPENDED_AWAITING_APPROVAL = "suspended.awaiting_approval";
|
|
398
413
|
export const SUBAGENT_SUSPENDED_NEEDS_REVIEW = "suspended.needs_review";
|
|
399
414
|
export const SUBAGENT_SUSPENDED_CHECKPOINT_EXPIRED = "suspended.checkpoint_expired";
|
|
400
|
-
function durablePauseDelegationReport(reportLabel,
|
|
401
|
-
const needsReview =
|
|
402
|
-
const token =
|
|
415
|
+
function durablePauseDelegationReport(reportLabel, paused) {
|
|
416
|
+
const needsReview = pauseFamily(paused) === "needs_review";
|
|
417
|
+
const token = paused.token;
|
|
403
418
|
return {
|
|
404
419
|
isError: true,
|
|
405
420
|
content: `[Sub-agent report${reportLabel}]\n` +
|
|
406
421
|
`status: suspended\n` +
|
|
407
422
|
`This delegation is PARKED at an approval gate — it did not fail, and it is not finished. ` +
|
|
408
|
-
`${needsReview ? "A human review" : "An approval"} it cannot grant itself is pending` +
|
|
409
|
-
`${token !== undefined ? `, held by checkpoint ${token}` : " (the run reported no checkpoint token)"}. ` +
|
|
423
|
+
`${needsReview ? "A human review" : "An approval"} it cannot grant itself is pending, held by checkpoint ${token}. ` +
|
|
410
424
|
`The gated action has NOT run.\n` +
|
|
411
425
|
`Only the deployment's approval channel can release it: you cannot approve it from here, and no ` +
|
|
412
426
|
`result from it will arrive in this turn. Do not re-issue the same approval-gated action — an ` +
|
|
@@ -414,7 +428,7 @@ function durablePauseDelegationReport(reportLabel, child) {
|
|
|
414
428
|
`this delegation, or report that it is awaiting approval.`,
|
|
415
429
|
details: {
|
|
416
430
|
error: needsReview ? SUBAGENT_SUSPENDED_NEEDS_REVIEW : SUBAGENT_SUSPENDED_AWAITING_APPROVAL,
|
|
417
|
-
|
|
431
|
+
checkpointToken: token,
|
|
418
432
|
},
|
|
419
433
|
};
|
|
420
434
|
}
|
|
@@ -698,7 +712,8 @@ export function createSubagentResume(deps) {
|
|
|
698
712
|
for await (const _ of stream)
|
|
699
713
|
void _;
|
|
700
714
|
const child = await stream.result();
|
|
701
|
-
|
|
715
|
+
const childFace = terminalProjection(child.terminal);
|
|
716
|
+
let status = child.terminal.kind === "completed" ? "completed" : abort.signal.aborted ? "killed" : "failed";
|
|
702
717
|
const resumeHandbackWarning = await reviewHandback({
|
|
703
718
|
review: deps.currentAutoModeReview,
|
|
704
719
|
toolCallId: deps.parentToolCallId,
|
|
@@ -707,16 +722,14 @@ export function createSubagentResume(deps) {
|
|
|
707
722
|
signal: abort.signal,
|
|
708
723
|
});
|
|
709
724
|
const resumeHandbackResult = withHandbackWarning(resumeHandbackWarning, child.result);
|
|
710
|
-
const errCodeRevive = status === "failed" ?
|
|
711
|
-
const errClassRevive = status === "failed"
|
|
712
|
-
? classifySubagentError({ status: "failed", ...(child.errorCode !== undefined ? { errorCode: child.errorCode } : {}), ...(child.errorMessage !== undefined ? { errorMessage: child.errorMessage } : {}) })
|
|
713
|
-
: undefined;
|
|
725
|
+
const errCodeRevive = status === "failed" ? childFace.errorCode : undefined;
|
|
726
|
+
const errClassRevive = status === "failed" ? classifySubagentError({ kind: "failed", ...(childFace.errorCode !== undefined ? { code: childFace.errorCode } : {}) }) : undefined;
|
|
714
727
|
if (reviveCycle !== undefined && deps.registry !== undefined && deps.taskId !== undefined) {
|
|
715
728
|
try {
|
|
716
729
|
const winner = deps.registry.settleRevivedAgent(deps.taskId, reviveCycle, {
|
|
717
730
|
status,
|
|
718
731
|
...resultSettleFields(resumeHandbackResult),
|
|
719
|
-
...(status !== "completed" ? { error: (
|
|
732
|
+
...(status !== "completed" ? { error: (childFace.errorMessage ?? `resumed run ${status}`).slice(0, 500) } : {}),
|
|
720
733
|
...(errCodeRevive !== undefined ? { errorCode: errCodeRevive } : {}),
|
|
721
734
|
...(errClassRevive !== undefined ? { retryable: errClassRevive.retryable, errorKind: errClassRevive.errorKind } : {}),
|
|
722
735
|
});
|
|
@@ -729,11 +742,11 @@ export function createSubagentResume(deps) {
|
|
|
729
742
|
const stoppedByRevive = status === "killed" ? deps.registry?.getStopAttribution(deps.taskId ?? "") ?? "system" : undefined;
|
|
730
743
|
const completionIdRevive = deps.registry?.getCompletionId(deps.taskId ?? "");
|
|
731
744
|
const reviveName = deps.rowDescription ?? `sub-agent ${marker}`;
|
|
732
|
-
const failReasonRevive = status === "failed" ?
|
|
745
|
+
const failReasonRevive = status === "failed" ? childFace.errorMessage : undefined;
|
|
733
746
|
const reviveElapsedMs = Date.now() - reviveStartedAt;
|
|
734
747
|
const reviveTerminalSummary = failReasonRevive !== undefined
|
|
735
748
|
? `Agent "${reviveName}" (resumed) failed: ${failReasonRevive}${ccElapsedTag(reviveElapsedMs)}`.slice(0, 300) + errorKindClause(errClassRevive)
|
|
736
|
-
: `Agent "${reviveName}" (resumed) ${status === "killed" ? "stopped" : child.
|
|
749
|
+
: `Agent "${reviveName}" (resumed) ${status === "killed" ? "stopped" : child.terminal.kind === "completed" ? "finished" : childFace.status}${ccElapsedTag(reviveElapsedMs)}`;
|
|
737
750
|
const reviveDurableProbe = deps.registry !== undefined && deps.taskId !== undefined ? deps.registry.durableAgentRowProbe(deps.taskId) : undefined;
|
|
738
751
|
const reviveDurableRow = reviveDurableProbe !== undefined ? await reviveDurableProbe().catch(() => false) : false;
|
|
739
752
|
const resumableRevive = resumabilityClaim({
|
|
@@ -805,8 +818,8 @@ export function createSubagentResume(deps) {
|
|
|
805
818
|
}
|
|
806
819
|
catch (e) {
|
|
807
820
|
const msgRevive = e instanceof Error ? e.message : String(e);
|
|
808
|
-
const errCodeReviveReject = abort.signal.aborted ? undefined :
|
|
809
|
-
const errClassReviveReject = abort.signal.aborted ? undefined : classifySubagentError({
|
|
821
|
+
const errCodeReviveReject = abort.signal.aborted ? undefined : thrownErrorCode(e);
|
|
822
|
+
const errClassReviveReject = abort.signal.aborted ? undefined : classifySubagentError({ kind: "failed", ...(errCodeReviveReject !== undefined ? { code: errCodeReviveReject } : {}) });
|
|
810
823
|
if (reviveCycle !== undefined && deps.registry !== undefined && deps.taskId !== undefined) {
|
|
811
824
|
try {
|
|
812
825
|
deps.registry.settleRevivedAgent(deps.taskId, reviveCycle, {
|
|
@@ -1896,11 +1909,11 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1896
1909
|
if (!isObserverTaskId(sid))
|
|
1897
1910
|
throw new ObserverStoppedByUserError("observer identity revoked — delivery refused");
|
|
1898
1911
|
const r = await opts.runner.runTask(spec, ctx.interactionPosture !== undefined ? { parentInteractionPosture: ctx.interactionPosture } : undefined);
|
|
1899
|
-
if (r.
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
throw new Error(`observer run ended ${r.status}${
|
|
1912
|
+
if (r.terminal.kind !== "completed") {
|
|
1913
|
+
const failedText = r.terminal.kind === "failed" && r.terminal.message ? `: ${r.terminal.message}` : "";
|
|
1914
|
+
if (r.terminal.kind === "failed" && r.terminal.code === "resume.session_not_found")
|
|
1915
|
+
throw new ObserverResumeStateError(`observer session no longer exists${failedText}`);
|
|
1916
|
+
throw new Error(`observer run ended ${terminalProjection(r.terminal).status}${failedText}`);
|
|
1904
1917
|
}
|
|
1905
1918
|
};
|
|
1906
1919
|
const spawner = {
|
|
@@ -2047,7 +2060,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2047
2060
|
});
|
|
2048
2061
|
const provenanceRequest = ctx.delegationProvenanceForChildren?.();
|
|
2049
2062
|
const childProvenanceRef = provenanceRequest !== undefined ? { current: newDelegationProvenanceAggregate() } : undefined;
|
|
2050
|
-
const childAttestation = (
|
|
2063
|
+
const childAttestation = (completed) => childProvenanceRef !== undefined ? reduceDelegationAttestation(childProvenanceRef.current, { completed }) : undefined;
|
|
2051
2064
|
const liveCaptureFloor = reviveClaim === undefined
|
|
2052
2065
|
? { optedOut: (await ctx.memoryCaptureOptedOut) === true, indeterminate: (await ctx.memoryCaptureIndeterminate) === true }
|
|
2053
2066
|
: undefined;
|
|
@@ -2135,7 +2148,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2135
2148
|
...(def?.memory ? { memory: def.memory } : {}),
|
|
2136
2149
|
...(def?.skills?.length ? { skills: def.skills } : {}),
|
|
2137
2150
|
...(ctx.principal !== undefined ? { principal: ctx.principal } : {}),
|
|
2138
|
-
...(ctx.checkpointStoreDisabledForChildren === true ? { checkpointStore:
|
|
2151
|
+
...(ctx.checkpointStoreDisabledForChildren === true ? { checkpointStore: "disabled" } : {}),
|
|
2139
2152
|
...(childOnAsk !== undefined ? { onAsk: childOnAsk } : {}),
|
|
2140
2153
|
...(ctx.onQuestion !== undefined ? { onQuestion: ctx.onQuestion } : {}),
|
|
2141
2154
|
...(ctx.interactiveTools === false ? { interactiveTools: false } : {}),
|
|
@@ -2409,10 +2422,10 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2409
2422
|
};
|
|
2410
2423
|
}
|
|
2411
2424
|
}
|
|
2412
|
-
const settleForkRow = (
|
|
2425
|
+
const settleForkRow = (terminal) => {
|
|
2413
2426
|
if (forkSettlementSeat === undefined || forkSettleId === undefined)
|
|
2414
2427
|
return;
|
|
2415
|
-
const att =
|
|
2428
|
+
const att = terminal !== undefined ? childAttestation(terminal.kind === "completed") : undefined;
|
|
2416
2429
|
const verdict = att === "external" ? "external" : att === "clean" ? "clean" : "unattestable";
|
|
2417
2430
|
let settled = false;
|
|
2418
2431
|
let lastErr;
|
|
@@ -2629,7 +2642,8 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2629
2642
|
void opts.runner
|
|
2630
2643
|
.runTask(bgForkSpec, bgForkInternals)
|
|
2631
2644
|
.then(async (child) => {
|
|
2632
|
-
|
|
2645
|
+
const childFace = terminalProjection(child.terminal);
|
|
2646
|
+
settleForkRow(child.terminal);
|
|
2633
2647
|
dropHostAbortListener();
|
|
2634
2648
|
await finishWorktree();
|
|
2635
2649
|
try {
|
|
@@ -2651,25 +2665,23 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2651
2665
|
signal: abort.signal,
|
|
2652
2666
|
});
|
|
2653
2667
|
const forkBgResult = withHandbackWarning(forkBgWarning, child.result);
|
|
2654
|
-
const okBg = child.
|
|
2668
|
+
const okBg = child.terminal.kind === "completed";
|
|
2655
2669
|
const reapedBg = !okBg && abort.signal.aborted;
|
|
2656
2670
|
const collateralBg = reapedBg && bg.registry.getAccessibleTask(taskId, { ...(bgOwner !== undefined ? { owner: bgOwner } : {}), ...(bgScope !== undefined ? { scope: bgScope } : {}) })?.status === "running";
|
|
2657
2671
|
const failedFork = !okBg && !reapedBg;
|
|
2658
|
-
const errCodeFork = failedFork ?
|
|
2659
|
-
const errClassFork = failedFork
|
|
2660
|
-
? classifySubagentError({ status: "failed", ...(child.errorCode !== undefined ? { errorCode: child.errorCode } : {}), ...(child.errorMessage !== undefined ? { errorMessage: child.errorMessage } : {}) })
|
|
2661
|
-
: undefined;
|
|
2672
|
+
const errCodeFork = failedFork ? childFace.errorCode : undefined;
|
|
2673
|
+
const errClassFork = failedFork ? classifySubagentError({ kind: "failed", ...(childFace.errorCode !== undefined ? { code: childFace.errorCode } : {}) }) : undefined;
|
|
2662
2674
|
const settledBg = bg.registry.settleBackgroundAgent(taskId, {
|
|
2663
2675
|
cycle: 0,
|
|
2664
2676
|
status: okBg ? "completed" : reapedBg ? "killed" : "failed",
|
|
2665
2677
|
...resultSettleFields(forkBgResult),
|
|
2666
|
-
...(!okBg ? { error: reapedBg ? (collateralBg ? BG_AGENT_COLLATERAL_REAP_REASON : BG_AGENT_REAP_STOP_ERROR) :
|
|
2678
|
+
...(!okBg ? { error: reapedBg ? (collateralBg ? BG_AGENT_COLLATERAL_REAP_REASON : BG_AGENT_REAP_STOP_ERROR) : childFace.errorMessage ?? childFace.status } : {}),
|
|
2667
2679
|
...(errCodeFork !== undefined ? { errorCode: errCodeFork } : {}),
|
|
2668
2680
|
...(errClassFork !== undefined ? { retryable: errClassFork.retryable, errorKind: errClassFork.errorKind } : {}),
|
|
2669
2681
|
}) ?? (abort.signal.aborted ? "killed" : okBg ? "completed" : "failed");
|
|
2670
2682
|
const stoppedByBg = settledBg === "killed" ? bg.registry.getStopAttribution(taskId) ?? "system" : undefined;
|
|
2671
2683
|
const completionIdFork = bg.registry.getCompletionId(taskId);
|
|
2672
|
-
const stillbornFork = child.
|
|
2684
|
+
const stillbornFork = child.terminal.kind === "failed" && child.terminal.code === "resume.session_not_found";
|
|
2673
2685
|
if (stillbornFork) {
|
|
2674
2686
|
try {
|
|
2675
2687
|
await (releaseForked ? releaseForked() : opts.runner.sessions.release?.(forkedId));
|
|
@@ -2680,11 +2692,11 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2680
2692
|
const residualFork = residualFields();
|
|
2681
2693
|
const resumableFork = false;
|
|
2682
2694
|
const forkTranscriptId = child.sessionId ?? forkedId;
|
|
2683
|
-
const failReasonFork = settledBg === "failed" ?
|
|
2695
|
+
const failReasonFork = settledBg === "failed" ? childFace.errorMessage : undefined;
|
|
2684
2696
|
const forkElapsedMs = Date.now() - forkBgStartedAt;
|
|
2685
2697
|
const forkTerminalSummary = failReasonFork !== undefined
|
|
2686
2698
|
? `Agent "${shortDesc}" failed: ${failReasonFork}${ccElapsedTag(forkElapsedMs)}`.slice(0, 300) + errorKindClause(errClassFork)
|
|
2687
|
-
: `${ccCompletionText(shortDesc, settledBg,
|
|
2699
|
+
: `${ccCompletionText(shortDesc, settledBg, childFace.status, forkElapsedMs)}`;
|
|
2688
2700
|
const ownsTerminalFacesFork = bg.registry.claimAgentTerminalNotify(taskId);
|
|
2689
2701
|
if (ownsTerminalFacesFork)
|
|
2690
2702
|
sinkEmit({
|
|
@@ -2728,13 +2740,13 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2728
2740
|
}
|
|
2729
2741
|
})
|
|
2730
2742
|
.catch((e) => {
|
|
2731
|
-
settleForkRow("failed");
|
|
2743
|
+
settleForkRow({ kind: "failed" });
|
|
2732
2744
|
dropHostAbortListener();
|
|
2733
2745
|
void finishWorktree();
|
|
2734
2746
|
const killed = abort.signal.aborted;
|
|
2735
2747
|
const msgFork = e instanceof Error ? e.message : String(e);
|
|
2736
|
-
const errCodeForkReject = killed ? undefined :
|
|
2737
|
-
const errClassForkReject = killed ? undefined : classifySubagentError({
|
|
2748
|
+
const errCodeForkReject = killed ? undefined : thrownErrorCode(e);
|
|
2749
|
+
const errClassForkReject = killed ? undefined : classifySubagentError({ kind: "failed", ...(errCodeForkReject !== undefined ? { code: errCodeForkReject } : {}) });
|
|
2738
2750
|
const settledBg = bg.registry.settleBackgroundAgent(taskId, {
|
|
2739
2751
|
cycle: 0,
|
|
2740
2752
|
status: killed ? "killed" : "failed",
|
|
@@ -2826,7 +2838,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2826
2838
|
let forkChild;
|
|
2827
2839
|
try {
|
|
2828
2840
|
forkChild = await opts.runner.runTask({ ...buildChildSpec(ctx.signal), sessionId: forkedId, requireExistingSession: true, objective: forkObjective }, forkInternals);
|
|
2829
|
-
if (forkChild.
|
|
2841
|
+
if (forkChild.terminal.kind === "failed" && forkChild.terminal.code === "resume.session_not_found") {
|
|
2830
2842
|
try {
|
|
2831
2843
|
await (releaseForked ? releaseForked() : opts.runner.sessions.release?.(forkedId));
|
|
2832
2844
|
}
|
|
@@ -2860,21 +2872,22 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2860
2872
|
tasks: 1 + (nsf?.tasks ?? 0),
|
|
2861
2873
|
costMicroUsd: rollupDelegatedCost(forkChild.stats, nsf),
|
|
2862
2874
|
});
|
|
2863
|
-
if (isDurablePause(forkChild.
|
|
2864
|
-
return durablePauseDelegationReport(` · ${FORK_SUBAGENT_TYPE}`, forkChild);
|
|
2875
|
+
if (isDurablePause(forkChild.terminal)) {
|
|
2876
|
+
return durablePauseDelegationReport(` · ${FORK_SUBAGENT_TYPE}`, forkChild.terminal);
|
|
2865
2877
|
}
|
|
2866
2878
|
const wtLine = await finishWorktree();
|
|
2867
|
-
const
|
|
2879
|
+
const forkFace = terminalProjection(forkChild.terminal);
|
|
2880
|
+
const forkErr = classifySubagentError(forkChild.terminal);
|
|
2868
2881
|
const forkLines = [
|
|
2869
2882
|
...(forkHandbackWarning ? [forkHandbackWarning, ""] : []),
|
|
2870
2883
|
`[Sub-agent report · ${FORK_SUBAGENT_TYPE}${a.description ? ` · ${String(a.description)}` : ""}] (forked session …${forkedId.slice(-8)})`,
|
|
2871
|
-
`status: ${
|
|
2884
|
+
`status: ${forkFace.status}`,
|
|
2872
2885
|
modelNote ?? "",
|
|
2873
2886
|
extraToolsNote ?? "",
|
|
2874
2887
|
bgIgnoredNote ?? "",
|
|
2875
2888
|
wtLine ?? "",
|
|
2876
|
-
|
|
2877
|
-
|
|
2889
|
+
forkFace.blockedReason ? `blocked_reason: ${inlineUntrusted(forkFace.blockedReason, REPORT_FIELD_MAX)}` : "",
|
|
2890
|
+
forkFace.errorMessage ? `error: ${inlineUntrusted(forkFace.errorMessage, REPORT_FIELD_MAX)}` : "",
|
|
2878
2891
|
forkErr ? `error_kind: ${forkErr.errorKind} (retryable: ${forkErr.retryable})` : "",
|
|
2879
2892
|
`stats: turns=${forkChild.stats.turns} tokens=${forkChild.stats.tokens}`,
|
|
2880
2893
|
"",
|
|
@@ -2889,7 +2902,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2889
2902
|
subagentType: FORK_SUBAGENT_TYPE,
|
|
2890
2903
|
error: forkErr,
|
|
2891
2904
|
...(() => {
|
|
2892
|
-
const a = childAttestation(forkChild.
|
|
2905
|
+
const a = childAttestation(forkChild.terminal.kind === "completed");
|
|
2893
2906
|
return a !== undefined ? { attestation: a } : {};
|
|
2894
2907
|
})(),
|
|
2895
2908
|
...(forkHandbackWarning !== undefined ? { handbackWarning: forkHandbackWarning } : {}),
|
|
@@ -2948,10 +2961,10 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2948
2961
|
};
|
|
2949
2962
|
}
|
|
2950
2963
|
}
|
|
2951
|
-
const settleDelegationRow = (
|
|
2964
|
+
const settleDelegationRow = (terminal) => {
|
|
2952
2965
|
if (settlementSeat === undefined || bgSettleId === undefined)
|
|
2953
2966
|
return;
|
|
2954
|
-
const att =
|
|
2967
|
+
const att = terminal !== undefined ? childAttestation(terminal.kind === "completed") : undefined;
|
|
2955
2968
|
const verdict = att === "external" ? "external" : att === "clean" ? "clean" : "unattestable";
|
|
2956
2969
|
let settled = false;
|
|
2957
2970
|
let lastErr;
|
|
@@ -3347,7 +3360,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3347
3360
|
catch (e) {
|
|
3348
3361
|
return rollbackAndThrow(e);
|
|
3349
3362
|
}
|
|
3350
|
-
if (childResult.
|
|
3363
|
+
if (childResult.terminal.kind === "failed") {
|
|
3351
3364
|
let reopened = false;
|
|
3352
3365
|
try {
|
|
3353
3366
|
const cp = (await bg.checkpointStore.get(pr.ticket.token));
|
|
@@ -3367,7 +3380,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3367
3380
|
return await cpS.expire(pr.ticket.token, cp.scope);
|
|
3368
3381
|
},
|
|
3369
3382
|
});
|
|
3370
|
-
throw new Error(`parked resume could not complete and the approval was REOPENED (still approvable/retryable): ${childResult.
|
|
3383
|
+
throw new Error(`parked resume could not complete and the approval was REOPENED (still approvable/retryable): ${childResult.terminal.message ?? "failed"}`);
|
|
3371
3384
|
}
|
|
3372
3385
|
}
|
|
3373
3386
|
return childResult;
|
|
@@ -3387,8 +3400,9 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3387
3400
|
: opts.runner.runTask(bgSpec, bgInternals);
|
|
3388
3401
|
void bgChildPromise
|
|
3389
3402
|
.then(async (child) => {
|
|
3390
|
-
|
|
3391
|
-
|
|
3403
|
+
const childFace = terminalProjection(child.terminal);
|
|
3404
|
+
settleDelegationRow(child.terminal);
|
|
3405
|
+
closeObserverWindow(childFace.status);
|
|
3392
3406
|
dropHostAbortListener();
|
|
3393
3407
|
await finishWorktree();
|
|
3394
3408
|
try {
|
|
@@ -3403,7 +3417,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3403
3417
|
catch {
|
|
3404
3418
|
}
|
|
3405
3419
|
const seqAtSettle = bgRetain?.cycleSeq ?? (parkedResume !== undefined ? (reviveRow?.seq ?? 1) + 1 : reviveRow?.seq);
|
|
3406
|
-
const bgHandbackWarning = isDurablePause(child.
|
|
3420
|
+
const bgHandbackWarning = isDurablePause(child.terminal)
|
|
3407
3421
|
? undefined
|
|
3408
3422
|
: await reviewHandback({
|
|
3409
3423
|
review: ctx.autoModeReview,
|
|
@@ -3414,15 +3428,16 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3414
3428
|
});
|
|
3415
3429
|
const bgHandbackResult = withHandbackWarning(bgHandbackWarning, child.result);
|
|
3416
3430
|
if (bgRetain) {
|
|
3417
|
-
if (isDurablePause(child.
|
|
3431
|
+
if (isDurablePause(child.terminal))
|
|
3418
3432
|
bgRetainLedger?.abandon(ctx.toolCallId);
|
|
3419
|
-
else if (child.
|
|
3433
|
+
else if (child.terminal.kind !== "completed" && abort.signal.aborted)
|
|
3420
3434
|
void bgRetainLedger?.evict(ctx.toolCallId);
|
|
3421
3435
|
else
|
|
3422
3436
|
bgRetainLedger?.markSettled(ctx.toolCallId);
|
|
3423
3437
|
}
|
|
3424
3438
|
let unparkedPause;
|
|
3425
|
-
if (isDurablePause(child.
|
|
3439
|
+
if (isDurablePause(child.terminal)) {
|
|
3440
|
+
const pausedToken = child.terminal.token;
|
|
3426
3441
|
const cpStore = bg.checkpointStore;
|
|
3427
3442
|
const expireByStoreScope = async (token2) => {
|
|
3428
3443
|
try {
|
|
@@ -3437,7 +3452,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3437
3452
|
};
|
|
3438
3453
|
const wired = bg.agentStore !== undefined && cpStore !== undefined && bg.ensureChildSessionDurable !== undefined;
|
|
3439
3454
|
if (wired) {
|
|
3440
|
-
const token =
|
|
3455
|
+
const token = pausedToken;
|
|
3441
3456
|
if (abort.signal.aborted) {
|
|
3442
3457
|
await expireByStoreScope(token);
|
|
3443
3458
|
}
|
|
@@ -3470,10 +3485,10 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3470
3485
|
}
|
|
3471
3486
|
}
|
|
3472
3487
|
else {
|
|
3473
|
-
unparkedPause = { kind: "no_park_lane", checkpointToken:
|
|
3488
|
+
unparkedPause = { kind: "no_park_lane", checkpointToken: pausedToken };
|
|
3474
3489
|
}
|
|
3475
3490
|
}
|
|
3476
|
-
const ok = child.
|
|
3491
|
+
const ok = child.terminal.kind === "completed";
|
|
3477
3492
|
const reaped = !ok && abort.signal.aborted;
|
|
3478
3493
|
const collateral = reaped && bg.registry.getAccessibleTask(taskId, { ...(bgOwner !== undefined ? { owner: bgOwner } : {}), ...(bgScope !== undefined ? { scope: bgScope } : {}) })?.status === "running";
|
|
3479
3494
|
const failedBg = !ok && !reaped;
|
|
@@ -3481,21 +3496,19 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3481
3496
|
const errCodeBg = failedBg
|
|
3482
3497
|
? unparkedPause !== undefined
|
|
3483
3498
|
? unparkedPause.kind === "no_park_lane"
|
|
3484
|
-
? child.
|
|
3499
|
+
? child.terminal.kind === "paused" && pauseFamily(child.terminal) === "needs_review"
|
|
3485
3500
|
? SUBAGENT_SUSPENDED_NEEDS_REVIEW
|
|
3486
3501
|
: SUBAGENT_SUSPENDED_AWAITING_APPROVAL
|
|
3487
3502
|
: SUBAGENT_SUSPENDED_CHECKPOINT_EXPIRED
|
|
3488
|
-
:
|
|
3489
|
-
: undefined;
|
|
3490
|
-
const errClassBg = failedBg
|
|
3491
|
-
? classifySubagentError({ status: "failed", ...(child.errorCode !== undefined ? { errorCode: child.errorCode } : {}), ...(child.errorMessage !== undefined ? { errorMessage: child.errorMessage } : {}) })
|
|
3503
|
+
: childFace.errorCode
|
|
3492
3504
|
: undefined;
|
|
3505
|
+
const errClassBg = failedBg ? classifySubagentError({ kind: "failed", ...(childFace.errorCode !== undefined ? { code: childFace.errorCode } : {}) }) : undefined;
|
|
3493
3506
|
const settled = bg.registry.settleBackgroundAgent(taskId, {
|
|
3494
3507
|
cycle: 0,
|
|
3495
3508
|
status: ok ? "completed" : reaped ? "killed" : "failed",
|
|
3496
3509
|
seq: seqAtSettle ?? 1,
|
|
3497
3510
|
...resultSettleFields(bgHandbackResult),
|
|
3498
|
-
...(!ok ? { error: reaped ? (collateral ? BG_AGENT_COLLATERAL_REAP_REASON : BG_AGENT_REAP_STOP_ERROR) : unparkedPauseReason ??
|
|
3511
|
+
...(!ok ? { error: reaped ? (collateral ? BG_AGENT_COLLATERAL_REAP_REASON : BG_AGENT_REAP_STOP_ERROR) : unparkedPauseReason ?? childFace.errorMessage ?? childFace.status } : {}),
|
|
3499
3512
|
...(errCodeBg !== undefined ? { errorCode: errCodeBg } : {}),
|
|
3500
3513
|
...(errClassBg !== undefined ? { retryable: errClassBg.retryable, errorKind: errClassBg.errorKind } : {}),
|
|
3501
3514
|
...(failedBg && child.retryAfterMs !== undefined ? { retryAfterMs: child.retryAfterMs } : {}),
|
|
@@ -3522,11 +3535,11 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3522
3535
|
durableRow: bgDurableRow,
|
|
3523
3536
|
named: agentName !== undefined,
|
|
3524
3537
|
});
|
|
3525
|
-
const failReasonBg = settled === "failed" ? unparkedPauseReason ??
|
|
3538
|
+
const failReasonBg = settled === "failed" ? unparkedPauseReason ?? childFace.errorMessage : undefined;
|
|
3526
3539
|
const bgElapsedMs = Date.now() - bgStartedAt;
|
|
3527
3540
|
const bgTerminalSummary = failReasonBg !== undefined
|
|
3528
3541
|
? `Agent "${shortDesc}" failed: ${failReasonBg}${ccElapsedTag(bgElapsedMs)}${observerNote}`.slice(0, 300) + errorKindClause(errClassBg)
|
|
3529
|
-
: `${ccCompletionText(shortDesc, settled,
|
|
3542
|
+
: `${ccCompletionText(shortDesc, settled, childFace.status, bgElapsedMs)}${observerNote}`;
|
|
3530
3543
|
const ownsTerminalFaces = bg.registry.claimAgentTerminalNotify(taskId);
|
|
3531
3544
|
if (ownsTerminalFaces)
|
|
3532
3545
|
sinkEmit({
|
|
@@ -3584,7 +3597,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3584
3597
|
}
|
|
3585
3598
|
})
|
|
3586
3599
|
.catch(async (e) => {
|
|
3587
|
-
settleDelegationRow("failed");
|
|
3600
|
+
settleDelegationRow({ kind: "failed" });
|
|
3588
3601
|
closeObserverWindow("failed");
|
|
3589
3602
|
dropHostAbortListener();
|
|
3590
3603
|
void finishWorktree();
|
|
@@ -3597,8 +3610,8 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3597
3610
|
bgRetainLedger?.markSettled(ctx.toolCallId);
|
|
3598
3611
|
}
|
|
3599
3612
|
const msg = e instanceof Error ? e.message : String(e);
|
|
3600
|
-
const errCodeBgReject = killed ? undefined :
|
|
3601
|
-
const errClassBgReject = killed ? undefined : classifySubagentError({
|
|
3613
|
+
const errCodeBgReject = killed ? undefined : thrownErrorCode(e);
|
|
3614
|
+
const errClassBgReject = killed ? undefined : classifySubagentError({ kind: "failed", ...(errCodeBgReject !== undefined ? { code: errCodeBgReject } : {}) });
|
|
3602
3615
|
const settled = bg.registry.settleBackgroundAgent(taskId, {
|
|
3603
3616
|
cycle: 0,
|
|
3604
3617
|
status: killed ? "killed" : "failed",
|
|
@@ -3755,7 +3768,8 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3755
3768
|
finally {
|
|
3756
3769
|
syncAdmission.release();
|
|
3757
3770
|
}
|
|
3758
|
-
|
|
3771
|
+
const childFace = terminalProjection(child.terminal);
|
|
3772
|
+
await settleObserver(childFace.status);
|
|
3759
3773
|
const handbackWarning = await reviewHandback({
|
|
3760
3774
|
review: ctx.autoModeReview,
|
|
3761
3775
|
toolCallId: ctx.toolCallId,
|
|
@@ -3764,7 +3778,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3764
3778
|
result: child.result,
|
|
3765
3779
|
steps: stepRecorder.recentSteps(),
|
|
3766
3780
|
edits: stepRecorder.editedFiles(),
|
|
3767
|
-
...(child.result || child.
|
|
3781
|
+
...(child.result || child.terminal.kind === "completed" ? {} : { partialText: assistantTextTail.trim() }),
|
|
3768
3782
|
},
|
|
3769
3783
|
signal: ctx.signal,
|
|
3770
3784
|
});
|
|
@@ -3775,14 +3789,14 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3775
3789
|
tasks: 1 + (ns?.tasks ?? 0),
|
|
3776
3790
|
costMicroUsd: rollupDelegatedCost(child.stats, ns),
|
|
3777
3791
|
});
|
|
3778
|
-
if (isDurablePause(child.
|
|
3792
|
+
if (isDurablePause(child.terminal)) {
|
|
3779
3793
|
if (retainEntry)
|
|
3780
3794
|
ctx.subagentRetain?.abandon(ctx.toolCallId);
|
|
3781
|
-
return durablePauseDelegationReport(def ? ` · ${def.name}` : "", child);
|
|
3795
|
+
return durablePauseDelegationReport(def ? ` · ${def.name}` : "", child.terminal);
|
|
3782
3796
|
}
|
|
3783
3797
|
let failureRetained = false;
|
|
3784
3798
|
if (!retainEntry) {
|
|
3785
|
-
if (child.
|
|
3799
|
+
if (child.terminal.kind !== "completed" && opts.retainFailedSessions !== false) {
|
|
3786
3800
|
failureRetained = await retainFailedChildSession(child.sessionId);
|
|
3787
3801
|
}
|
|
3788
3802
|
if (!failureRetained) {
|
|
@@ -3794,16 +3808,16 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3794
3808
|
}
|
|
3795
3809
|
}
|
|
3796
3810
|
const worktreeLine = await finishWorktree();
|
|
3797
|
-
const errClass = classifySubagentError(child);
|
|
3811
|
+
const errClass = classifySubagentError(child.terminal);
|
|
3798
3812
|
const lines = [
|
|
3799
3813
|
...(handbackWarning ? [handbackWarning, ""] : []),
|
|
3800
3814
|
`[Sub-agent report${def ? ` · ${def.name}` : ""}${a.description ? ` · ${String(a.description)}` : ""}]`,
|
|
3801
|
-
`status: ${
|
|
3815
|
+
`status: ${childFace.status}`,
|
|
3802
3816
|
modelNote ?? "",
|
|
3803
3817
|
extraToolsNote ?? "",
|
|
3804
3818
|
worktreeLine ?? "",
|
|
3805
|
-
|
|
3806
|
-
|
|
3819
|
+
childFace.blockedReason ? `blocked_reason: ${inlineUntrusted(childFace.blockedReason, REPORT_FIELD_MAX)}` : "",
|
|
3820
|
+
childFace.errorMessage ? `error: ${inlineUntrusted(childFace.errorMessage, REPORT_FIELD_MAX)}` : "",
|
|
3807
3821
|
errClass ? `error_kind: ${errClass.errorKind} (retryable: ${errClass.retryable})` : "",
|
|
3808
3822
|
observerFailure !== undefined
|
|
3809
3823
|
? `observer: failed (${inlineUntrusted(observerFailure, REPORT_FIELD_MAX)})`
|
|
@@ -3816,7 +3830,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3816
3830
|
failureRetained
|
|
3817
3831
|
? `session_retained: this child's session is kept for a short time (~15 min) so its transcript stays inspectable via transcript_id; it is released automatically afterwards.`
|
|
3818
3832
|
: "",
|
|
3819
|
-
...(child.
|
|
3833
|
+
...(child.terminal.kind !== "completed"
|
|
3820
3834
|
? (() => {
|
|
3821
3835
|
const rs = stepRecorder.recentSteps();
|
|
3822
3836
|
const ef = stepRecorder.editedFiles();
|
|
@@ -3837,7 +3851,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3837
3851
|
"result:",
|
|
3838
3852
|
child.result
|
|
3839
3853
|
? delimitUntrusted("sub-agent result", child.result)
|
|
3840
|
-
: child.
|
|
3854
|
+
: child.terminal.kind !== "completed" && assistantTextTail.trim() !== ""
|
|
3841
3855
|
? `partial findings (the child's last assistant text before it stopped):\n${delimitUntrusted("sub-agent partial findings", assistantTextTail.trim())}`
|
|
3842
3856
|
: "(no text result)",
|
|
3843
3857
|
"",
|
|
@@ -3853,7 +3867,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
3853
3867
|
...(def !== undefined ? { subagentType: def.name } : {}),
|
|
3854
3868
|
error: errClass,
|
|
3855
3869
|
...(() => {
|
|
3856
|
-
const a = childAttestation(child.
|
|
3870
|
+
const a = childAttestation(child.terminal.kind === "completed");
|
|
3857
3871
|
return a !== undefined ? { attestation: a } : {};
|
|
3858
3872
|
})(),
|
|
3859
3873
|
...(handbackWarning !== undefined ? { handbackWarning } : {}),
|