@sema-agent/core 2.3.0 → 2.5.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/dist/agents/send-message-tool.d.ts +4 -0
- package/dist/agents/send-message-tool.js +37 -24
- package/dist/agents/subagent.js +279 -128
- package/dist/brain/errors.d.ts +1 -0
- package/dist/brain/errors.js +14 -0
- package/dist/brain/stream-engine.js +3 -3
- package/dist/core/auto-compaction.d.ts +2 -0
- package/dist/core/auto-compaction.js +2 -1
- package/dist/core/context-edit.js +2 -1
- package/dist/core/mcp.js +4 -1
- package/dist/core/runner/prepare-task.d.ts +5 -0
- package/dist/core/runner/prepare-task.js +41 -2
- package/dist/core/runner/runtask.js +39 -9
- package/dist/core/runner/tool-disclosure.d.ts +1 -0
- package/dist/core/runner/tool-disclosure.js +16 -5
- package/dist/core/runner/tool-output-projection.js +2 -1
- package/dist/core/session-reconcile.d.ts +1 -0
- package/dist/core/session-reconcile.js +40 -20
- package/dist/core/store-contracts/checkpoint-store-contract.d.ts +37 -0
- package/dist/core/store-contracts/checkpoint-store-contract.js +195 -0
- package/dist/core/store-contracts/contract-harness.d.ts +6 -0
- package/dist/core/store-contracts/contract-harness.js +16 -0
- package/dist/core/store-contracts/contract-kit-version.d.ts +1 -0
- package/dist/core/store-contracts/contract-kit-version.js +2 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.d.ts +3 -0
- package/dist/core/store-contracts/file-snapshot-store-contract.js +126 -0
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +6 -0
- package/dist/core/store-contracts/mailbox-store-contract.js +193 -0
- package/dist/core/store-contracts/session-repo-contract.d.ts +3 -0
- package/dist/core/store-contracts/session-repo-contract.js +36 -0
- package/dist/core/store-contracts/tool-result-store-contract.d.ts +3 -0
- package/dist/core/store-contracts/tool-result-store-contract.js +35 -0
- package/dist/core/task-notification.d.ts +2 -0
- package/dist/core/task-registry-agent.d.ts +6 -0
- package/dist/core/task-registry-agent.js +24 -1
- package/dist/core/task-registry-monitor.js +6 -6
- package/dist/core/task-registry-shared.d.ts +9 -2
- package/dist/core/task-registry-shared.js +1 -1
- package/dist/core/task-registry.d.ts +8 -0
- package/dist/core/task-registry.js +59 -4
- package/dist/core/tool-result-store.d.ts +3 -2
- package/dist/core/tool-result-store.js +12 -4
- package/dist/core/trace.d.ts +7 -0
- package/dist/core/types.d.ts +10 -3
- package/dist/engine/compaction/compaction.d.ts +5 -0
- package/dist/engine/compaction/compaction.js +68 -2
- package/dist/engine/compaction/utils.d.ts +6 -0
- package/dist/engine/compaction/utils.js +53 -3
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/messages.js +11 -3
- package/dist/engine/loop/types.d.ts +2 -0
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -0
- package/dist/engine/lsp/node-lsp-manager.js +16 -0
- package/dist/engine/session/import-validate.js +30 -1
- package/dist/engine/session/session.js +7 -5
- package/dist/index.d.ts +8 -0
- package/dist/index.js +8 -0
- package/dist/internal/harness.d.ts +1 -1
- package/dist/internal/harness.js +1 -1
- package/dist/orchestration/builtin-workflows.d.ts +1 -1
- package/dist/orchestration/builtin-workflows.js +11 -2
- package/dist/orchestration/workflow-governance.d.ts +6 -1
- package/dist/orchestration/workflow-governance.js +24 -4
- package/dist/orchestration/workflow-primitives.js +7 -1
- package/dist/orchestration/workflow-types.d.ts +1 -0
- package/dist/orchestration/workflow.d.ts +1 -0
- package/dist/orchestration/workflow.js +41 -3
- package/dist/tools/fs/fs-bash.d.ts +7 -1
- package/dist/tools/fs/fs-bash.js +59 -22
- package/dist/tools/fs/fs-read.js +22 -11
- package/dist/tools/fs/fs-search-tools.js +3 -3
- package/dist/tools/fs/fs-shared.d.ts +20 -7
- package/dist/tools/fs/fs-shared.js +17 -3
- package/dist/tools/fs/fs-write.js +4 -4
- package/dist/tools/fs/index.d.ts +2 -0
- package/dist/tools/fs/index.js +7 -1
- package/dist/tools/fs/repo-map.js +2 -2
- package/dist/tools/fs/safety.d.ts +10 -0
- package/dist/tools/fs/safety.js +15 -1
- package/dist/tools/monitor.js +18 -4
- package/dist/tools/web.js +6 -2
- package/dist/tools/worktree.js +46 -25
- package/package.json +1 -1
package/dist/agents/subagent.js
CHANGED
|
@@ -197,6 +197,7 @@ const ccElapsedTag = (ms) => {
|
|
|
197
197
|
return sec >= 60 ? ` \u00b7 ${Math.floor(sec / 60)}m${sec % 60}s` : ` \u00b7 ${sec}s`;
|
|
198
198
|
};
|
|
199
199
|
const ccCompletionText = (desc, settled, rawStatus, elapsedMs) => `Agent "${desc}" ${settled === "killed" ? "stopped" : settled === "completed" ? "finished" : rawStatus}${ccElapsedTag(elapsedMs)}`;
|
|
200
|
+
const BG_AGENT_COLLATERAL_REAP_REASON = "its parent run ended";
|
|
200
201
|
const RESERVED_AGENT_NAMES = new Set([OUTPUT_TOOL_NAME, TOOL_SEARCH_NAME, OFFLOAD_TOOL_NAME, REPORT_BLOCKED_TOOL_NAME, DEFAULT_SUBAGENT_TOOL_NAME, LEGACY_SUBAGENT_TOOL_NAME]);
|
|
201
202
|
export const REPORT_FIELD_MAX = 300;
|
|
202
203
|
function configError(message, code) {
|
|
@@ -220,6 +221,9 @@ export function classifySubagentError(child) {
|
|
|
220
221
|
: "logic";
|
|
221
222
|
return { errorKind, retryable: errorKind !== "logic" };
|
|
222
223
|
}
|
|
224
|
+
function errorKindClause(c) {
|
|
225
|
+
return c !== undefined ? ` (error_kind: ${c.errorKind}, retryable: ${c.retryable})` : "";
|
|
226
|
+
}
|
|
223
227
|
const FAILED_SESSION_RETAIN_TTL_MS = 15 * 60 * 1000;
|
|
224
228
|
const PARTIAL_FINDINGS_MAX_CHARS = 1200;
|
|
225
229
|
const BG_NOTIFY_DRAIN_WINDOW_MS = 2_000;
|
|
@@ -415,12 +419,18 @@ export function createSubagentResume(deps) {
|
|
|
415
419
|
void _;
|
|
416
420
|
const child = await stream.result();
|
|
417
421
|
let status = child.status === "completed" ? "completed" : abort.signal.aborted ? "killed" : "failed";
|
|
422
|
+
const errCodeRevive = status === "failed" ? (child.errorCode ?? extractErrorCode(child.errorMessage)) : undefined;
|
|
423
|
+
const errClassRevive = status === "failed"
|
|
424
|
+
? classifySubagentError({ status: "failed", ...(child.errorCode !== undefined ? { errorCode: child.errorCode } : {}), ...(child.errorMessage !== undefined ? { errorMessage: child.errorMessage } : {}) })
|
|
425
|
+
: undefined;
|
|
418
426
|
if (reviveCycle !== undefined && deps.registry !== undefined && deps.taskId !== undefined) {
|
|
419
427
|
try {
|
|
420
428
|
const winner = deps.registry.settleRevivedAgent(deps.taskId, reviveCycle, {
|
|
421
429
|
status,
|
|
422
430
|
...resultSettleFields(child.result),
|
|
423
431
|
...(status !== "completed" ? { error: (child.errorMessage ?? `resumed run ${status}`).slice(0, 500) } : {}),
|
|
432
|
+
...(errCodeRevive !== undefined ? { errorCode: errCodeRevive } : {}),
|
|
433
|
+
...(errClassRevive !== undefined ? { retryable: errClassRevive.retryable, errorKind: errClassRevive.errorKind } : {}),
|
|
424
434
|
});
|
|
425
435
|
if (winner !== undefined)
|
|
426
436
|
status = winner;
|
|
@@ -431,21 +441,27 @@ export function createSubagentResume(deps) {
|
|
|
431
441
|
const stoppedByRevive = status === "killed" ? deps.registry?.getStopAttribution(deps.taskId ?? "") ?? "system" : undefined;
|
|
432
442
|
const completionIdRevive = deps.registry?.getCompletionId(deps.taskId ?? "");
|
|
433
443
|
const reviveName = deps.rowDescription ?? `sub-agent ${marker}`;
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
444
|
+
const failReasonRevive = status === "failed" ? child.errorMessage : undefined;
|
|
445
|
+
const reviveTerminalSummary = failReasonRevive !== undefined
|
|
446
|
+
? `Agent "${reviveName}" (resumed) failed: ${failReasonRevive}${ccElapsedTag(Date.now() - reviveStartedAt)}`.slice(0, 300) + errorKindClause(errClassRevive)
|
|
447
|
+
: `Agent "${reviveName}" (resumed) ${status === "killed" ? "stopped" : child.status === "completed" ? "finished" : String(child.status)}${ccElapsedTag(Date.now() - reviveStartedAt)}`;
|
|
448
|
+
const ownsTerminalFacesRevive = deps.registry !== undefined && deps.taskId !== undefined ? deps.registry.claimAgentTerminalNotify(deps.taskId) : true;
|
|
449
|
+
if (ownsTerminalFacesRevive)
|
|
450
|
+
reviveEmit?.({
|
|
451
|
+
kind: "terminal",
|
|
452
|
+
taskId: deps.taskId,
|
|
453
|
+
sessionScoped: deps.sessionScoped === true,
|
|
454
|
+
sessionId: entry.childSessionId,
|
|
455
|
+
transcriptId: entry.childSessionId,
|
|
456
|
+
...(deps.parentToolCallId !== undefined ? { parentToolCallId: deps.parentToolCallId } : {}),
|
|
457
|
+
status,
|
|
458
|
+
seq: entry.cycleSeq,
|
|
459
|
+
...(stoppedByRevive !== undefined ? { stoppedBy: stoppedByRevive } : {}),
|
|
460
|
+
summary: reviveTerminalSummary,
|
|
461
|
+
resumable: status !== "killed",
|
|
462
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: child.stats.costMicroUsd },
|
|
463
|
+
...(completionIdRevive !== undefined ? { completionId: completionIdRevive } : {}),
|
|
464
|
+
});
|
|
449
465
|
const resumeFrame = {
|
|
450
466
|
task_id: deps.taskId ?? entry.childSessionId,
|
|
451
467
|
...(entry.childSessionId !== undefined ? { sessionId: entry.childSessionId } : {}),
|
|
@@ -454,7 +470,9 @@ export function createSubagentResume(deps) {
|
|
|
454
470
|
status,
|
|
455
471
|
...(stoppedByRevive !== undefined ? { stoppedBy: stoppedByRevive } : {}),
|
|
456
472
|
seq: entry.cycleSeq,
|
|
457
|
-
summary:
|
|
473
|
+
summary: reviveTerminalSummary,
|
|
474
|
+
...(failReasonRevive !== undefined ? { error: failReasonRevive.slice(0, REPORT_FIELD_MAX) } : {}),
|
|
475
|
+
...(status === "failed" && errCodeRevive !== undefined ? { errorCode: errCodeRevive } : {}),
|
|
458
476
|
...(child.result ? { result: notifyResultField(child.result) } : {}),
|
|
459
477
|
...(status === "killed" && child.result ? { partial: true } : {}),
|
|
460
478
|
...resumeResidual(),
|
|
@@ -462,7 +480,7 @@ export function createSubagentResume(deps) {
|
|
|
462
480
|
usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: child.stats.costMicroUsd },
|
|
463
481
|
...(completionIdRevive !== undefined ? { completionId: completionIdRevive } : {}),
|
|
464
482
|
};
|
|
465
|
-
const gateOwner = status === "completed" && deps.notify !== undefined && deps.registry !== undefined && ledger.get(deps.parentToolCallId) === entry
|
|
483
|
+
const gateOwner = ownsTerminalFacesRevive && status === "completed" && deps.notify !== undefined && deps.registry !== undefined && ledger.get(deps.parentToolCallId) === entry
|
|
466
484
|
? entry.childSessionId
|
|
467
485
|
: undefined;
|
|
468
486
|
const aliveBgCount = gateOwner !== undefined ? deps.registry.countRunningBackgroundForOwner(gateOwner) : 0;
|
|
@@ -476,7 +494,7 @@ export function createSubagentResume(deps) {
|
|
|
476
494
|
notify: deps.notify,
|
|
477
495
|
});
|
|
478
496
|
}
|
|
479
|
-
else {
|
|
497
|
+
else if (ownsTerminalFacesRevive) {
|
|
480
498
|
try {
|
|
481
499
|
deps.notify?.(resumeFrame, { priority: "later" });
|
|
482
500
|
}
|
|
@@ -485,11 +503,16 @@ export function createSubagentResume(deps) {
|
|
|
485
503
|
}
|
|
486
504
|
}
|
|
487
505
|
catch (e) {
|
|
506
|
+
const msgRevive = e instanceof Error ? e.message : String(e);
|
|
507
|
+
const errCodeReviveReject = abort.signal.aborted ? undefined : extractErrorCode(msgRevive);
|
|
508
|
+
const errClassReviveReject = abort.signal.aborted ? undefined : classifySubagentError({ status: "failed", errorMessage: msgRevive });
|
|
488
509
|
if (reviveCycle !== undefined && deps.registry !== undefined && deps.taskId !== undefined) {
|
|
489
510
|
try {
|
|
490
511
|
deps.registry.settleRevivedAgent(deps.taskId, reviveCycle, {
|
|
491
512
|
status: abort.signal.aborted ? "killed" : "failed",
|
|
492
|
-
error:
|
|
513
|
+
error: msgRevive.slice(0, 500),
|
|
514
|
+
...(errCodeReviveReject !== undefined ? { errorCode: errCodeReviveReject } : {}),
|
|
515
|
+
...(errClassReviveReject !== undefined ? { retryable: errClassReviveReject.retryable, errorKind: errClassReviveReject.errorKind } : {}),
|
|
493
516
|
});
|
|
494
517
|
}
|
|
495
518
|
catch {
|
|
@@ -498,31 +521,36 @@ export function createSubagentResume(deps) {
|
|
|
498
521
|
const stoppedByReject = abort.signal.aborted ? deps.registry?.getStopAttribution(deps.taskId ?? "") ?? "system" : undefined;
|
|
499
522
|
const completionIdRejectRevive = deps.registry?.getCompletionId(deps.taskId ?? "");
|
|
500
523
|
const rejectName = deps.rowDescription ?? `sub-agent ${marker}`;
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
...(stoppedByReject !== undefined ? { stoppedBy: stoppedByReject } : {}),
|
|
511
|
-
summary: `Agent "${rejectName}" (resumed) ${abort.signal.aborted ? "stopped" : "failed"}${ccElapsedTag(Date.now() - reviveStartedAt)}`.slice(0, 300),
|
|
512
|
-
...(completionIdRejectRevive !== undefined ? { completionId: completionIdRejectRevive } : {}),
|
|
513
|
-
});
|
|
514
|
-
try {
|
|
515
|
-
deps.notify?.({
|
|
516
|
-
task_id: deps.taskId ?? entry.childSessionId,
|
|
517
|
-
...(entry.childSessionId !== undefined ? { sessionId: entry.childSessionId } : {}),
|
|
518
|
-
task_type: "background_agent",
|
|
519
|
-
toolUseId: deps.parentToolCallId,
|
|
524
|
+
const ownsTerminalFacesReviveReject = deps.registry !== undefined && deps.taskId !== undefined ? deps.registry.claimAgentTerminalNotify(deps.taskId) : true;
|
|
525
|
+
if (ownsTerminalFacesReviveReject)
|
|
526
|
+
reviveEmit?.({
|
|
527
|
+
kind: "terminal",
|
|
528
|
+
taskId: deps.taskId,
|
|
529
|
+
sessionScoped: deps.sessionScoped === true,
|
|
530
|
+
sessionId: entry.childSessionId,
|
|
531
|
+
transcriptId: entry.childSessionId,
|
|
532
|
+
...(deps.parentToolCallId !== undefined ? { parentToolCallId: deps.parentToolCallId } : {}),
|
|
520
533
|
status: abort.signal.aborted ? "killed" : "failed",
|
|
521
534
|
seq: entry.cycleSeq,
|
|
522
535
|
...(stoppedByReject !== undefined ? { stoppedBy: stoppedByReject } : {}),
|
|
523
|
-
summary: `Agent "${rejectName}" (resumed) ${abort.signal.aborted ? "stopped" :
|
|
536
|
+
summary: `Agent "${rejectName}" (resumed) ${abort.signal.aborted ? "stopped" : "failed"}${ccElapsedTag(Date.now() - reviveStartedAt)}`.slice(0, 300) + (abort.signal.aborted ? "" : errorKindClause(errClassReviveReject)),
|
|
524
537
|
...(completionIdRejectRevive !== undefined ? { completionId: completionIdRejectRevive } : {}),
|
|
525
|
-
}
|
|
538
|
+
});
|
|
539
|
+
try {
|
|
540
|
+
if (ownsTerminalFacesReviveReject)
|
|
541
|
+
deps.notify?.({
|
|
542
|
+
task_id: deps.taskId ?? entry.childSessionId,
|
|
543
|
+
...(entry.childSessionId !== undefined ? { sessionId: entry.childSessionId } : {}),
|
|
544
|
+
task_type: "background_agent",
|
|
545
|
+
toolUseId: deps.parentToolCallId,
|
|
546
|
+
status: abort.signal.aborted ? "killed" : "failed",
|
|
547
|
+
seq: entry.cycleSeq,
|
|
548
|
+
...(stoppedByReject !== undefined ? { stoppedBy: stoppedByReject } : {}),
|
|
549
|
+
summary: `Agent "${rejectName}" (resumed) ${abort.signal.aborted ? "stopped" : `failed: ${msgRevive}`}${ccElapsedTag(Date.now() - reviveStartedAt)}`.slice(0, 300) + (abort.signal.aborted ? "" : errorKindClause(errClassReviveReject)),
|
|
550
|
+
...(abort.signal.aborted ? {} : { error: msgRevive.slice(0, REPORT_FIELD_MAX) }),
|
|
551
|
+
...(!abort.signal.aborted && errCodeReviveReject !== undefined ? { errorCode: errCodeReviveReject } : {}),
|
|
552
|
+
...(completionIdRejectRevive !== undefined ? { completionId: completionIdRejectRevive } : {}),
|
|
553
|
+
}, { priority: "later" });
|
|
526
554
|
}
|
|
527
555
|
catch {
|
|
528
556
|
}
|
|
@@ -1588,6 +1616,40 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1588
1616
|
return { isError: true, content: `Sub-agent not started in background: ${e instanceof Error ? e.message : String(e)}${wt ? `\n${wt}` : ""}`, details: { error: "register_failed" } };
|
|
1589
1617
|
}
|
|
1590
1618
|
bg.registry.bindBackgroundAgentSession(taskId, forkedId);
|
|
1619
|
+
const forkBgHangAt = Date.now();
|
|
1620
|
+
bg.registry.attachAgentTerminalNotifier(taskId, () => {
|
|
1621
|
+
const stoppedByReap = bg.registry.getStopAttribution(taskId) ?? "system";
|
|
1622
|
+
const completionIdReap = bg.registry.getCompletionId(taskId);
|
|
1623
|
+
const summaryReap = ccCompletionText(shortDesc, "killed", "killed", Date.now() - forkBgHangAt);
|
|
1624
|
+
sinkEmit({
|
|
1625
|
+
kind: "terminal",
|
|
1626
|
+
taskId,
|
|
1627
|
+
sessionScoped: sessionScopedBg === true,
|
|
1628
|
+
sessionId: forkedId,
|
|
1629
|
+
transcriptId: forkedId,
|
|
1630
|
+
parentToolCallId: ctx.toolCallId,
|
|
1631
|
+
status: "killed",
|
|
1632
|
+
stoppedBy: stoppedByReap,
|
|
1633
|
+
summary: summaryReap,
|
|
1634
|
+
resumable: false,
|
|
1635
|
+
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
1636
|
+
});
|
|
1637
|
+
try {
|
|
1638
|
+
notify?.({
|
|
1639
|
+
task_id: taskId,
|
|
1640
|
+
task_type: "background_agent",
|
|
1641
|
+
toolUseId: ctx.toolCallId,
|
|
1642
|
+
status: "killed",
|
|
1643
|
+
stoppedBy: stoppedByReap,
|
|
1644
|
+
summary: summaryReap,
|
|
1645
|
+
sessionId: forkedId,
|
|
1646
|
+
resumable: false,
|
|
1647
|
+
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
1648
|
+
}, { priority: "later" });
|
|
1649
|
+
}
|
|
1650
|
+
catch {
|
|
1651
|
+
}
|
|
1652
|
+
});
|
|
1591
1653
|
if (agentName !== undefined) {
|
|
1592
1654
|
recordRosterSpawn(ctx.roster, { name: agentName, agentId: taskId, sessionId: forkedId, toolUseId: ctx.toolCallId, owner: bgOwner, scope: bgScope, ...((typeof childModel === "string" ? resolveModelDisplayLabel(childModel) : childModel?.id) !== undefined ? { model: typeof childModel === "string" ? childModel : childModel?.id } : {}), ...((ctx.rootSessionId ?? ctx.sessionId) !== undefined ? { rootSessionId: ctx.rootSessionId ?? ctx.sessionId } : {}), ...(sessionScopedBg ? { sessionScoped: true } : {}), createdAt: Date.now() });
|
|
1593
1655
|
}
|
|
@@ -1683,10 +1745,18 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1683
1745
|
}
|
|
1684
1746
|
const okBg = child.status === "completed";
|
|
1685
1747
|
const reapedBg = !okBg && abort.signal.aborted;
|
|
1748
|
+
const collateralBg = reapedBg && bg.registry.getAccessibleTask(taskId, { ...(bgOwner !== undefined ? { owner: bgOwner } : {}), ...(bgScope !== undefined ? { scope: bgScope } : {}) })?.status === "running";
|
|
1749
|
+
const failedFork = !okBg && !reapedBg;
|
|
1750
|
+
const errCodeFork = failedFork ? (child.errorCode ?? extractErrorCode(child.errorMessage)) : undefined;
|
|
1751
|
+
const errClassFork = failedFork
|
|
1752
|
+
? classifySubagentError({ status: "failed", ...(child.errorCode !== undefined ? { errorCode: child.errorCode } : {}), ...(child.errorMessage !== undefined ? { errorMessage: child.errorMessage } : {}) })
|
|
1753
|
+
: undefined;
|
|
1686
1754
|
const settledBg = bg.registry.settleBackgroundAgent(taskId, {
|
|
1687
1755
|
status: okBg ? "completed" : reapedBg ? "killed" : "failed",
|
|
1688
1756
|
...resultSettleFields(child.result),
|
|
1689
|
-
...(!okBg ? { error: reapedBg ? BG_AGENT_REAP_STOP_ERROR : child.errorMessage ?? String(child.status) } : {}),
|
|
1757
|
+
...(!okBg ? { error: reapedBg ? (collateralBg ? BG_AGENT_COLLATERAL_REAP_REASON : BG_AGENT_REAP_STOP_ERROR) : child.errorMessage ?? String(child.status) } : {}),
|
|
1758
|
+
...(errCodeFork !== undefined ? { errorCode: errCodeFork } : {}),
|
|
1759
|
+
...(errClassFork !== undefined ? { retryable: errClassFork.retryable, errorKind: errClassFork.errorKind } : {}),
|
|
1690
1760
|
}) ?? (abort.signal.aborted ? "killed" : okBg ? "completed" : "failed");
|
|
1691
1761
|
const stoppedByBg = settledBg === "killed" ? bg.registry.getStopAttribution(taskId) ?? "system" : undefined;
|
|
1692
1762
|
const completionIdFork = bg.registry.getCompletionId(taskId);
|
|
@@ -1701,37 +1771,46 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1701
1771
|
const residualFork = residualFields();
|
|
1702
1772
|
const resumableFork = false;
|
|
1703
1773
|
const forkTranscriptId = child.sessionId ?? forkedId;
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
...(completionIdFork !== undefined ? { completionId: completionIdFork } : {}),
|
|
1718
|
-
});
|
|
1719
|
-
try {
|
|
1720
|
-
notify?.({
|
|
1721
|
-
task_id: taskId,
|
|
1722
|
-
task_type: "background_agent",
|
|
1723
|
-
toolUseId: ctx.toolCallId,
|
|
1774
|
+
const failReasonFork = settledBg === "failed" ? child.errorMessage : undefined;
|
|
1775
|
+
const forkTerminalSummary = failReasonFork !== undefined
|
|
1776
|
+
? `Agent "${shortDesc}" failed: ${failReasonFork}${ccElapsedTag(Date.now() - forkBgStartedAt)}`.slice(0, 300) + errorKindClause(errClassFork)
|
|
1777
|
+
: `${ccCompletionText(shortDesc, settledBg, String(child.status), Date.now() - forkBgStartedAt)}`;
|
|
1778
|
+
const ownsTerminalFacesFork = bg.registry.claimAgentTerminalNotify(taskId);
|
|
1779
|
+
if (ownsTerminalFacesFork)
|
|
1780
|
+
sinkEmit({
|
|
1781
|
+
kind: "terminal",
|
|
1782
|
+
taskId,
|
|
1783
|
+
sessionScoped: sessionScopedBg === true,
|
|
1784
|
+
sessionId: forkTranscriptId,
|
|
1785
|
+
...(stillbornFork ? {} : { transcriptId: forkTranscriptId }),
|
|
1786
|
+
parentToolCallId: ctx.toolCallId,
|
|
1724
1787
|
status: settledBg,
|
|
1725
1788
|
...(stoppedByBg !== undefined ? { stoppedBy: stoppedByBg } : {}),
|
|
1726
|
-
summary:
|
|
1727
|
-
...(child.sessionId ? { sessionId: child.sessionId } : {}),
|
|
1728
|
-
...(child.result ? { result: notifyResultField(child.result) } : {}),
|
|
1729
|
-
...(settledBg === "killed" && child.result ? { partial: true } : {}),
|
|
1789
|
+
summary: forkTerminalSummary,
|
|
1730
1790
|
...residualFork,
|
|
1731
1791
|
resumable: resumableFork,
|
|
1732
1792
|
usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
|
|
1733
1793
|
...(completionIdFork !== undefined ? { completionId: completionIdFork } : {}),
|
|
1734
|
-
}
|
|
1794
|
+
});
|
|
1795
|
+
try {
|
|
1796
|
+
if (ownsTerminalFacesFork)
|
|
1797
|
+
notify?.({
|
|
1798
|
+
task_id: taskId,
|
|
1799
|
+
task_type: "background_agent",
|
|
1800
|
+
toolUseId: ctx.toolCallId,
|
|
1801
|
+
status: settledBg,
|
|
1802
|
+
...(stoppedByBg !== undefined ? { stoppedBy: stoppedByBg } : {}),
|
|
1803
|
+
summary: forkTerminalSummary,
|
|
1804
|
+
...(failReasonFork !== undefined ? { error: failReasonFork.slice(0, REPORT_FIELD_MAX) } : {}),
|
|
1805
|
+
...(settledBg === "failed" && errCodeFork !== undefined ? { errorCode: errCodeFork } : {}),
|
|
1806
|
+
...(child.sessionId ? { sessionId: child.sessionId } : {}),
|
|
1807
|
+
...(child.result ? { result: notifyResultField(child.result) } : {}),
|
|
1808
|
+
...(settledBg === "killed" && child.result ? { partial: true } : {}),
|
|
1809
|
+
...residualFork,
|
|
1810
|
+
resumable: resumableFork,
|
|
1811
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
|
|
1812
|
+
...(completionIdFork !== undefined ? { completionId: completionIdFork } : {}),
|
|
1813
|
+
}, { priority: "later" });
|
|
1735
1814
|
}
|
|
1736
1815
|
catch {
|
|
1737
1816
|
}
|
|
@@ -1740,36 +1819,46 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1740
1819
|
dropHostAbortListener();
|
|
1741
1820
|
void finishWorktree();
|
|
1742
1821
|
const killed = abort.signal.aborted;
|
|
1822
|
+
const msgFork = e instanceof Error ? e.message : String(e);
|
|
1823
|
+
const errCodeForkReject = killed ? undefined : extractErrorCode(msgFork);
|
|
1824
|
+
const errClassForkReject = killed ? undefined : classifySubagentError({ status: "failed", errorMessage: msgFork });
|
|
1743
1825
|
const settledBg = bg.registry.settleBackgroundAgent(taskId, {
|
|
1744
1826
|
status: killed ? "killed" : "failed",
|
|
1745
|
-
error: killed ? BG_AGENT_REAP_STOP_ERROR :
|
|
1827
|
+
error: killed ? BG_AGENT_REAP_STOP_ERROR : msgFork,
|
|
1828
|
+
...(errCodeForkReject !== undefined ? { errorCode: errCodeForkReject } : {}),
|
|
1829
|
+
...(errClassForkReject !== undefined ? { retryable: errClassForkReject.retryable, errorKind: errClassForkReject.errorKind } : {}),
|
|
1746
1830
|
}) ?? (killed ? "killed" : "failed");
|
|
1747
1831
|
const stoppedByBg = settledBg === "killed" ? bg.registry.getStopAttribution(taskId) ?? "system" : undefined;
|
|
1748
1832
|
const completionIdForkReject = bg.registry.getCompletionId(taskId);
|
|
1749
|
-
const summaryBg = `${shortDesc} — ${settledBg === "failed" ? `failed: ${
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
parentToolCallId: ctx.toolCallId,
|
|
1757
|
-
status: settledBg,
|
|
1758
|
-
...(stoppedByBg !== undefined ? { stoppedBy: stoppedByBg } : {}),
|
|
1759
|
-
summary: summaryBg,
|
|
1760
|
-
...(completionIdForkReject !== undefined ? { completionId: completionIdForkReject } : {}),
|
|
1761
|
-
});
|
|
1762
|
-
try {
|
|
1763
|
-
notify?.({
|
|
1764
|
-
task_id: taskId,
|
|
1765
|
-
task_type: "background_agent",
|
|
1766
|
-
toolUseId: ctx.toolCallId,
|
|
1767
|
-
status: settledBg,
|
|
1833
|
+
const summaryBg = `${shortDesc} — ${settledBg === "failed" ? `failed: ${msgFork}` : settledBg}`.slice(0, 300) + (settledBg === "failed" ? errorKindClause(errClassForkReject) : "");
|
|
1834
|
+
const ownsTerminalFacesForkReject = bg.registry.claimAgentTerminalNotify(taskId);
|
|
1835
|
+
if (ownsTerminalFacesForkReject)
|
|
1836
|
+
sinkEmit({
|
|
1837
|
+
kind: "terminal",
|
|
1838
|
+
taskId,
|
|
1839
|
+
sessionScoped: sessionScopedBg === true,
|
|
1768
1840
|
sessionId: forkedId,
|
|
1841
|
+
transcriptId: forkedId,
|
|
1842
|
+
parentToolCallId: ctx.toolCallId,
|
|
1843
|
+
status: settledBg,
|
|
1769
1844
|
...(stoppedByBg !== undefined ? { stoppedBy: stoppedByBg } : {}),
|
|
1770
1845
|
summary: summaryBg,
|
|
1771
1846
|
...(completionIdForkReject !== undefined ? { completionId: completionIdForkReject } : {}),
|
|
1772
|
-
}
|
|
1847
|
+
});
|
|
1848
|
+
try {
|
|
1849
|
+
if (ownsTerminalFacesForkReject)
|
|
1850
|
+
notify?.({
|
|
1851
|
+
task_id: taskId,
|
|
1852
|
+
task_type: "background_agent",
|
|
1853
|
+
toolUseId: ctx.toolCallId,
|
|
1854
|
+
status: settledBg,
|
|
1855
|
+
sessionId: forkedId,
|
|
1856
|
+
...(stoppedByBg !== undefined ? { stoppedBy: stoppedByBg } : {}),
|
|
1857
|
+
summary: summaryBg,
|
|
1858
|
+
...(settledBg === "failed" ? { error: msgFork.slice(0, REPORT_FIELD_MAX) } : {}),
|
|
1859
|
+
...(settledBg === "failed" && errCodeForkReject !== undefined ? { errorCode: errCodeForkReject } : {}),
|
|
1860
|
+
...(completionIdForkReject !== undefined ? { completionId: completionIdForkReject } : {}),
|
|
1861
|
+
}, { priority: "later" });
|
|
1773
1862
|
}
|
|
1774
1863
|
catch {
|
|
1775
1864
|
}
|
|
@@ -1956,6 +2045,39 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
1956
2045
|
const bgStartedAt = Date.now();
|
|
1957
2046
|
stepRecorder.lockTo(bgChildSessionId);
|
|
1958
2047
|
bg.registry.bindBackgroundAgentSession(taskId, bgChildSessionId);
|
|
2048
|
+
bg.registry.attachAgentTerminalNotifier(taskId, () => {
|
|
2049
|
+
const stoppedByReap = bg.registry.getStopAttribution(taskId) ?? "system";
|
|
2050
|
+
const completionIdReap = bg.registry.getCompletionId(taskId);
|
|
2051
|
+
const summaryReap = ccCompletionText(shortDesc, "killed", "killed", Date.now() - bgStartedAt);
|
|
2052
|
+
sinkEmit({
|
|
2053
|
+
kind: "terminal",
|
|
2054
|
+
taskId,
|
|
2055
|
+
sessionScoped: sessionScopedBg === true,
|
|
2056
|
+
sessionId: bgChildSessionId,
|
|
2057
|
+
transcriptId: bgChildSessionId,
|
|
2058
|
+
parentToolCallId: ctx.toolCallId,
|
|
2059
|
+
status: "killed",
|
|
2060
|
+
stoppedBy: stoppedByReap,
|
|
2061
|
+
summary: summaryReap,
|
|
2062
|
+
resumable: false,
|
|
2063
|
+
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
2064
|
+
});
|
|
2065
|
+
try {
|
|
2066
|
+
notify?.({
|
|
2067
|
+
task_id: taskId,
|
|
2068
|
+
task_type: "background_agent",
|
|
2069
|
+
toolUseId: ctx.toolCallId,
|
|
2070
|
+
status: "killed",
|
|
2071
|
+
stoppedBy: stoppedByReap,
|
|
2072
|
+
summary: summaryReap,
|
|
2073
|
+
sessionId: bgChildSessionId,
|
|
2074
|
+
resumable: false,
|
|
2075
|
+
...(completionIdReap !== undefined ? { completionId: completionIdReap } : {}),
|
|
2076
|
+
}, { priority: "later" });
|
|
2077
|
+
}
|
|
2078
|
+
catch {
|
|
2079
|
+
}
|
|
2080
|
+
});
|
|
1959
2081
|
const bgDurableProbe = bg.registry.durableAgentRowProbe(taskId);
|
|
1960
2082
|
const bgRowConfirmed = async () => (bgDurableProbe ? await bgDurableProbe().catch(() => false) : false);
|
|
1961
2083
|
sinkEmit({
|
|
@@ -2259,11 +2381,19 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2259
2381
|
}
|
|
2260
2382
|
const ok = child.status === "completed";
|
|
2261
2383
|
const reaped = !ok && abort.signal.aborted;
|
|
2384
|
+
const collateral = reaped && bg.registry.getAccessibleTask(taskId, { ...(bgOwner !== undefined ? { owner: bgOwner } : {}), ...(bgScope !== undefined ? { scope: bgScope } : {}) })?.status === "running";
|
|
2385
|
+
const failedBg = !ok && !reaped;
|
|
2386
|
+
const errCodeBg = failedBg ? (child.errorCode ?? extractErrorCode(child.errorMessage)) : undefined;
|
|
2387
|
+
const errClassBg = failedBg
|
|
2388
|
+
? classifySubagentError({ status: "failed", ...(child.errorCode !== undefined ? { errorCode: child.errorCode } : {}), ...(child.errorMessage !== undefined ? { errorMessage: child.errorMessage } : {}) })
|
|
2389
|
+
: undefined;
|
|
2262
2390
|
const settled = bg.registry.settleBackgroundAgent(taskId, {
|
|
2263
2391
|
status: ok ? "completed" : reaped ? "killed" : "failed",
|
|
2264
2392
|
seq: seqAtSettle ?? 1,
|
|
2265
2393
|
...resultSettleFields(child.result),
|
|
2266
|
-
...(!ok ? { error: reaped ? BG_AGENT_REAP_STOP_ERROR : child.errorMessage ?? String(child.status) } : {}),
|
|
2394
|
+
...(!ok ? { error: reaped ? (collateral ? BG_AGENT_COLLATERAL_REAP_REASON : BG_AGENT_REAP_STOP_ERROR) : child.errorMessage ?? String(child.status) } : {}),
|
|
2395
|
+
...(errCodeBg !== undefined ? { errorCode: errCodeBg } : {}),
|
|
2396
|
+
...(errClassBg !== undefined ? { retryable: errClassBg.retryable, errorKind: errClassBg.errorKind } : {}),
|
|
2267
2397
|
}) ??
|
|
2268
2398
|
(abort.signal.aborted ? "killed" : ok ? "completed" : "failed");
|
|
2269
2399
|
if (!bgRetain && reviveRow === undefined && !(await bgRowConfirmed())) {
|
|
@@ -2279,21 +2409,27 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2279
2409
|
const observerNote = observerNoteFor(await startBoundedObserverDrain());
|
|
2280
2410
|
const residual = residualFields();
|
|
2281
2411
|
const resumableBg = bgRetain !== undefined && settled !== "killed";
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2412
|
+
const failReasonBg = settled === "failed" ? child.errorMessage : undefined;
|
|
2413
|
+
const bgTerminalSummary = failReasonBg !== undefined
|
|
2414
|
+
? `Agent "${shortDesc}" failed: ${failReasonBg}${ccElapsedTag(Date.now() - bgStartedAt)}${observerNote}`.slice(0, 300) + errorKindClause(errClassBg)
|
|
2415
|
+
: `${ccCompletionText(shortDesc, settled, String(child.status), Date.now() - bgStartedAt)}${observerNote}`;
|
|
2416
|
+
const ownsTerminalFaces = bg.registry.claimAgentTerminalNotify(taskId);
|
|
2417
|
+
if (ownsTerminalFaces)
|
|
2418
|
+
sinkEmit({
|
|
2419
|
+
kind: "terminal",
|
|
2420
|
+
taskId,
|
|
2421
|
+
sessionScoped: sessionScopedBg === true,
|
|
2422
|
+
...(child.sessionId ? { sessionId: child.sessionId, transcriptId: child.sessionId } : {}),
|
|
2423
|
+
parentToolCallId: ctx.toolCallId,
|
|
2424
|
+
status: settled,
|
|
2425
|
+
...(seqAtSettle !== undefined ? { seq: seqAtSettle } : {}),
|
|
2426
|
+
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
|
2427
|
+
summary: bgTerminalSummary,
|
|
2428
|
+
...residual,
|
|
2429
|
+
resumable: resumableBg,
|
|
2430
|
+
usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
|
|
2431
|
+
...(completionIdBg !== undefined ? { completionId: completionIdBg } : {}),
|
|
2432
|
+
});
|
|
2297
2433
|
const completionFrame = {
|
|
2298
2434
|
task_id: taskId,
|
|
2299
2435
|
task_type: "background_agent",
|
|
@@ -2301,7 +2437,9 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2301
2437
|
status: settled,
|
|
2302
2438
|
...(seqAtSettle !== undefined ? { seq: seqAtSettle } : {}),
|
|
2303
2439
|
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
|
2304
|
-
summary:
|
|
2440
|
+
summary: bgTerminalSummary,
|
|
2441
|
+
...(failReasonBg !== undefined ? { error: failReasonBg.slice(0, REPORT_FIELD_MAX) } : {}),
|
|
2442
|
+
...(settled === "failed" && errCodeBg !== undefined ? { errorCode: errCodeBg } : {}),
|
|
2305
2443
|
...(child.sessionId ? { sessionId: child.sessionId } : {}),
|
|
2306
2444
|
...(child.result ? { result: notifyResultField(child.result) } : {}),
|
|
2307
2445
|
...(settled === "killed" && child.result ? { partial: true } : {}),
|
|
@@ -2310,7 +2448,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2310
2448
|
usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
|
|
2311
2449
|
...(completionIdBg !== undefined ? { completionId: completionIdBg } : {}),
|
|
2312
2450
|
};
|
|
2313
|
-
const gateOwner = settled === "completed" && notify !== undefined ? bgRetain?.childSessionId : undefined;
|
|
2451
|
+
const gateOwner = ownsTerminalFaces && settled === "completed" && notify !== undefined ? bgRetain?.childSessionId : undefined;
|
|
2314
2452
|
const aliveBgCount = gateOwner !== undefined ? bg.registry.countRunningBackgroundForOwner(gateOwner) : 0;
|
|
2315
2453
|
if (gateOwner !== undefined && bgRetain !== undefined && aliveBgCount > 0) {
|
|
2316
2454
|
parkCompletionNotify({
|
|
@@ -2322,7 +2460,7 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2322
2460
|
notify: notify,
|
|
2323
2461
|
});
|
|
2324
2462
|
}
|
|
2325
|
-
else {
|
|
2463
|
+
else if (ownsTerminalFaces) {
|
|
2326
2464
|
try {
|
|
2327
2465
|
notify?.(completionFrame, { priority: "later" });
|
|
2328
2466
|
}
|
|
@@ -2343,7 +2481,15 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2343
2481
|
bgRetainLedger?.markSettled(ctx.toolCallId);
|
|
2344
2482
|
}
|
|
2345
2483
|
const msg = e instanceof Error ? e.message : String(e);
|
|
2346
|
-
const
|
|
2484
|
+
const errCodeBgReject = killed ? undefined : extractErrorCode(msg);
|
|
2485
|
+
const errClassBgReject = killed ? undefined : classifySubagentError({ status: "failed", errorMessage: msg });
|
|
2486
|
+
const settled = bg.registry.settleBackgroundAgent(taskId, {
|
|
2487
|
+
status: killed ? "killed" : "failed",
|
|
2488
|
+
error: msg,
|
|
2489
|
+
seq: seqAtSettle ?? 1,
|
|
2490
|
+
...(errCodeBgReject !== undefined ? { errorCode: errCodeBgReject } : {}),
|
|
2491
|
+
...(errClassBgReject !== undefined ? { retryable: errClassBgReject.retryable, errorKind: errClassBgReject.errorKind } : {}),
|
|
2492
|
+
}) ?? (killed ? "killed" : "failed");
|
|
2347
2493
|
if (!bgRetain && reviveRow === undefined && !(await bgRowConfirmed())) {
|
|
2348
2494
|
try {
|
|
2349
2495
|
await opts.runner.sessions.release(bgChildSessionId);
|
|
@@ -2355,31 +2501,36 @@ function createSubagentToolNode(opts, depth, excluded, extraToolsBudget) {
|
|
|
2355
2501
|
const stoppedBy = settled === "killed" ? bg.registry.getStopAttribution(taskId) ?? "system" : undefined;
|
|
2356
2502
|
const completionIdBgReject = bg.registry.getCompletionId(taskId);
|
|
2357
2503
|
const observerNote = observerNoteFor(await startBoundedObserverDrain());
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
parentToolCallId: ctx.toolCallId,
|
|
2365
|
-
status: settled,
|
|
2366
|
-
...(seqAtSettle !== undefined ? { seq: seqAtSettle } : {}),
|
|
2367
|
-
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
|
2368
|
-
summary: `${settled === "failed" ? `Agent "${shortDesc}" failed: ${msg}${ccElapsedTag(Date.now() - bgStartedAt)}` : ccCompletionText(shortDesc, settled, settled, Date.now() - bgStartedAt)}${observerNote}`.slice(0, 300),
|
|
2369
|
-
...(completionIdBgReject !== undefined ? { completionId: completionIdBgReject } : {}),
|
|
2370
|
-
});
|
|
2371
|
-
try {
|
|
2372
|
-
notify?.({
|
|
2373
|
-
task_id: taskId,
|
|
2374
|
-
task_type: "background_agent",
|
|
2375
|
-
toolUseId: ctx.toolCallId,
|
|
2376
|
-
status: settled,
|
|
2504
|
+
const ownsTerminalFacesReject = bg.registry.claimAgentTerminalNotify(taskId);
|
|
2505
|
+
if (ownsTerminalFacesReject)
|
|
2506
|
+
sinkEmit({
|
|
2507
|
+
kind: "terminal",
|
|
2508
|
+
taskId,
|
|
2509
|
+
sessionScoped: sessionScopedBg === true,
|
|
2377
2510
|
sessionId: bgChildSessionId,
|
|
2511
|
+
transcriptId: bgChildSessionId,
|
|
2512
|
+
parentToolCallId: ctx.toolCallId,
|
|
2513
|
+
status: settled,
|
|
2378
2514
|
...(seqAtSettle !== undefined ? { seq: seqAtSettle } : {}),
|
|
2379
2515
|
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
|
2380
|
-
summary: `${settled === "failed" ? `Agent "${shortDesc}" failed: ${msg}${ccElapsedTag(Date.now() - bgStartedAt)}` : ccCompletionText(shortDesc, settled, settled, Date.now() - bgStartedAt)}${observerNote}`.slice(0, 300),
|
|
2516
|
+
summary: `${settled === "failed" ? `Agent "${shortDesc}" failed: ${msg}${ccElapsedTag(Date.now() - bgStartedAt)}` : ccCompletionText(shortDesc, settled, settled, Date.now() - bgStartedAt)}${observerNote}`.slice(0, 300) + (settled === "failed" ? errorKindClause(errClassBgReject) : ""),
|
|
2381
2517
|
...(completionIdBgReject !== undefined ? { completionId: completionIdBgReject } : {}),
|
|
2382
|
-
}
|
|
2518
|
+
});
|
|
2519
|
+
try {
|
|
2520
|
+
if (ownsTerminalFacesReject)
|
|
2521
|
+
notify?.({
|
|
2522
|
+
task_id: taskId,
|
|
2523
|
+
task_type: "background_agent",
|
|
2524
|
+
toolUseId: ctx.toolCallId,
|
|
2525
|
+
status: settled,
|
|
2526
|
+
sessionId: bgChildSessionId,
|
|
2527
|
+
...(seqAtSettle !== undefined ? { seq: seqAtSettle } : {}),
|
|
2528
|
+
...(stoppedBy !== undefined ? { stoppedBy } : {}),
|
|
2529
|
+
summary: `${settled === "failed" ? `Agent "${shortDesc}" failed: ${msg}${ccElapsedTag(Date.now() - bgStartedAt)}` : ccCompletionText(shortDesc, settled, settled, Date.now() - bgStartedAt)}${observerNote}`.slice(0, 300) + (settled === "failed" ? errorKindClause(errClassBgReject) : ""),
|
|
2530
|
+
...(settled === "failed" ? { error: msg.slice(0, REPORT_FIELD_MAX) } : {}),
|
|
2531
|
+
...(settled === "failed" && errCodeBgReject !== undefined ? { errorCode: errCodeBgReject } : {}),
|
|
2532
|
+
...(completionIdBgReject !== undefined ? { completionId: completionIdBgReject } : {}),
|
|
2533
|
+
}, { priority: "later" });
|
|
2383
2534
|
}
|
|
2384
2535
|
catch {
|
|
2385
2536
|
}
|
package/dist/brain/errors.d.ts
CHANGED
|
@@ -12,4 +12,5 @@ export declare class BrainError extends Error {
|
|
|
12
12
|
export declare function classifyHttp(status: number): BrainErrorCode;
|
|
13
13
|
export declare function extractErrorCode(errorMessage: string | undefined): BrainErrorCode | undefined;
|
|
14
14
|
export declare function stripErrorCodePrefix(errorMessage: string): string;
|
|
15
|
+
export declare function describeNetworkError(e: unknown): string;
|
|
15
16
|
export {};
|
package/dist/brain/errors.js
CHANGED
|
@@ -42,3 +42,17 @@ export function extractErrorCode(errorMessage) {
|
|
|
42
42
|
export function stripErrorCodePrefix(errorMessage) {
|
|
43
43
|
return errorMessage.replace(CODE_PREFIX_RE, "");
|
|
44
44
|
}
|
|
45
|
+
export function describeNetworkError(e) {
|
|
46
|
+
const top = e instanceof Error ? e.message : String(e);
|
|
47
|
+
const parts = [];
|
|
48
|
+
let cur = e instanceof Error ? e.cause : undefined;
|
|
49
|
+
for (let depth = 0; depth < 4 && cur !== undefined && cur !== null; depth++) {
|
|
50
|
+
const code = typeof cur.code === "string" ? cur.code : undefined;
|
|
51
|
+
const msg = cur instanceof Error ? cur.message : String(cur);
|
|
52
|
+
const piece = code !== undefined && !msg.includes(code) ? `${code}: ${msg}` : msg;
|
|
53
|
+
if (piece.length > 0 && piece !== top && !parts.includes(piece))
|
|
54
|
+
parts.push(piece);
|
|
55
|
+
cur = cur instanceof Error ? cur.cause : undefined;
|
|
56
|
+
}
|
|
57
|
+
return parts.length > 0 ? `${top} (${parts.join(" ← ")})` : top;
|
|
58
|
+
}
|