@sema-agent/core 1.279.0 → 1.281.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.
Files changed (87) hide show
  1. package/dist/agents/subagent.d.ts +12 -0
  2. package/dist/agents/subagent.d.ts.map +1 -1
  3. package/dist/agents/subagent.js +221 -19
  4. package/dist/agents/subagent.js.map +1 -1
  5. package/dist/bin/sema-tb.d.ts +10 -0
  6. package/dist/bin/sema-tb.d.ts.map +1 -1
  7. package/dist/bin/sema-tb.js +81 -10
  8. package/dist/bin/sema-tb.js.map +1 -1
  9. package/dist/core/background-shell.d.ts +2 -0
  10. package/dist/core/background-shell.d.ts.map +1 -1
  11. package/dist/core/background-shell.js.map +1 -1
  12. package/dist/core/context-guard.d.ts +2 -0
  13. package/dist/core/context-guard.d.ts.map +1 -1
  14. package/dist/core/context-guard.js +10 -0
  15. package/dist/core/context-guard.js.map +1 -1
  16. package/dist/core/mcp.d.ts +4 -0
  17. package/dist/core/mcp.d.ts.map +1 -1
  18. package/dist/core/mcp.js +189 -32
  19. package/dist/core/mcp.js.map +1 -1
  20. package/dist/core/runner/assemble-result.d.ts +2 -0
  21. package/dist/core/runner/assemble-result.d.ts.map +1 -1
  22. package/dist/core/runner/assemble-result.js.map +1 -1
  23. package/dist/core/runner/call-cap.d.ts +10 -0
  24. package/dist/core/runner/call-cap.d.ts.map +1 -1
  25. package/dist/core/runner/call-cap.js +27 -1
  26. package/dist/core/runner/call-cap.js.map +1 -1
  27. package/dist/core/runner/prepare-task.d.ts.map +1 -1
  28. package/dist/core/runner/prepare-task.js +20 -4
  29. package/dist/core/runner/prepare-task.js.map +1 -1
  30. package/dist/core/runner/runtask.d.ts.map +1 -1
  31. package/dist/core/runner/runtask.js +66 -24
  32. package/dist/core/runner/runtask.js.map +1 -1
  33. package/dist/core/session-reconcile.d.ts +1 -1
  34. package/dist/core/session-reconcile.d.ts.map +1 -1
  35. package/dist/core/session-reconcile.js +7 -2
  36. package/dist/core/session-reconcile.js.map +1 -1
  37. package/dist/core/task-notification.d.ts +2 -0
  38. package/dist/core/task-notification.d.ts.map +1 -1
  39. package/dist/core/task-notification.js.map +1 -1
  40. package/dist/core/task-registry.d.ts +1 -0
  41. package/dist/core/task-registry.d.ts.map +1 -1
  42. package/dist/core/task-registry.js +184 -55
  43. package/dist/core/task-registry.js.map +1 -1
  44. package/dist/core/types.d.ts +2 -0
  45. package/dist/core/types.d.ts.map +1 -1
  46. package/dist/engine/execution-env/node-execution-env.d.ts.map +1 -1
  47. package/dist/engine/execution-env/node-execution-env.js +17 -0
  48. package/dist/engine/execution-env/node-execution-env.js.map +1 -1
  49. package/dist/engine/harness/agent-harness.d.ts +1 -0
  50. package/dist/engine/harness/agent-harness.d.ts.map +1 -1
  51. package/dist/engine/harness/agent-harness.js +3 -0
  52. package/dist/engine/harness/agent-harness.js.map +1 -1
  53. package/dist/engine/harness/types.d.ts +8 -0
  54. package/dist/engine/harness/types.d.ts.map +1 -1
  55. package/dist/engine/harness/types.js.map +1 -1
  56. package/dist/engine/loop/agent-loop.js +163 -35
  57. package/dist/engine/loop/agent-loop.js.map +1 -1
  58. package/dist/engine/loop/types.d.ts +8 -0
  59. package/dist/engine/loop/types.d.ts.map +1 -1
  60. package/dist/index.d.ts +1 -1
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +1 -1
  63. package/dist/index.js.map +1 -1
  64. package/dist/orchestration/workflow.d.ts +19 -3
  65. package/dist/orchestration/workflow.d.ts.map +1 -1
  66. package/dist/orchestration/workflow.js +61 -11
  67. package/dist/orchestration/workflow.js.map +1 -1
  68. package/dist/tools/fs/index.d.ts +1 -0
  69. package/dist/tools/fs/index.d.ts.map +1 -1
  70. package/dist/tools/fs/index.js +137 -35
  71. package/dist/tools/fs/index.js.map +1 -1
  72. package/dist/tools/fs/pdf.d.ts +5 -0
  73. package/dist/tools/fs/pdf.d.ts.map +1 -1
  74. package/dist/tools/fs/pdf.js +58 -11
  75. package/dist/tools/fs/pdf.js.map +1 -1
  76. package/dist/tools/fs/safety.d.ts +1 -0
  77. package/dist/tools/fs/safety.d.ts.map +1 -1
  78. package/dist/tools/fs/safety.js +1 -0
  79. package/dist/tools/fs/safety.js.map +1 -1
  80. package/dist/tools/fs/search.d.ts +13 -0
  81. package/dist/tools/fs/search.d.ts.map +1 -1
  82. package/dist/tools/fs/search.js +58 -16
  83. package/dist/tools/fs/search.js.map +1 -1
  84. package/dist/tools/web.d.ts.map +1 -1
  85. package/dist/tools/web.js +141 -28
  86. package/dist/tools/web.js.map +1 -1
  87. package/package.json +2 -2
@@ -49,6 +49,7 @@ export declare const SUBAGENT_RESUME_CAP = 8;
49
49
  export interface SubagentRetainEntry {
50
50
  childSessionId: string;
51
51
  agentName?: string;
52
+ ttlMs?: number;
52
53
  specSnapshot: Readonly<TaskSpec>;
53
54
  internalsSnapshot: RunInternals;
54
55
  running: boolean;
@@ -63,11 +64,15 @@ export declare class SubagentRetainLedger {
63
64
  readonly max: number;
64
65
  private entries;
65
66
  private evictedIds;
67
+ private ttlTimers;
66
68
  private isDisposed;
67
69
  constructor(config: true | {
68
70
  ttlMs?: number;
69
71
  max?: number;
70
72
  });
73
+ private static readonly TOMBSTONES_MAX;
74
+ private tombstone;
75
+ private effectiveTtlMs;
71
76
  get disposed(): boolean;
72
77
  get size(): number;
73
78
  get(parentToolCallId: string): SubagentRetainEntry | undefined;
@@ -75,6 +80,8 @@ export declare class SubagentRetainLedger {
75
80
  sweepExpired(now?: number): void;
76
81
  register(parentToolCallId: string, entry: Omit<SubagentRetainEntry, "running" | "settled" | "settledAt" | "resumeCount" | "activeAbort">): SubagentRetainEntry | undefined;
77
82
  markSettled(parentToolCallId: string): void;
83
+ private armTtlTimer;
84
+ private clearTtlTimer;
78
85
  abandon(parentToolCallId: string): void;
79
86
  evict(parentToolCallId: string): Promise<void>;
80
87
  disposeAll(): Promise<void>;
@@ -107,6 +114,11 @@ export interface SubagentToolOptions {
107
114
  timeoutSec?: number;
108
115
  };
109
116
  maxDepth?: number;
117
+ retainFailedSessions?: boolean;
118
+ onObserverError?: (err: unknown, info: {
119
+ observedAgent?: string;
120
+ observerAgent?: string;
121
+ }) => void;
110
122
  }
111
123
  export declare const SUBAGENT_SYSTEM_NOTE: string;
112
124
  export declare const FORK_DIRECTIVE_FRAME = "<fork-boilerplate>\nYou are a worker fork. The transcript above is the parent's history \u2014 inherited reference, not your situation. You are NOT a continuation of that agent. Execute ONE directive, then stop.\n\nHard rules:\n- Do NOT spawn subagents with the Agent tool. The \"default to forking\" guidance is for the parent; you ARE the fork, execute directly.\n- One shot: report once and stop. No follow-up questions, no proposed next steps, no waiting for the user.\n\nGuidelines (your directive may override any of these):\n- Stay in scope. Other forks may be handling adjacent work; if you spot something outside your directive, note it in a sentence and move on.\n- Open with one line restating your task, so the parent can spot scope drift at a glance.\n- Be concise \u2014 as short as the answer allows, no shorter. Plain text, no preamble, no meta-commentary.\n- If you committed changes, list the paths and commit hashes in your report.\n</fork-boilerplate>\n\nYour directive: ";
@@ -1 +1 @@
1
- {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../src/agents/subagent.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subagent.d.ts","sourceRoot":"","sources":["../../src/agents/subagent.ts"],"names":[],"mappings":"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"}
@@ -175,6 +175,9 @@ export function classifySubagentError(child) {
175
175
  export const SUBAGENT_RESUME_CAP = 8;
176
176
  const RETAIN_DEFAULT_TTL_MS = 30 * 60 * 1000;
177
177
  const RETAIN_DEFAULT_MAX = 16;
178
+ const FAILED_SESSION_RETAIN_TTL_MS = 15 * 60 * 1000;
179
+ const PARTIAL_FINDINGS_MAX_CHARS = 1200;
180
+ const BG_NOTIFY_DRAIN_WINDOW_MS = 2_000;
178
181
  function markerFragment() {
179
182
  return uuidv7().replace(/-/g, "").slice(-12);
180
183
  }
@@ -183,12 +186,27 @@ export class SubagentRetainLedger {
183
186
  max;
184
187
  entries = new Map();
185
188
  evictedIds = new Set();
189
+ ttlTimers = new Map();
186
190
  isDisposed = false;
187
191
  constructor(config) {
188
192
  const cfg = config === true ? {} : config;
189
193
  this.ttlMs = cfg.ttlMs ?? RETAIN_DEFAULT_TTL_MS;
190
194
  this.max = cfg.max ?? RETAIN_DEFAULT_MAX;
191
195
  }
196
+ static TOMBSTONES_MAX = 512;
197
+ tombstone(parentToolCallId) {
198
+ this.evictedIds.delete(parentToolCallId);
199
+ this.evictedIds.add(parentToolCallId);
200
+ while (this.evictedIds.size > SubagentRetainLedger.TOMBSTONES_MAX) {
201
+ const oldest = this.evictedIds.values().next().value;
202
+ if (oldest === undefined)
203
+ break;
204
+ this.evictedIds.delete(oldest);
205
+ }
206
+ }
207
+ effectiveTtlMs(e) {
208
+ return e.ttlMs ?? this.ttlMs;
209
+ }
192
210
  get disposed() {
193
211
  return this.isDisposed;
194
212
  }
@@ -203,7 +221,7 @@ export class SubagentRetainLedger {
203
221
  }
204
222
  sweepExpired(now = Date.now()) {
205
223
  for (const [id, e] of this.entries) {
206
- if (e.settled && !e.running && now - e.settledAt > this.ttlMs) {
224
+ if (e.settled && !e.running && now - e.settledAt > this.effectiveTtlMs(e)) {
207
225
  void this.evict(id);
208
226
  }
209
227
  }
@@ -222,7 +240,7 @@ export class SubagentRetainLedger {
222
240
  }
223
241
  }
224
242
  if (oldest === undefined) {
225
- this.evictedIds.add(parentToolCallId);
243
+ this.tombstone(parentToolCallId);
226
244
  return undefined;
227
245
  }
228
246
  void this.evict(oldest);
@@ -237,11 +255,43 @@ export class SubagentRetainLedger {
237
255
  e.running = false;
238
256
  e.settled = true;
239
257
  e.settledAt = Date.now();
258
+ this.armTtlTimer(parentToolCallId);
259
+ }
260
+ }
261
+ armTtlTimer(parentToolCallId) {
262
+ this.clearTtlTimer(parentToolCallId);
263
+ const entry = this.entries.get(parentToolCallId);
264
+ if (!entry)
265
+ return;
266
+ const ttlMs = this.effectiveTtlMs(entry);
267
+ if (ttlMs >= 0x7fffffff)
268
+ return;
269
+ const t = setTimeout(() => {
270
+ this.ttlTimers.delete(parentToolCallId);
271
+ const e = this.entries.get(parentToolCallId);
272
+ if (!e)
273
+ return;
274
+ if (e.settled && !e.running && Date.now() - e.settledAt > this.effectiveTtlMs(e)) {
275
+ void this.evict(parentToolCallId);
276
+ }
277
+ else {
278
+ this.armTtlTimer(parentToolCallId);
279
+ }
280
+ }, ttlMs + 1);
281
+ t.unref?.();
282
+ this.ttlTimers.set(parentToolCallId, t);
283
+ }
284
+ clearTtlTimer(parentToolCallId) {
285
+ const t = this.ttlTimers.get(parentToolCallId);
286
+ if (t !== undefined) {
287
+ clearTimeout(t);
288
+ this.ttlTimers.delete(parentToolCallId);
240
289
  }
241
290
  }
242
291
  abandon(parentToolCallId) {
243
292
  if (this.entries.delete(parentToolCallId)) {
244
- this.evictedIds.add(parentToolCallId);
293
+ this.clearTtlTimer(parentToolCallId);
294
+ this.tombstone(parentToolCallId);
245
295
  }
246
296
  }
247
297
  async evict(parentToolCallId) {
@@ -249,7 +299,8 @@ export class SubagentRetainLedger {
249
299
  if (!e)
250
300
  return;
251
301
  this.entries.delete(parentToolCallId);
252
- this.evictedIds.add(parentToolCallId);
302
+ this.clearTtlTimer(parentToolCallId);
303
+ this.tombstone(parentToolCallId);
253
304
  try {
254
305
  e.activeAbort?.abort();
255
306
  }
@@ -265,8 +316,13 @@ export class SubagentRetainLedger {
265
316
  }
266
317
  }
267
318
  const sessionRetainLedgers = new Map();
319
+ const SESSION_RETAIN_LEDGERS_MAX = 64;
268
320
  export function getSessionRetainLedger(sessionId) {
269
- return sessionRetainLedgers.get(sessionId)?.ledger;
321
+ const row = sessionRetainLedgers.get(sessionId);
322
+ if (!row)
323
+ return undefined;
324
+ row.touchedAt = Date.now();
325
+ return row.ledger;
270
326
  }
271
327
  function getOrCreateSessionRetainLedger(sessionId, config) {
272
328
  const now = Date.now();
@@ -280,6 +336,21 @@ function getOrCreateSessionRetainLedger(sessionId, config) {
280
336
  existing.touchedAt = now;
281
337
  return existing.ledger;
282
338
  }
339
+ while (sessionRetainLedgers.size >= SESSION_RETAIN_LEDGERS_MAX) {
340
+ let lru;
341
+ let lruAt = Infinity;
342
+ for (const [sid, row] of sessionRetainLedgers) {
343
+ if (row.touchedAt < lruAt) {
344
+ lru = sid;
345
+ lruAt = row.touchedAt;
346
+ }
347
+ }
348
+ if (lru === undefined)
349
+ break;
350
+ const row = sessionRetainLedgers.get(lru);
351
+ sessionRetainLedgers.delete(lru);
352
+ void row.ledger.disposeAll();
353
+ }
283
354
  const ledger = new SubagentRetainLedger(config);
284
355
  sessionRetainLedgers.set(sessionId, { ledger, touchedAt: now });
285
356
  return ledger;
@@ -405,6 +476,7 @@ function makeSubagentResume(deps) {
405
476
  status: child.status === "completed" ? "completed" : abort.signal.aborted ? "killed" : "failed",
406
477
  summary: `resumed sub-agent ${marker} — ${child.status !== "completed" && abort.signal.aborted ? "killed" : child.status}`,
407
478
  ...(child.result ? { result: child.result.slice(0, 2_000) } : {}),
479
+ ...(child.status !== "completed" && abort.signal.aborted && child.result ? { partial: true } : {}),
408
480
  usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: child.stats.costMicroUsd },
409
481
  }, { priority: "later" });
410
482
  }
@@ -428,6 +500,7 @@ function makeSubagentResume(deps) {
428
500
  entry.running = false;
429
501
  entry.activeAbort = undefined;
430
502
  entry.settledAt = Date.now();
503
+ ledger.markSettled(deps.parentToolCallId);
431
504
  settleResolve();
432
505
  }
433
506
  })();
@@ -726,6 +799,20 @@ function makeSubagentTool(opts, depth, excluded) {
726
799
  let observerPairing;
727
800
  let observerTap;
728
801
  let observerSessionId;
802
+ let observerFailure;
803
+ const noteObserverFailure = (err) => {
804
+ if (observerFailure === undefined) {
805
+ observerFailure = (err instanceof Error ? err.message : String(err)).slice(0, REPORT_FIELD_MAX);
806
+ }
807
+ try {
808
+ opts.onObserverError?.(err, {
809
+ ...(def !== undefined ? { observedAgent: def.name } : {}),
810
+ ...(observerArm ? { observerAgent: observerArm.observerDefinition.name } : {}),
811
+ });
812
+ }
813
+ catch {
814
+ }
815
+ };
729
816
  const observedSteerRef = {};
730
817
  if (observerArm) {
731
818
  const observerDef = observerArm.observerDefinition;
@@ -771,6 +858,7 @@ function makeSubagentTool(opts, depth, excluded) {
771
858
  ...(observerArm.observerMessage !== undefined ? { observerMessage: observerArm.observerMessage } : {}),
772
859
  spawner,
773
860
  framingPrompt: observerFramingPrompt({ observedEnvelopeName: envelopeName, ...(childAgentName !== undefined ? { observedTaskLabel: childAgentName } : {}) }),
861
+ onError: noteObserverFailure,
774
862
  });
775
863
  reportOpts.pairing = observerPairing;
776
864
  observerTap = new ObserverDigestTap((activity) => observerPairing.enqueueSegment(activity));
@@ -800,6 +888,8 @@ function makeSubagentTool(opts, depth, excluded) {
800
888
  t.unref?.();
801
889
  });
802
890
  const outcome = await Promise.race([observerPairing.drain().then(() => "drained"), timeout]);
891
+ if (outcome === "timeout")
892
+ noteObserverFailure(new Error("observer unresponsive at settle (delivery drain timed out)"));
803
893
  observerPairing.retire(outcome === "timeout" ? "stopped" : "retired");
804
894
  if (observerSessionId !== undefined) {
805
895
  try {
@@ -815,10 +905,29 @@ function makeSubagentTool(opts, depth, excluded) {
815
905
  closeObserverWindow(status);
816
906
  await drainAndReleaseObserver();
817
907
  };
908
+ const startBoundedObserverDrain = async () => {
909
+ const drain = drainAndReleaseObserver().catch(() => undefined);
910
+ if (observerPairing === undefined)
911
+ return "drained";
912
+ let timer;
913
+ const timeout = new Promise((resolve) => {
914
+ timer = setTimeout(() => resolve("still_draining"), BG_NOTIFY_DRAIN_WINDOW_MS);
915
+ timer.unref?.();
916
+ });
917
+ const outcome = await Promise.race([drain.then(() => "drained"), timeout]);
918
+ if (timer !== undefined)
919
+ clearTimeout(timer);
920
+ return outcome;
921
+ };
922
+ const observerNoteFor = (outcome) => observerFailure !== undefined ? " [observer: failed]" : outcome === "still_draining" ? " [observer: still draining]" : "";
818
923
  const stepRecorder = new SubagentStepRecorder(ctx.toolCallId);
819
924
  const toolStatsCounter = makeToolStatsCounter(opts.name ?? DEFAULT_SUBAGENT_TOOL_NAME);
925
+ let assistantTextTail = "";
820
926
  const recordingForward = (e) => {
821
927
  stepRecorder.record(e);
928
+ if (e.type === "text_delta" && e.parentToolCallId === ctx.toolCallId) {
929
+ assistantTextTail = (assistantTextTail + e.delta).slice(-PARTIAL_FINDINGS_MAX_CHARS);
930
+ }
822
931
  if (e.type === "tool_start")
823
932
  toolStatsCounter.record(e.toolName, e.args);
824
933
  if (e.type === "task_progress") {
@@ -860,13 +969,14 @@ function makeSubagentTool(opts, depth, excluded) {
860
969
  limits: childLimits,
861
970
  signal,
862
971
  });
863
- const tryRetainChild = async (ledger) => {
972
+ const tryRetainChild = async (ledger, entryTtlMs) => {
864
973
  if (!ledger)
865
974
  return undefined;
866
975
  const childSessionId = uuidv7();
867
976
  const { signal: _spawnSignal, ...plainSpec } = buildChildSpec(undefined);
868
977
  let entry = ledger.register(ctx.toolCallId, {
869
978
  childSessionId,
979
+ ...(entryTtlMs !== undefined ? { ttlMs: entryTtlMs } : {}),
870
980
  ...(childAgentName !== undefined ? { agentName: childAgentName } : {}),
871
981
  specSnapshot: Object.freeze({
872
982
  ...plainSpec,
@@ -897,9 +1007,85 @@ function makeSubagentTool(opts, depth, excluded) {
897
1007
  await ledger.evict(ctx.toolCallId);
898
1008
  entry = undefined;
899
1009
  }
1010
+ if (entry !== undefined && (ledger.disposed || ledger.get(ctx.toolCallId) !== entry)) {
1011
+ try {
1012
+ await opts.runner.sessions.unpin?.(childSessionId);
1013
+ }
1014
+ catch {
1015
+ }
1016
+ try {
1017
+ await opts.runner.sessions.release(childSessionId);
1018
+ }
1019
+ catch {
1020
+ }
1021
+ entry = undefined;
1022
+ }
900
1023
  }
901
1024
  return entry;
902
1025
  };
1026
+ const retainFailedChildSession = async (childSessionId) => {
1027
+ const releaseChild = async () => {
1028
+ try {
1029
+ await opts.runner.sessions.unpin?.(childSessionId);
1030
+ }
1031
+ catch {
1032
+ }
1033
+ try {
1034
+ await opts.runner.sessions.release(childSessionId);
1035
+ }
1036
+ catch {
1037
+ }
1038
+ };
1039
+ const ledger = ctx.sessionId !== undefined
1040
+ ? getOrCreateSessionRetainLedger(ctx.sessionId, { ttlMs: FAILED_SESSION_RETAIN_TTL_MS, max: RETAIN_DEFAULT_MAX })
1041
+ : ctx.subagentRetain;
1042
+ if (ledger !== undefined && !ledger.disposed) {
1043
+ if (opts.background)
1044
+ ensureSessionReapHook(opts.background.registry);
1045
+ const { signal: _spawnSignal, ...plainSpec } = buildChildSpec(undefined);
1046
+ const entry = ledger.register(ctx.toolCallId, {
1047
+ childSessionId,
1048
+ ttlMs: FAILED_SESSION_RETAIN_TTL_MS,
1049
+ ...(childAgentName !== undefined ? { agentName: childAgentName } : {}),
1050
+ specSnapshot: Object.freeze({
1051
+ ...plainSpec,
1052
+ tools: [...(plainSpec.tools ?? [])],
1053
+ ...(plainSpec.limits ? { limits: { ...plainSpec.limits } } : {}),
1054
+ ...(plainSpec.memory !== undefined && typeof plainSpec.memory === "object" ? { memory: { ...plainSpec.memory } } : {}),
1055
+ ...(plainSpec.clientContext !== undefined ? { clientContext: { ...plainSpec.clientContext } } : {}),
1056
+ }),
1057
+ internalsSnapshot: { ...childInternals },
1058
+ release: releaseChild,
1059
+ });
1060
+ if (entry) {
1061
+ try {
1062
+ await opts.runner.sessions.pin?.(childSessionId);
1063
+ }
1064
+ catch {
1065
+ try {
1066
+ await opts.runner.sessions.unpin?.(childSessionId);
1067
+ }
1068
+ catch {
1069
+ }
1070
+ ledger.abandon(ctx.toolCallId);
1071
+ return false;
1072
+ }
1073
+ if (ledger.disposed || ledger.get(ctx.toolCallId) !== entry) {
1074
+ try {
1075
+ await opts.runner.sessions.unpin?.(childSessionId);
1076
+ }
1077
+ catch {
1078
+ }
1079
+ return false;
1080
+ }
1081
+ ledger.markSettled(ctx.toolCallId);
1082
+ return true;
1083
+ }
1084
+ }
1085
+ const timer = setTimeout(() => void releaseChild(), FAILED_SESSION_RETAIN_TTL_MS);
1086
+ timer.unref?.();
1087
+ return true;
1088
+ };
903
1089
  if (wantsFork) {
904
1090
  let forkedId;
905
1091
  try {
@@ -1051,6 +1237,7 @@ function makeSubagentTool(opts, depth, excluded) {
1051
1237
  summary: `${shortDesc} — ${settledBg === "killed" ? "stopped" : child.status}`,
1052
1238
  ...(child.sessionId ? { sessionId: child.sessionId } : {}),
1053
1239
  ...(child.result ? { result: child.result.slice(0, 2_000) } : {}),
1240
+ ...(settledBg === "killed" && child.result ? { partial: true } : {}),
1054
1241
  ...residualFork,
1055
1242
  resumable: resumableFork,
1056
1243
  usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
@@ -1231,7 +1418,7 @@ task_id: ${taskId}
1231
1418
  : ctx.subagentRetain;
1232
1419
  if (sessionScopedBg && bgRetainLedger)
1233
1420
  ensureSessionReapHook(bg.registry);
1234
- const bgRetain = await tryRetainChild(bgRetainLedger);
1421
+ const bgRetain = await tryRetainChild(bgRetainLedger, sessionScopedBg && ctx.subagentRetain ? ctx.subagentRetain.ttlMs : undefined);
1235
1422
  if (bgRetain)
1236
1423
  stepRecorder.lockTo(bgRetain.childSessionId);
1237
1424
  const bgSpec = { ...buildChildSpec(abort.signal), ...(bgRetain ? { sessionId: bgRetain.childSessionId } : {}) };
@@ -1315,6 +1502,7 @@ task_id: ${taskId}
1315
1502
  }) ??
1316
1503
  (abort.signal.aborted ? "killed" : ok ? "completed" : "failed");
1317
1504
  const stoppedBy = settled === "killed" ? bg.registry.getStopAttribution(taskId) ?? "system" : undefined;
1505
+ const observerNote = observerNoteFor(await startBoundedObserverDrain());
1318
1506
  const residual = residualFields();
1319
1507
  const resumableBg = bgRetain !== undefined && settled !== "killed";
1320
1508
  sinkEmit({
@@ -1324,7 +1512,7 @@ task_id: ${taskId}
1324
1512
  ...(child.sessionId ? { sessionId: child.sessionId, transcriptId: child.sessionId } : {}),
1325
1513
  status: settled,
1326
1514
  ...(stoppedBy !== undefined ? { stoppedBy } : {}),
1327
- summary: `${shortDesc} — ${settled === "killed" ? "stopped" : child.status}`,
1515
+ summary: `${shortDesc} — ${settled === "killed" ? "stopped" : child.status}${observerNote}`,
1328
1516
  ...residual,
1329
1517
  resumable: resumableBg,
1330
1518
  usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
@@ -1336,9 +1524,10 @@ task_id: ${taskId}
1336
1524
  toolUseId: ctx.toolCallId,
1337
1525
  status: settled,
1338
1526
  ...(stoppedBy !== undefined ? { stoppedBy } : {}),
1339
- summary: `${shortDesc} — ${settled === "killed" ? "stopped" : child.status}`,
1527
+ summary: `${shortDesc} — ${settled === "killed" ? "stopped" : child.status}${observerNote}`,
1340
1528
  ...(child.sessionId ? { sessionId: child.sessionId } : {}),
1341
1529
  ...(child.result ? { result: child.result.slice(0, 2_000) } : {}),
1530
+ ...(settled === "killed" && child.result ? { partial: true } : {}),
1342
1531
  ...residual,
1343
1532
  resumable: resumableBg,
1344
1533
  usage: { tokens: child.stats.tokens, turns: child.stats.turns, costMicroUsd: (child.stats.costMicroUsd ?? 0) + (child.stats.nested?.costMicroUsd ?? 0) },
@@ -1346,11 +1535,9 @@ task_id: ${taskId}
1346
1535
  }
1347
1536
  catch {
1348
1537
  }
1349
- void drainAndReleaseObserver();
1350
1538
  })
1351
- .catch((e) => {
1539
+ .catch(async (e) => {
1352
1540
  closeObserverWindow("failed");
1353
- void drainAndReleaseObserver();
1354
1541
  dropHostAbortListener();
1355
1542
  void finishWorktree();
1356
1543
  const killed = abort.signal.aborted;
@@ -1363,13 +1550,14 @@ task_id: ${taskId}
1363
1550
  const msg = e instanceof Error ? e.message : String(e);
1364
1551
  const settled = bg.registry.settleBackgroundAgent(taskId, { status: killed ? "killed" : "failed", error: msg }) ?? (killed ? "killed" : "failed");
1365
1552
  const stoppedBy = settled === "killed" ? bg.registry.getStopAttribution(taskId) ?? "system" : undefined;
1553
+ const observerNote = observerNoteFor(await startBoundedObserverDrain());
1366
1554
  sinkEmit({
1367
1555
  kind: "terminal",
1368
1556
  taskId,
1369
1557
  sessionScoped: sessionScopedBg === true,
1370
1558
  status: settled,
1371
1559
  ...(stoppedBy !== undefined ? { stoppedBy } : {}),
1372
- summary: `${shortDesc} — ${settled === "failed" ? `failed: ${msg}` : settled}`.slice(0, 300),
1560
+ summary: `${shortDesc} — ${settled === "failed" ? `failed: ${msg}` : settled}${observerNote}`.slice(0, 300),
1373
1561
  });
1374
1562
  try {
1375
1563
  notify?.({
@@ -1378,7 +1566,7 @@ task_id: ${taskId}
1378
1566
  toolUseId: ctx.toolCallId,
1379
1567
  status: settled,
1380
1568
  ...(stoppedBy !== undefined ? { stoppedBy } : {}),
1381
- summary: `${shortDesc} — ${settled === "failed" ? `failed: ${msg}` : settled}`.slice(0, 300),
1569
+ summary: `${shortDesc} — ${settled === "failed" ? `failed: ${msg}` : settled}${observerNote}`.slice(0, 300),
1382
1570
  }, { priority: "later" });
1383
1571
  }
1384
1572
  catch {
@@ -1467,11 +1655,17 @@ task_id: ${taskId}
1467
1655
  details: { error: child.status === "needs_review" ? "unexpected.needs_review" : "unexpected.suspended", checkpointToken: child.checkpointToken },
1468
1656
  };
1469
1657
  }
1658
+ let failureRetained = false;
1470
1659
  if (!retainEntry) {
1471
- try {
1472
- await opts.runner.sessions.release(child.sessionId);
1660
+ if (child.status !== "completed" && opts.retainFailedSessions !== false) {
1661
+ failureRetained = await retainFailedChildSession(child.sessionId);
1473
1662
  }
1474
- catch {
1663
+ if (!failureRetained) {
1664
+ try {
1665
+ await opts.runner.sessions.release(child.sessionId);
1666
+ }
1667
+ catch {
1668
+ }
1475
1669
  }
1476
1670
  }
1477
1671
  const worktreeLine = await finishWorktree();
@@ -1484,9 +1678,13 @@ task_id: ${taskId}
1484
1678
  child.blockedReason ? `blocked_reason: ${inlineUntrusted(child.blockedReason, REPORT_FIELD_MAX)}` : "",
1485
1679
  child.errorMessage ? `error: ${inlineUntrusted(child.errorMessage, REPORT_FIELD_MAX)}` : "",
1486
1680
  errClass ? `error_kind: ${errClass.errorKind} (retryable: ${errClass.retryable})` : "",
1681
+ observerFailure !== undefined ? `observer: failed (${inlineUntrusted(observerFailure, REPORT_FIELD_MAX)})` : "",
1487
1682
  `stats: turns=${child.stats.turns} tokens=${child.stats.tokens}`,
1488
- retainEntry ? `transcript_id: ${child.sessionId}` : "",
1683
+ retainEntry || failureRetained ? `transcript_id: ${child.sessionId}` : "",
1489
1684
  retainEntry ? `resumable: true` : "",
1685
+ failureRetained
1686
+ ? `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.`
1687
+ : "",
1490
1688
  ...(child.status !== "completed"
1491
1689
  ? (() => {
1492
1690
  const rs = stepRecorder.recentSteps();
@@ -1506,7 +1704,11 @@ task_id: ${taskId}
1506
1704
  : []),
1507
1705
  "",
1508
1706
  "result:",
1509
- child.result ? delimitUntrusted("sub-agent result", child.result) : "(no text result)",
1707
+ child.result
1708
+ ? delimitUntrusted("sub-agent result", child.result)
1709
+ : child.status !== "completed" && assistantTextTail.trim() !== ""
1710
+ ? `partial findings (the child's last assistant text before it stopped):\n${delimitUntrusted("sub-agent partial findings", assistantTextTail.trim())}`
1711
+ : "(no text result)",
1510
1712
  "",
1511
1713
  "Verify this result before concluding. If it leaves more to do, continue or delegate again.",
1512
1714
  ].filter(Boolean);