@sema-agent/core 3.0.0 → 5.0.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 (153) hide show
  1. package/CHANGELOG.md +2382 -0
  2. package/dist/agents/cascade.d.ts +3 -1
  3. package/dist/agents/cascade.js +31 -32
  4. package/dist/agents/cumulative-stats.d.ts +29 -0
  5. package/dist/agents/cumulative-stats.js +29 -0
  6. package/dist/agents/observer.d.ts +4 -0
  7. package/dist/agents/observer.js +11 -10
  8. package/dist/agents/repair-loop.d.ts +2 -0
  9. package/dist/agents/repair-loop.js +48 -24
  10. package/dist/agents/retain-ledger.d.ts +2 -0
  11. package/dist/agents/retain-ledger.js +6 -5
  12. package/dist/agents/roster-store.d.ts +1 -0
  13. package/dist/agents/roster-store.js +3 -5
  14. package/dist/agents/send-message-tool.d.ts +1 -0
  15. package/dist/agents/send-message-tool.js +2 -0
  16. package/dist/agents/subagent.d.ts +3 -1
  17. package/dist/agents/subagent.js +79 -94
  18. package/dist/agents/teacher.d.ts +1 -9
  19. package/dist/agents/teacher.js +21 -24
  20. package/dist/agents/tool-filter.js +6 -7
  21. package/dist/agents/verify.d.ts +1 -0
  22. package/dist/agents/verify.js +15 -14
  23. package/dist/brain/anthropic.js +24 -21
  24. package/dist/brain/openai.js +24 -21
  25. package/dist/brain/stream-engine.js +5 -2
  26. package/dist/brain/stream-shared.d.ts +1 -0
  27. package/dist/brain/stream-shared.js +14 -0
  28. package/dist/brain/terminal-cause.d.ts +4 -0
  29. package/dist/brain/terminal-cause.js +12 -0
  30. package/dist/brain/tool-call-id.d.ts +1 -0
  31. package/dist/brain/tool-call-id.js +3 -0
  32. package/dist/brain/tool-call-repair.js +2 -1
  33. package/dist/core/arg-summary.d.ts +21 -1
  34. package/dist/core/arg-summary.js +61 -14
  35. package/dist/core/auto-compaction.d.ts +1 -0
  36. package/dist/core/auto-compaction.js +16 -25
  37. package/dist/core/background-agent-store.d.ts +22 -22
  38. package/dist/core/background-agent-store.js +19 -23
  39. package/dist/core/checkpoint-store.d.ts +6 -13
  40. package/dist/core/checkpoint-store.js +11 -5
  41. package/dist/core/file-snapshot-store.d.ts +8 -0
  42. package/dist/core/file-snapshot-store.js +4 -3
  43. package/dist/core/fs-write-gate-policy.js +2 -3
  44. package/dist/core/hooks.d.ts +4 -1
  45. package/dist/core/hooks.js +8 -18
  46. package/dist/core/lsp.js +4 -3
  47. package/dist/core/mailbox-store.d.ts +7 -10
  48. package/dist/core/mcp.d.ts +7 -10
  49. package/dist/core/mcp.js +7 -9
  50. package/dist/core/memory-engine/engine.d.ts +0 -1
  51. package/dist/core/memory-engine/engine.js +24 -34
  52. package/dist/core/memory-engine/file-backend.d.ts +1 -2
  53. package/dist/core/memory-engine/file-backend.js +25 -36
  54. package/dist/core/memory-engine/layout.d.ts +8 -0
  55. package/dist/core/memory-engine/layout.js +60 -4
  56. package/dist/core/memory-engine/scope-contract.js +9 -3
  57. package/dist/core/memory-engine/types.d.ts +1 -1
  58. package/dist/core/permission-rules.js +2 -3
  59. package/dist/core/runner/active-skill-scope.d.ts +0 -1
  60. package/dist/core/runner/active-skill-scope.js +2 -17
  61. package/dist/core/runner/assemble-result.d.ts +2 -7
  62. package/dist/core/runner/assemble-result.js +3 -4
  63. package/dist/core/runner/compaction-call-options.d.ts +7 -0
  64. package/dist/core/runner/compaction-call-options.js +30 -0
  65. package/dist/core/runner/prepare-task.d.ts +6 -23
  66. package/dist/core/runner/prepare-task.js +36 -61
  67. package/dist/core/runner/runtask.d.ts +1 -0
  68. package/dist/core/runner/runtask.js +84 -172
  69. package/dist/core/runner/session-rule-policy.js +7 -5
  70. package/dist/core/runner/teardown-bounded.d.ts +7 -0
  71. package/dist/core/runner/teardown-bounded.js +36 -0
  72. package/dist/core/runner/tool-disclosure.d.ts +2 -5
  73. package/dist/core/runner/turn-attachments.d.ts +5 -15
  74. package/dist/core/runner/turn-attachments.js +1 -1
  75. package/dist/core/safe-notify.d.ts +17 -0
  76. package/dist/core/safe-notify.js +59 -0
  77. package/dist/core/sensitive-path-policy.js +4 -4
  78. package/dist/core/session-reconcile.js +1 -2
  79. package/dist/core/skill-tool-specifier.js +2 -3
  80. package/dist/core/skills-directory.js +2 -3
  81. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  82. package/dist/core/stub-env.d.ts +2 -6
  83. package/dist/core/surrogate-safe-slice.d.ts +4 -0
  84. package/dist/core/surrogate-safe-slice.js +18 -0
  85. package/dist/core/task-registry-monitor.js +8 -13
  86. package/dist/core/task-registry-shared.d.ts +23 -1
  87. package/dist/core/task-registry-shared.js +16 -0
  88. package/dist/core/task-registry.d.ts +6 -1
  89. package/dist/core/task-registry.js +52 -87
  90. package/dist/core/task-tool-shape.d.ts +0 -2
  91. package/dist/core/task-tool-shape.js +2 -5
  92. package/dist/core/tool-errors.js +5 -4
  93. package/dist/core/tool-name-aliases.d.ts +1 -2
  94. package/dist/core/tool-name-aliases.js +42 -59
  95. package/dist/core/tool-policy.js +21 -17
  96. package/dist/core/tool-result-store.d.ts +1 -0
  97. package/dist/core/tool-result-store.js +17 -1
  98. package/dist/core/trace.d.ts +9 -9
  99. package/dist/core/types.d.ts +15 -12
  100. package/dist/core/untrusted-egress.d.ts +4 -2
  101. package/dist/core/untrusted-egress.js +28 -14
  102. package/dist/core/workflow-journal-store.d.ts +9 -20
  103. package/dist/core/workflow-run-store.d.ts +11 -10
  104. package/dist/core/workflow-run-store.js +22 -16
  105. package/dist/engine/compaction/utils.js +4 -2
  106. package/dist/engine/execution-env/node-execution-env.d.ts +2 -24
  107. package/dist/engine/execution-env/node-execution-env.js +1 -1
  108. package/dist/engine/harness/agent-harness.d.ts +1 -0
  109. package/dist/engine/harness/agent-harness.js +13 -33
  110. package/dist/engine/harness/types.d.ts +29 -67
  111. package/dist/engine/llm/types.d.ts +1 -1
  112. package/dist/engine/loop/agent-loop.js +12 -14
  113. package/dist/engine/loop/types.d.ts +11 -9
  114. package/dist/engine/session/memory-repo.d.ts +2 -6
  115. package/dist/engine/session/session.d.ts +5 -30
  116. package/dist/index.d.ts +6 -3
  117. package/dist/index.js +4 -3
  118. package/dist/internal/harness-types.d.ts +3 -1
  119. package/dist/orchestration/run-spec.js +6 -4
  120. package/dist/orchestration/run-workflow-tool.js +3 -36
  121. package/dist/orchestration/workflow-governance.js +2 -1
  122. package/dist/orchestration/workflow.d.ts +4 -11
  123. package/dist/orchestration/workflow.js +164 -204
  124. package/dist/prompt-assembly/packs/sema-default.js +1 -3
  125. package/dist/prompt-assembly/tool-catalog.d.ts +10 -9
  126. package/dist/prompt-assembly/turn-snapshot.d.ts +2 -5
  127. package/dist/prompts/default.js +1 -3
  128. package/dist/prompts/simple-sections.d.ts +0 -1
  129. package/dist/prompts/simple-sections.js +0 -1
  130. package/dist/stores/file/background-agent-store.d.ts +3 -12
  131. package/dist/stores/file/background-agent-store.js +3 -41
  132. package/dist/stores/file/checkpoint-store.js +6 -6
  133. package/dist/stores/file/mailbox-store.d.ts +2 -6
  134. package/dist/stores/file/session-policy-store.js +15 -1
  135. package/dist/stores/file/session-store.d.ts +2 -6
  136. package/dist/stores/file/workflow-journal-store.d.ts +3 -11
  137. package/dist/stores/file/workflow-run-store.d.ts +3 -7
  138. package/dist/stores/file/workflow-run-store.js +4 -17
  139. package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -0
  140. package/dist/tools/fs/bash-readonly-classifier.js +60 -25
  141. package/dist/tools/fs/fs-bash.js +330 -104
  142. package/dist/tools/fs/fs-pdf.d.ts +2 -12
  143. package/dist/tools/fs/fs-shared.js +2 -2
  144. package/dist/tools/fs/fs-write.js +0 -1
  145. package/dist/tools/fs/notebook.d.ts +2 -5
  146. package/dist/tools/fs/safety.d.ts +3 -0
  147. package/dist/tools/fs/safety.js +43 -14
  148. package/dist/tools/fs/search.js +5 -5
  149. package/dist/tools/monitor.d.ts +1 -0
  150. package/dist/tools/monitor.js +7 -5
  151. package/dist/tools/worktree.d.ts +2 -7
  152. package/dist/tools/worktree.js +3 -1
  153. package/package.json +6 -2
@@ -29,9 +29,9 @@ import { reconcileInterruptedSession } from "../session-reconcile.js";
29
29
  import { CacheBreakDetector, toolsToFingerprintInputs } from "../cache-break-detector.js";
30
30
  import { reservedCollisions, reservedFor } from "../../brain/request-params.js";
31
31
  import { defineTool, isDefineToolProduct } from "../tools.js";
32
- import { canonicalToolName } from "../tool-name-aliases.js";
32
+ import { RETIRED_TOOL_NAMES } from "../tool-name-aliases.js";
33
33
  import { pathToUri } from "../lsp-protocol.js";
34
- import { DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, buildToolResultRef, firstPartyOffloadPolicy, InMemoryToolResultStore, RunnerSharedToolResultStore, ScopedToolResultStore, isVolatileOffloadStore, OFFLOAD_TOOL_NAME, createReadToolResultTool, withToolResultOffload, } from "../tool-result-store.js";
34
+ import { DEFAULT_TOOL_RESULT_THRESHOLD_CHARS, createOffloadPersist, firstPartyOffloadPolicy, InMemoryToolResultStore, RunnerSharedToolResultStore, ScopedToolResultStore, isVolatileOffloadStore, OFFLOAD_TOOL_NAME, createReadToolResultTool, withToolResultOffload, } from "../tool-result-store.js";
35
35
  import { OUTPUT_TOOL_NAME, REPORT_FINDINGS_TOOL_NAME, SKILL_CONTENT_MAX_CHARS, SKILL_TOOL_NAME, createOutputTool, createReportBlockedTool, createReportFindingsTool, createSkillTool, normalizeSkills } from "./synthetic-tools.js";
36
36
  import { compileOutputSchema } from "./strict-output-schema.js";
37
37
  import { TOOL_SEARCH_NAME, buildDeferredRegistry, classifyDeferred, extractDiscoveredToolNames, createPlaceholderTool, createToolSearchTool, } from "./tool-disclosure.js";
@@ -51,6 +51,7 @@ import { dropOrphanToolResults, guardBudget, insertTrimNotice, trimToBudget } fr
51
51
  import { StubExecutionEnv } from "../stub-env.js";
52
52
  import { hasDestroy, isIsolated, isRemoteExecutionEnv, isRetryableRemoteErrorCode, isSuspendable, missingRestoreSurface, RETRYABLE_REMOTE_ERROR_CODES } from "../remote-env.js";
53
53
  import { withRetry } from "../with-retry.js";
54
+ import { settleTeardownLeg } from "./teardown-bounded.js";
54
55
  import { hasBackgroundShell, sweepBackgroundShells } from "../background-shell.js";
55
56
  import { createTaskOutputTool, createTaskStopTool, defaultTaskRegistry } from "../task-registry.js";
56
57
  import { createMonitorTool } from "../../tools/monitor.js";
@@ -62,7 +63,7 @@ import { createSchedulerTools } from "../../tools/scheduler-tools.js";
62
63
  import { createPresentPlanTool, createEnterPlanModeTool, PRESENT_PLAN_TOOL_NAME, ENTER_PLAN_MODE_TOOL_NAME } from "../present-plan-tool.js";
63
64
  import { isSelfOrchestrationActive, selfOrchestrationFailClosedReason } from "../../orchestration/workflow-script-runner.js";
64
65
  import { createRunWorkflowTool, RUN_WORKFLOW_TOOL_NAME } from "../../orchestration/run-workflow-tool.js";
65
- import { createLspTool, gitCheckIgnoreFilter } from "../lsp.js";
66
+ import { createLspTool, gitCheckIgnoreFilter, resolveLspPath } from "../lsp.js";
66
67
  import { resolveKey } from "../../tools/fs/safety.js";
67
68
  import { BINDING_CHECKPOINT_VERSION, mintCheckpointToken, RESOURCE_CHECKPOINT_VERSION, WALLTIME_CHECKPOINT_VERSION, buildRiskDescriptor, debitLedger, remainingBudgetMicroUsd, } from "../checkpoint-store.js";
68
69
  import { boundInputHashOf } from "../canonical-json.js";
@@ -442,18 +443,21 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
442
443
  if (extraBodyCollisions.length > 0) {
443
444
  deps.onError?.(new Error(`model.extraBody contains reserved key(s) [${extraBodyCollisions.join(", ")}] that core owns and sets itself — they are ignored. Remove them from extraBody.`), { phase: "config", sessionId });
444
445
  }
445
- const nestedStats = { tokens: 0, turns: 0, tasks: 0, costMicroUsd: 0 };
446
+ const nestedStats = { tokens: 0, turns: 0, tasks: 0, costMicroUsd: 0, anyUnpriced: false };
446
447
  if (resume) {
447
448
  nestedStats.tokens = resume.seed.nestedStats.tokens;
448
449
  nestedStats.turns = resume.seed.nestedStats.turns;
449
450
  nestedStats.tasks = resume.seed.nestedStats.tasks;
450
451
  nestedStats.costMicroUsd = resume.seed.nestedStats.costMicroUsd;
452
+ nestedStats.anyUnpriced = resume.seed.nestedStats.anyUnpriced ?? true;
451
453
  }
452
454
  const reportUsage = (u) => {
453
455
  nestedStats.tokens += u.tokens;
454
456
  nestedStats.turns += u.turns;
455
457
  nestedStats.tasks += u.tasks;
456
458
  nestedStats.costMicroUsd += u.costMicroUsd ?? 0;
459
+ if (u.costMicroUsd === undefined)
460
+ nestedStats.anyUnpriced = true;
457
461
  };
458
462
  const explicitGlobalThreshold = spec.toolResultThresholdChars ?? deps.toolResultThresholdChars;
459
463
  const offloadThreshold = explicitGlobalThreshold ?? DEFAULT_TOOL_RESULT_THRESHOLD_CHARS;
@@ -482,13 +486,13 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
482
486
  if (offloadStore && (spec.tools ?? []).some((t) => t.name === OFFLOAD_TOOL_NAME)) {
483
487
  const e = new Error(`Tool name "${OFFLOAD_TOOL_NAME}" is reserved when large-result offload is enabled.`);
484
488
  e.code = "config.reserved_tool_name";
485
- await forgetOnThrow();
489
+ await settleTeardownLeg(() => forgetOnThrow(), "forgetOnThrow (reserved-name leg)", (err) => deps.onError?.(err, { phase: "config", sessionId }));
486
490
  throw e;
487
491
  }
488
492
  let ownedEnv;
489
493
  let mcp;
490
494
  if (internals?.requestedCwd !== undefined && deps.executionEnvFactory === undefined) {
491
- await forgetOnThrow();
495
+ await settleTeardownLeg(() => forgetOnThrow(), "forgetOnThrow (cwd-unsupported leg)", (err) => deps.onError?.(err, { phase: "config", sessionId }));
492
496
  const e = new Error(`Agent cwd "${internals.requestedCwd}" cannot take effect: this deployment has no executionEnvFactory (a static execution environment cannot be re-rooted per agent). Drop the cwd parameter or deploy a factory.`);
493
497
  e.code = "config.cwd_unsupported";
494
498
  throw e;
@@ -504,7 +508,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
504
508
  : undefined;
505
509
  }
506
510
  catch (factoryErr) {
507
- await forgetOnThrow();
511
+ await settleTeardownLeg(() => forgetOnThrow(), "forgetOnThrow (env-factory-throw leg)", (err) => deps.onError?.(err, { phase: "config", sessionId }));
508
512
  throw factoryErr;
509
513
  }
510
514
  const executionEnv = ownedEnv ?? deps.executionEnv ?? new StubExecutionEnv();
@@ -515,13 +519,8 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
515
519
  };
516
520
  const want = await canon(internals.requestedCwd);
517
521
  const rejectCwd = async (message, code) => {
518
- await forgetOnThrow();
519
- try {
520
- if (ownedEnv && hasDestroy(ownedEnv))
521
- await ownedEnv.destroy();
522
- }
523
- catch {
524
- }
522
+ await settleTeardownLeg(() => forgetOnThrow(), "forgetOnThrow (cwd-reject leg)", (err) => deps.onError?.(err, { phase: "config", sessionId }));
523
+ await settleTeardownLeg(() => (ownedEnv && hasDestroy(ownedEnv) ? ownedEnv.destroy() : undefined), "ownedEnv.destroy (cwd-reject leg)", (err) => deps.onError?.(err, { phase: "config", sessionId }));
525
524
  const e = new Error(message);
526
525
  e.code = code;
527
526
  throw e;
@@ -1403,6 +1402,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1403
1402
  ...(internals?.onTaskNotification !== undefined ? { onTaskNotification: internals.onTaskNotification } : {}),
1404
1403
  ...(handsCwdRef !== undefined ? { cwdRef: handsCwdRef } : {}),
1405
1404
  ...(offloadStore !== undefined ? { toolResultStore: offloadStore } : {}),
1405
+ ...(spec.retainBackgroundProcesses === true ? { retainBackgroundProcesses: true } : {}),
1406
1406
  })));
1407
1407
  }
1408
1408
  if (handsCwdRef !== undefined) {
@@ -1466,30 +1466,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
1466
1466
  const nudgeLspOnEdit = lspDiagnostics
1467
1467
  ? (rawPath) => {
1468
1468
  const baseDir = handsCwdRef?.current ?? taskRootPath;
1469
- const isAbsForm = rawPath.startsWith("/") || /^[A-Za-z]:[\\/]/.test(rawPath);
1470
- const joinSep = baseDir.includes("\\") ? "\\" : "/";
1471
- const normalizeSegments = (pth) => {
1472
- const isUnc = pth.startsWith("\\\\");
1473
- const drive = /^[A-Za-z]:/.exec(pth)?.[0] ?? "";
1474
- const rest = pth.slice(drive.length + (isUnc ? 2 : 0));
1475
- const sep = pth.includes("\\") ? "\\" : "/";
1476
- const abs = rest.startsWith("/") || rest.startsWith("\\");
1477
- const outSegs = [];
1478
- for (const seg of rest.split(/[\\/]+/)) {
1479
- if (!seg || seg === ".")
1480
- continue;
1481
- if (seg === "..") {
1482
- if (outSegs.length > 0 && outSegs[outSegs.length - 1] !== "..")
1483
- outSegs.pop();
1484
- else if (!abs)
1485
- outSegs.push("..");
1486
- continue;
1487
- }
1488
- outSegs.push(seg);
1489
- }
1490
- return (isUnc ? sep + sep : "") + drive + (abs ? sep : "") + outSegs.join(sep);
1491
- };
1492
- const filePath = normalizeSegments(isAbsForm ? rawPath : baseDir.replace(/[\\/]+$/, "") + joinSep + rawPath);
1469
+ const filePath = resolveLspPath(rawPath, baseDir);
1493
1470
  lspDiagnostics.fileEdited(pathToUri(filePath));
1494
1471
  void lspManager
1495
1472
  .sessionFor(filePath, undefined, executionEnv)
@@ -2041,9 +2018,9 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
2041
2018
  };
2042
2019
  }
2043
2020
  if (spec.agents !== undefined && spec.agents.length > 0) {
2044
- const known = new Set(tools.flatMap((t) => [canonicalToolName(t.name), ...(t.aliases ?? []).map((a) => canonicalToolName(a))]));
2021
+ const known = new Set(tools.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
2045
2022
  for (const def of spec.agents) {
2046
- const unknownAllow = (def.allowTools ?? []).filter((n) => n !== "*" && !known.has(canonicalToolName(n)));
2023
+ const unknownAllow = (def.allowTools ?? []).filter((n) => n !== "*" && !known.has(n));
2047
2024
  if (unknownAllow.length > 0) {
2048
2025
  try {
2049
2026
  deps.onError?.(new Error(`TaskSpec.agents: agent "${def.name}" allows tool(s) ${unknownAllow.join(", ")} not present in this task's assembled roster — likely a typo (the entry would be item-filtered at spawn; the agent stays usable). Advisory only: the delegation pool can differ from this roster, so a tool mounted only on the delegation tool or produced by per-spawn extraTools makes this spurious.`), { phase: "config", sessionId });
@@ -2054,7 +2031,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
2054
2031
  for (const n of def.denyTools ?? []) {
2055
2032
  if (n === "*")
2056
2033
  continue;
2057
- if (!known.has(canonicalToolName(n))) {
2034
+ if (!known.has(n)) {
2058
2035
  const e = new Error(`TaskSpec.agents: agent "${def.name}" declares tool "${n}" in its denied tools, but no such tool exists in this deployment — fix the agent's tools list or mount the tool.`);
2059
2036
  e.code = "config.agent.unknown_tool";
2060
2037
  throw e;
@@ -2216,15 +2193,22 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
2216
2193
  {
2217
2194
  const nameGroups = toolPolicyNameSets(policy);
2218
2195
  if (nameGroups.length > 0) {
2219
- const known = new Set(tools.flatMap((t) => [canonicalToolName(t.name), ...(t.aliases ?? []).map((a) => canonicalToolName(a))]));
2196
+ const known = new Set(tools.flatMap((t) => [t.name, ...(t.aliases ?? [])]));
2220
2197
  for (const t of harnessTools)
2221
- known.add(canonicalToolName(t.name));
2198
+ known.add(t.name);
2222
2199
  const unmatched = new Set();
2223
2200
  for (const g of nameGroups) {
2224
2201
  for (const [kind, list] of [["deny", g.deny], ["ask", g.ask], ["allow", g.allow]]) {
2225
2202
  for (const n of list ?? []) {
2226
- if (!known.has(canonicalToolName(n)))
2227
- unmatched.add(`"${n}" (${kind})`);
2203
+ if (known.has(n))
2204
+ continue;
2205
+ const retired = RETIRED_TOOL_NAMES.get(n);
2206
+ if (retired !== undefined) {
2207
+ const err = new Error(`tool policy ${kind}-list entry "${n}" is a RETIRED tool name (${retired}) and matches nothing in this run's roster — legacy-name normalization was removed (RB-476-A), so this entry would silently guard nothing. Update the deployment's rule to the current name.`);
2208
+ err.code = "config.legacy_tool_name";
2209
+ throw err;
2210
+ }
2211
+ unmatched.add(`"${n}" (${kind})`);
2228
2212
  }
2229
2213
  }
2230
2214
  }
@@ -3183,6 +3167,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
3183
3167
  let result;
3184
3168
  try {
3185
3169
  result = await runToolGate({
3170
+ onNotifyError: (f) => emitTrace(deps.tracer, () => ({ kind: "observer.notify_failed", version: 1, taskId: spec.taskId ?? sessionId, site: f.site, message: f.error.message, ts: Date.now() })),
3186
3171
  event: e,
3187
3172
  preToolUse: hooks?.preToolUse,
3188
3173
  adjudicate,
@@ -3296,11 +3281,7 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
3296
3281
  ...(offloadStore
3297
3282
  ? {
3298
3283
  offload: {
3299
- persist: (toolCallId, fullText) => {
3300
- const ref = buildToolResultRef(sessionId, toolCallId);
3301
- void offloadStore.put(ref, fullText);
3302
- return ref;
3303
- },
3284
+ persist: createOffloadPersist(offloadStore, sessionId),
3304
3285
  },
3305
3286
  }
3306
3287
  : {}),
@@ -3501,20 +3482,14 @@ export async function prepareTask(spec, deps, sessions, resume, internals, runne
3501
3482
  }
3502
3483
  catch (prepareErr) {
3503
3484
  if (mcp) {
3504
- try {
3505
- await mcp.dispose();
3506
- }
3507
- catch {
3508
- }
3485
+ const mcpHandle = mcp;
3486
+ await settleTeardownLeg(() => mcpHandle.dispose(), "mcp.dispose (prepare-throw leg)", (e) => deps.onError?.(e, { phase: "config", sessionId }));
3509
3487
  }
3510
3488
  if (ownedEnv && hasDestroy(ownedEnv)) {
3511
- try {
3512
- await ownedEnv.destroy();
3513
- }
3514
- catch {
3515
- }
3489
+ const env = ownedEnv;
3490
+ await settleTeardownLeg(() => env.destroy(), "ownedEnv.destroy (prepare-throw leg)", (e) => deps.onError?.(e, { phase: "config", sessionId }));
3516
3491
  }
3517
- await forgetOnThrow();
3492
+ await settleTeardownLeg(() => forgetOnThrow(), "forgetOnThrow (prepare-throw leg)", (e) => deps.onError?.(e, { phase: "config", sessionId }));
3518
3493
  throw prepareErr;
3519
3494
  }
3520
3495
  }
@@ -19,6 +19,7 @@ interface ResumeRun {
19
19
  trusted: boolean;
20
20
  };
21
21
  onEnvRestoreFailed?: (reason: ReopenReason) => Promise<void>;
22
+ decisionDelivered?: boolean;
22
23
  }
23
24
  export declare class Runner {
24
25
  private deps;