@sema-agent/server 7.137.0 → 7.139.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 (328) hide show
  1. package/MIGRATION.md +600 -142
  2. package/README.md +7 -3
  3. package/README.zh-CN.md +6 -3
  4. package/USAGE.md +132 -41
  5. package/deploy/sema-up/README.md +1 -1
  6. package/deploy/sema-up/lib/lanes.json +3 -2
  7. package/dist/adoption/wire.d.ts +3 -3
  8. package/dist/approval-card.d.ts +23 -16
  9. package/dist/approval-card.js +1 -0
  10. package/dist/audit.js +1 -0
  11. package/dist/background-agent-name.d.ts +5 -0
  12. package/dist/background-agent-name.js +5 -0
  13. package/dist/bench/s1/arms.d.ts +1 -1
  14. package/dist/bench/s1/arms.js +1 -3
  15. package/dist/bench/s1/run-firm.js +2 -2
  16. package/dist/boot/budget-tracing.d.ts +1 -12
  17. package/dist/boot/deployment-mods.d.ts +46 -16
  18. package/dist/boot/deployment-mods.js +82 -6
  19. package/dist/boot/device-lane.d.ts +8 -3
  20. package/dist/boot/device-lane.js +7 -2
  21. package/dist/boot/execution-env.d.ts +4 -2
  22. package/dist/boot/execution-env.js +16 -24
  23. package/dist/boot/execution-lane.d.ts +1 -1
  24. package/dist/boot/governance-seams.d.ts +12 -18
  25. package/dist/boot/governance-seams.js +10 -24
  26. package/dist/boot/leader.d.ts +3 -0
  27. package/dist/boot/leader.js +1 -0
  28. package/dist/boot/memory-consolidation.js +2 -2
  29. package/dist/boot/org-delivery.js +15 -2
  30. package/dist/boot/resolve-spec.d.ts +4 -1
  31. package/dist/boot/resolve-spec.js +29 -19
  32. package/dist/boot/retention-lane.d.ts +14 -8
  33. package/dist/boot/retention-lane.js +2 -8
  34. package/dist/boot/runner-deps.d.ts +10 -4
  35. package/dist/boot/runner-deps.js +2 -0
  36. package/dist/boot/session-faces.d.ts +0 -3
  37. package/dist/boot/session-faces.js +15 -8
  38. package/dist/boot/stage-02-web-admin-pull.js +2 -2
  39. package/dist/boot/stage-04-stores.d.ts +1 -12
  40. package/dist/boot/stage-05-execution-env.d.ts +3 -12
  41. package/dist/boot/stage-05-execution-env.js +8 -5
  42. package/dist/boot/stage-06-runners.d.ts +3 -12
  43. package/dist/boot/stage-06-runners.js +5 -3
  44. package/dist/boot/stage-07-capability-layer.d.ts +3 -12
  45. package/dist/boot/stage-07-capability-layer.js +2 -2
  46. package/dist/boot/stage-08-reapers.d.ts +3 -12
  47. package/dist/boot/stage-09-leader.d.ts +3 -12
  48. package/dist/boot/stage-09-leader.js +2 -3
  49. package/dist/boot/stage-10-http-server.d.ts +3 -12
  50. package/dist/boot/stage-10-http-server.js +5 -3
  51. package/dist/boot/stores.js +4 -4
  52. package/dist/boot/web-admin.d.ts +5 -2
  53. package/dist/boot/web-admin.js +5 -5
  54. package/dist/brain.js +5 -5
  55. package/dist/budget.d.ts +17 -15
  56. package/dist/budget.js +2 -2
  57. package/dist/capabilities/mcp-probe.d.ts +36 -11
  58. package/dist/capabilities/mcp-probe.js +44 -5
  59. package/dist/capabilities/scenarios.d.ts +1 -1
  60. package/dist/capability-facts.d.ts +21 -7
  61. package/dist/capability-facts.js +13 -3
  62. package/dist/checkpoint-identity.d.ts +13 -6
  63. package/dist/config-catalog.js +14 -8
  64. package/dist/config-invariants.d.ts +23 -3
  65. package/dist/config-invariants.js +42 -0
  66. package/dist/config-provider.d.ts +19 -24
  67. package/dist/config-provider.js +27 -12
  68. package/dist/config-types.d.ts +25 -12
  69. package/dist/config.d.ts +33 -0
  70. package/dist/config.js +52 -20
  71. package/dist/delegated-session-owner.d.ts +2 -2
  72. package/dist/deployment-shape.d.ts +7 -7
  73. package/dist/device-enrollment.d.ts +41 -2
  74. package/dist/device-enrollment.js +27 -12
  75. package/dist/device-store.d.ts +58 -85
  76. package/dist/device-store.js +19 -49
  77. package/dist/device-ws-hub.js +2 -1
  78. package/dist/env-name-allowlist-knobs.d.ts +5 -4
  79. package/dist/exec-cut.d.ts +60 -0
  80. package/dist/exec-cut.js +36 -0
  81. package/dist/execution-lane-caps.d.ts +19 -0
  82. package/dist/execution-lane-caps.js +10 -0
  83. package/dist/execution-placement.d.ts +259 -0
  84. package/dist/execution-placement.js +199 -0
  85. package/dist/field-conflict.d.ts +3 -2
  86. package/dist/field-conflict.js +1 -0
  87. package/dist/gate-settlement.d.ts +71 -0
  88. package/dist/gate-settlement.js +40 -0
  89. package/dist/hooks/classic-stations.d.ts +1 -0
  90. package/dist/hooks/classic-stations.js +1 -0
  91. package/dist/hooks/command-spawn.d.ts +2 -2
  92. package/dist/hooks/hook-runner.js +14 -14
  93. package/dist/hosted-posture.d.ts +2 -2
  94. package/dist/http/admission.js +10 -19
  95. package/dist/http/checkpoint-ctx.d.ts +21 -12
  96. package/dist/http/checkpoint-ctx.js +4 -2
  97. package/dist/http/claimed-run.d.ts +1 -1
  98. package/dist/http/dispatch.d.ts +4 -0
  99. package/dist/http/dispatch.js +3 -0
  100. package/dist/http/durable-run-leg.js +12 -6
  101. package/dist/http/execution-context.d.ts +218 -0
  102. package/dist/http/execution-context.js +330 -0
  103. package/dist/http/memory-compliance-failure-reply.js +3 -0
  104. package/dist/http/resume-legs.d.ts +5 -11
  105. package/dist/http/resume-legs.js +179 -104
  106. package/dist/http/route-ctx.d.ts +44 -59
  107. package/dist/http/route-ctx.js +2 -5
  108. package/dist/http/routes/a2a-serve.js +10 -4
  109. package/dist/http/routes/agents-roster.d.ts +1 -1
  110. package/dist/http/routes/agents-roster.js +5 -1
  111. package/dist/http/routes/approvals-assistant.js +6 -6
  112. package/dist/http/routes/background.d.ts +29 -1
  113. package/dist/http/routes/background.js +29 -2
  114. package/dist/http/routes/capabilities.js +12 -10
  115. package/dist/http/routes/devices.d.ts +13 -19
  116. package/dist/http/routes/devices.js +21 -26
  117. package/dist/http/routes/mcp-reconnect.d.ts +3 -2
  118. package/dist/http/routes/mcp-reconnect.js +7 -5
  119. package/dist/http/routes/memory-consolidation.d.ts +1 -1
  120. package/dist/http/routes/memory-origin.d.ts +1 -1
  121. package/dist/http/routes/rules.js +3 -3
  122. package/dist/http/routes/runs.js +11 -7
  123. package/dist/http/routes/session-sync.js +110 -15
  124. package/dist/http/routes/sessions.d.ts +6 -0
  125. package/dist/http/routes/sessions.js +119 -13
  126. package/dist/http/routes/side-query.d.ts +12 -4
  127. package/dist/http/routes/side-query.js +6 -8
  128. package/dist/http/routes/tasks.js +800 -782
  129. package/dist/http/server.d.ts +61 -39
  130. package/dist/http/server.js +11 -0
  131. package/dist/http/session-inherit-env.d.ts +3 -4
  132. package/dist/http/session-inherit-env.js +1 -1
  133. package/dist/http/wire-types.d.ts +22 -18
  134. package/dist/identity-source.d.ts +1 -1
  135. package/dist/index.d.ts +3 -0
  136. package/dist/index.js +1 -0
  137. package/dist/leader/wire.d.ts +7 -0
  138. package/dist/leader/wire.js +5 -4
  139. package/dist/mcp-assertion-header.d.ts +51 -40
  140. package/dist/mcp-assertion-header.js +10 -11
  141. package/dist/mcp-authorization-face.d.ts +27 -0
  142. package/dist/mcp-authorization-face.js +15 -0
  143. package/dist/memory-operator-faces.d.ts +13 -4
  144. package/dist/memory-operator-faces.js +1 -17
  145. package/dist/memory-sync-client.d.ts +53 -14
  146. package/dist/memory-sync-client.js +187 -92
  147. package/dist/memory-sync.d.ts +1 -1
  148. package/dist/memory-sync.js +3 -2
  149. package/dist/model-route-gap.d.ts +6 -22
  150. package/dist/model-route-gap.js +7 -5
  151. package/dist/mods-declaration.d.ts +110 -0
  152. package/dist/mods-declaration.js +109 -0
  153. package/dist/observability/cost-taxonomy.d.ts +2 -2
  154. package/dist/observability/err-text.d.ts +5 -0
  155. package/dist/observability/err-text.js +9 -0
  156. package/dist/observability/fail-open.d.ts +17 -1
  157. package/dist/observability/fail-open.js +17 -1
  158. package/dist/observability/run-terminal.js +0 -1
  159. package/dist/observability/secret-env-scrub.d.ts +1 -1
  160. package/dist/observability/secret-env-scrub.js +1 -1
  161. package/dist/orchestration/workflow-notify-journal.js +4 -4
  162. package/dist/org-memory-admission.d.ts +4 -3
  163. package/dist/org-memory-admission.js +6 -6
  164. package/dist/parked-decide.d.ts +49 -11
  165. package/dist/parked-decide.js +25 -26
  166. package/dist/parked-revive-surface.d.ts +12 -15
  167. package/dist/parked-revive-surface.js +3 -6
  168. package/dist/peer-seat.d.ts +156 -0
  169. package/dist/peer-seat.js +273 -0
  170. package/dist/permission-rule-vocab.d.ts +7 -7
  171. package/dist/permission-rule-vocab.js +3 -3
  172. package/dist/plain-string-record.d.ts +38 -0
  173. package/dist/plain-string-record.js +38 -0
  174. package/dist/plugins/approval-ask-store-file.d.ts +7 -0
  175. package/dist/plugins/approval-ask-store-file.js +11 -0
  176. package/dist/plugins/approval-ask-store-memory.d.ts +6 -0
  177. package/dist/plugins/approval-ask-store-memory.js +12 -0
  178. package/dist/plugins/approval-ask-store-sql.d.ts +22 -5
  179. package/dist/plugins/approval-ask-store-sql.js +30 -12
  180. package/dist/plugins/background-agent-store-sql.js +6 -3
  181. package/dist/plugins/caching-session-store.d.ts +11 -2
  182. package/dist/plugins/caching-session-store.js +15 -3
  183. package/dist/plugins/checkpoint-store-sql.d.ts +21 -25
  184. package/dist/plugins/checkpoint-store-sql.js +13 -15
  185. package/dist/plugins/device-store-sql.d.ts +25 -51
  186. package/dist/plugins/device-store-sql.js +49 -103
  187. package/dist/plugins/execution-placement-sql.d.ts +151 -0
  188. package/dist/plugins/execution-placement-sql.js +223 -0
  189. package/dist/plugins/file-history-store-sql.d.ts +7 -6
  190. package/dist/plugins/file-history-store-sql.js +8 -7
  191. package/dist/plugins/file-run-store.d.ts +6 -1
  192. package/dist/plugins/file-run-store.js +4 -0
  193. package/dist/plugins/fork-routing-session-store.d.ts +6 -0
  194. package/dist/plugins/fork-routing-session-store.js +16 -0
  195. package/dist/plugins/k8s-pod-reaper.d.ts +2 -8
  196. package/dist/plugins/k8s-pod-reaper.js +3 -3
  197. package/dist/plugins/local-checkpoint-store.d.ts +1 -11
  198. package/dist/plugins/local-checkpoint-store.js +0 -1
  199. package/dist/plugins/local-session-store.d.ts +183 -45
  200. package/dist/plugins/local-session-store.js +412 -105
  201. package/dist/plugins/mailbox-store-sql.d.ts +11 -3
  202. package/dist/plugins/mailbox-store-sql.js +103 -15
  203. package/dist/plugins/memory-key-guards.d.ts +4 -0
  204. package/dist/plugins/memory-key-guards.js +1 -0
  205. package/dist/plugins/memory-run-store.d.ts +1 -1
  206. package/dist/plugins/memory-sync-store-pg.d.ts +16 -5
  207. package/dist/plugins/memory-sync-store-tidb.d.ts +3 -3
  208. package/dist/plugins/one-time-migrations.d.ts +117 -6
  209. package/dist/plugins/one-time-migrations.js +383 -14
  210. package/dist/plugins/outcome-ledger-sql.d.ts +2 -2
  211. package/dist/plugins/permission-rule-store-sql.d.ts +13 -15
  212. package/dist/plugins/permission-rule-store-sql.js +34 -29
  213. package/dist/plugins/pg-pool.d.ts +7 -3
  214. package/dist/plugins/pg-session-storage.d.ts +41 -22
  215. package/dist/plugins/pg-session-storage.js +136 -55
  216. package/dist/plugins/remote-env-adb.d.ts +22 -4
  217. package/dist/plugins/remote-env-adb.js +70 -62
  218. package/dist/plugins/remote-env-device.d.ts +32 -12
  219. package/dist/plugins/remote-env-device.js +18 -17
  220. package/dist/plugins/remote-env-e2b.d.ts +19 -3
  221. package/dist/plugins/remote-env-e2b.js +41 -42
  222. package/dist/plugins/remote-env-file-error.d.ts +2 -0
  223. package/dist/plugins/remote-env-file-error.js +1 -1
  224. package/dist/plugins/remote-env-host.d.ts +23 -8
  225. package/dist/plugins/remote-env-host.js +66 -70
  226. package/dist/plugins/remote-env-k8s.d.ts +13 -16
  227. package/dist/plugins/remote-env-k8s.js +61 -54
  228. package/dist/plugins/remote-env-local-docker.d.ts +30 -5
  229. package/dist/plugins/remote-env-local-docker.js +46 -59
  230. package/dist/plugins/remote-env-ssh.d.ts +18 -4
  231. package/dist/plugins/remote-env-ssh.js +72 -56
  232. package/dist/plugins/remote-shell.d.ts +100 -3
  233. package/dist/plugins/remote-shell.js +166 -2
  234. package/dist/plugins/retention-store-sql.d.ts +23 -8
  235. package/dist/plugins/retention-store-sql.js +13 -1
  236. package/dist/plugins/run-store-sql.d.ts +13 -3
  237. package/dist/plugins/run-store-sql.js +5 -0
  238. package/dist/plugins/schema-consistency.d.ts +15 -5
  239. package/dist/plugins/schema-consistency.js +14 -8
  240. package/dist/plugins/schema-drift-sentence.d.ts +27 -0
  241. package/dist/plugins/schema-drift-sentence.js +38 -0
  242. package/dist/plugins/session-fork.d.ts +63 -12
  243. package/dist/plugins/session-fork.js +38 -21
  244. package/dist/plugins/session-ownership.d.ts +7 -0
  245. package/dist/plugins/session-ownership.js +5 -0
  246. package/dist/plugins/session-row-sql.d.ts +22 -0
  247. package/dist/plugins/session-row-sql.js +81 -0
  248. package/dist/plugins/session-store.d.ts +1 -1
  249. package/dist/plugins/session-workspace-cell.d.ts +17 -0
  250. package/dist/plugins/session-workspace-cell.js +38 -0
  251. package/dist/plugins/store-backend.d.ts +1 -1
  252. package/dist/plugins/store-backend.js +26 -14
  253. package/dist/plugins/store-contracts.d.ts +25 -5
  254. package/dist/plugins/tidb-pool.d.ts +12 -7
  255. package/dist/plugins/tidb-pool.js +15 -3
  256. package/dist/plugins/tidb-session-store.d.ts +74 -28
  257. package/dist/plugins/tidb-session-store.js +132 -53
  258. package/dist/plugins/tool-result-store-sql.d.ts +16 -8
  259. package/dist/plugins/tool-result-store-sql.js +26 -17
  260. package/dist/plugins/worktree-isolation.d.ts +3 -2
  261. package/dist/plugins/worktree-isolation.js +1 -7
  262. package/dist/project-identity.d.ts +1 -14
  263. package/dist/project-identity.js +0 -4
  264. package/dist/project-memory.d.ts +9 -15
  265. package/dist/project-memory.js +5 -4
  266. package/dist/request-key-closure.js +1 -1
  267. package/dist/request-value-closure.d.ts +6 -7
  268. package/dist/request-value-closure.js +1 -3
  269. package/dist/rules-consent.js +6 -4
  270. package/dist/run-local.d.ts +6 -0
  271. package/dist/run-local.js +36 -26
  272. package/dist/runs.d.ts +9 -2
  273. package/dist/runs.js +9 -2
  274. package/dist/sandbox-git-plane.d.ts +2 -2
  275. package/dist/security.d.ts +38 -12
  276. package/dist/security.js +8 -2
  277. package/dist/server-secret-env.d.ts +15 -8
  278. package/dist/server-secret-env.js +4 -2
  279. package/dist/session-children-retire.d.ts +27 -9
  280. package/dist/session-children-retire.js +9 -5
  281. package/dist/session-incarnation.d.ts +19 -10
  282. package/dist/session-incarnation.js +5 -3
  283. package/dist/session-row.d.ts +114 -5
  284. package/dist/session-row.js +55 -5
  285. package/dist/session-titler.d.ts +2 -2
  286. package/dist/session-workspace.d.ts +130 -0
  287. package/dist/session-workspace.js +83 -0
  288. package/dist/spec-fields.d.ts +1 -1
  289. package/dist/standing-answer-grant.d.ts +2 -13
  290. package/dist/standing-answer-grant.js +0 -7
  291. package/dist/task-a2a.d.ts +44 -14
  292. package/dist/task-a2a.js +46 -20
  293. package/dist/task-cwd.d.ts +6 -1
  294. package/dist/task-mcp.d.ts +33 -20
  295. package/dist/task-mcp.js +46 -22
  296. package/dist/tool-approval.d.ts +38 -8
  297. package/dist/tool-approval.js +57 -13
  298. package/dist/trace/core-keyset-guard.d.ts +33 -18
  299. package/dist/trace/engine-notice-wire.d.ts +1 -1
  300. package/dist/trace/engine-notice-wire.js +2 -0
  301. package/dist/trace/exit-seat.d.ts +20 -1
  302. package/dist/trace/exit-seat.js +3 -0
  303. package/dist/trace/extension-call-face.d.ts +33 -0
  304. package/dist/trace/extension-call-face.js +39 -0
  305. package/dist/trace/project.d.ts +26 -7
  306. package/dist/trace/project.js +30 -3
  307. package/dist/trace/redact.js +42 -13
  308. package/dist/trace/self-minted-wire.d.ts +240 -12
  309. package/dist/trace/self-minted-wire.js +100 -4
  310. package/dist/trace/wire-projection-faces.d.ts +6 -6
  311. package/dist/trace/wire-projection-faces.js +6 -5
  312. package/dist/url-refusal.d.ts +1 -1
  313. package/dist/user-authored-text.d.ts +2 -2
  314. package/dist/user-authored-text.js +16 -1
  315. package/dist/web-admin-client/apply-effective.d.ts +17 -3
  316. package/dist/web-admin-client/apply-effective.js +20 -10
  317. package/dist/web-admin-client/center-request.d.ts +3 -2
  318. package/dist/web-admin-client/center-request.js +2 -3
  319. package/dist/web-admin-client/skills-mcp.d.ts +8 -4
  320. package/dist/web-admin-client/skills-mcp.js +32 -18
  321. package/dist/web-admin-client/types.d.ts +11 -0
  322. package/package.json +3 -3
  323. package/wire-changes/server@7.138.0.json +446 -0
  324. package/wire-changes/server@7.139.0.json +348 -0
  325. package/dist/http/device-placement.d.ts +0 -175
  326. package/dist/http/device-placement.js +0 -145
  327. package/dist/http/mcp-remote-text.d.ts +0 -5
  328. package/dist/http/mcp-remote-text.js +0 -7
@@ -1,5 +1,6 @@
1
1
  import { redactErrorMessage, redactHead, redactTerminalResult } from "../../observability/run-terminal.js";
2
2
  import { runWithVerification, runCascade, taskNotificationDedupKey, uuidv7 } from "@sema-agent/core";
3
+ import { heldFor } from "../../peer-seat.js";
3
4
  import { graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, HEARTBEAT_MS } from "../../runs.js";
4
5
  import { sealResultForExit, outwardPlane } from "../../terminal.js";
5
6
  import { withPrincipal } from "../../observability/principal-context.js";
@@ -23,7 +24,8 @@ import { collectSsePreamble } from "../sse-log.js";
23
24
  import { buildApprovalPreamble, buildApprovalPreambleSseFrames } from "../../approval-card.js";
24
25
  import { approvalPreambleReplays, createApprovalCardEmitter, declaredApprovalFrameFamilies, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
25
26
  import { buildActiveRunConflict, isActiveRunConflictBody, toDoneFrameResult } from "../active-run-conflict.js";
26
- import { commitPlacement, devicePlacementErrorBody } from "../device-placement.js";
27
+ import { commitExecutionContext } from "../execution-context.js";
28
+ import { rootSessionAbsentAnswer } from "../execution-context.js";
27
29
  import { commitSessionInheritEnv } from "../session-inherit-env.js";
28
30
  import { headerStr, gatedPrincipal, explicitOperatorOk, runIdentityOf } from "../principal-gate.js";
29
31
  import { failOpenTagForDroppedFrame, recordFailOpen } from "../../observability/fail-open.js";
@@ -38,6 +40,7 @@ import { createInstructionSelectionLeg } from "../../instruction-selection.js";
38
40
  import { fieldConflictFacts } from "../../field-conflict.js";
39
41
  import { refusalBody } from "../refusal-body.js";
40
42
  import { heldWorkflowParkDecisions } from "../../parked-decide.js";
43
+ import { createSessionWorkspaceRecorder, legSessionWitnessOf, sessionWorkspaceStoreOf } from "../../session-workspace.js";
41
44
  const DISCONNECT_PARK_GRACE_MS = 10_000;
42
45
  function sseData(res, payload) {
43
46
  const anchor = payload.eventId;
@@ -151,666 +154,620 @@ export async function handleTasks(req, res, match, ctx) {
151
154
  const prepared = await prepareSpec(req, res, keyedBody, undefined, { liveStream });
152
155
  if (!prepared)
153
156
  return;
154
- const declaredFamilies = declaredApprovalFrameFamilies(prepared.body.settings);
155
- const approvalLegInput = (streamApprovalOn) => {
156
- const legWalltimeMs = typeof prepared.spec.limits?.maxWalltimeMs === "number" ? prepared.spec.limits.maxWalltimeMs : undefined;
157
- return {
158
- streamApprovalOn,
159
- windowMs: deps.config.streamApproval?.windowMs,
160
- windowMarginMs: deps.config.streamAskWindowMarginMs,
161
- ...(legWalltimeMs !== undefined ? { legWalltimeMs } : {}),
162
- declaredFamilies,
157
+ try {
158
+ const declaredFamilies = declaredApprovalFrameFamilies(prepared.body.settings);
159
+ const approvalLegInput = (streamApprovalOn) => {
160
+ const legWalltimeMs = typeof prepared.spec.limits?.maxWalltimeMs === "number" ? prepared.spec.limits.maxWalltimeMs : undefined;
161
+ return {
162
+ streamApprovalOn,
163
+ windowMs: deps.config.streamApproval?.windowMs,
164
+ windowMarginMs: deps.config.streamAskWindowMarginMs,
165
+ ...(legWalltimeMs !== undefined ? { legWalltimeMs } : {}),
166
+ declaredFamilies,
167
+ };
163
168
  };
164
- };
165
- const assembleApprovalLeg = (streamApprovalOn) => resolveApprovalLeg({ ...approvalLegInput(streamApprovalOn), nowMonotonicMs: performance.now() });
166
- const principal = prepared.auth?.principal;
167
- const wiringOperatorFace = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
168
- let wiringReceipt;
169
- const instructionLeg = createInstructionSelectionLeg();
170
- const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills: runSkillsOf(prepared.spec) });
171
- const withRunReceipt = (out) => wiringReceipt !== undefined ? { ...out, wiringManifest: wiringReceipt } : out;
172
- if (liveStream) {
173
- if (prepared.verify || prepared.cascade) {
174
- sendError(res, 400, "request.field_conflict", "verify / cascade are not supported on /v1/tasks/stream (both are multi-attempt, not a single stream) — use /v1/tasks or /v1/runs", fieldConflictFacts("cascade_verify", prepared.verify ? (prepared.cascade ? ["verify", "cascade"] : ["verify"]) : ["cascade"]));
175
- return;
176
- }
177
- const earlyDurableTid = facts.durableRuns(deps).available && prepared.spec.sessionId ? uuidv7() : undefined;
178
- const streamLegStartedAt = Date.now();
179
- const detachOnDisconnect = headerStr(req.headers["x-detach-on-disconnect"]) === "true";
180
- if (detachOnDisconnect && earlyDurableTid === undefined) {
181
- sendError(res, 400, "request.precondition_unmet", "x-detach-on-disconnect requires a durable run (a run store + sessionId) — without one the detached result would be unqueryable");
182
- return;
183
- }
184
- reqState.streamTaskId = earlyDurableTid;
185
- let usageKey;
186
- reqState.streamDetached = detachOnDisconnect;
187
- sseHeaders(res, earlyDurableTid ? { "x-task-id": earlyDurableTid } : undefined);
188
- if (earlyDurableTid)
189
- writeMetaFrame(res, earlyDurableTid, prepared.spec.sessionId, prepared.warnings);
190
- const ac = createRunAbort();
191
- let closed = false;
192
- let detachLogged = false;
193
- let disconnectParkGrace;
194
- const onDisconnect = () => {
195
- if (detachOnDisconnect) {
196
- if (res.writableEnded)
197
- return;
198
- if (!detachLogged) {
199
- detachLogged = true;
200
- res.on("error", () => undefined);
201
- deps.logger?.info("stream_client_detached", { taskId: earlyDurableTid, sessionId: prepared.spec.sessionId, detached: true });
202
- }
169
+ const assembleApprovalLeg = (streamApprovalOn) => resolveApprovalLeg({ ...approvalLegInput(streamApprovalOn), nowMonotonicMs: performance.now() });
170
+ const principal = prepared.auth?.principal;
171
+ const wiringOperatorFace = explicitOperatorOk(gatedPrincipal(req, deps.config), deps.config);
172
+ let wiringReceipt;
173
+ const instructionLeg = createInstructionSelectionLeg();
174
+ const legWiringSections = () => ({ instructions: instructionLeg.segment(), skills: runSkillsOf(prepared.spec) });
175
+ const withRunReceipt = (out) => wiringReceipt !== undefined ? { ...out, wiringManifest: wiringReceipt } : out;
176
+ if (liveStream) {
177
+ if (prepared.verify || prepared.cascade) {
178
+ sendError(res, 400, "request.field_conflict", "verify / cascade are not supported on /v1/tasks/stream (both are multi-attempt, not a single stream) — use /v1/tasks or /v1/runs", fieldConflictFacts("cascade_verify", prepared.verify ? (prepared.cascade ? ["verify", "cascade"] : ["verify"]) : ["cascade"]));
179
+ return;
180
+ }
181
+ const earlyDurableTid = facts.durableRuns(deps).available ? uuidv7() : undefined;
182
+ const streamLegStartedAt = Date.now();
183
+ const detachOnDisconnect = headerStr(req.headers["x-detach-on-disconnect"]) === "true";
184
+ if (detachOnDisconnect && earlyDurableTid === undefined) {
185
+ sendError(res, 400, "request.precondition_unmet", "x-detach-on-disconnect requires a durable run (a run store + sessionId) — without one the detached result would be unqueryable");
203
186
  return;
204
187
  }
205
- if (deps.checkpointStore && earlyDurableTid && disconnectParkGrace === undefined) {
206
- const parked = deps.toolApproval?.parkOpenAsksForTask(earlyDurableTid) ?? 0;
207
- if (parked > 0) {
208
- res.on("error", () => undefined);
209
- deps.logger?.info("stream_disconnect_ask_parked", { taskId: earlyDurableTid, sessionId: prepared.spec.sessionId, asks: parked, graceMs: DISCONNECT_PARK_GRACE_MS });
210
- disconnectParkGrace = setTimeout(() => {
211
- closed = true;
212
- ac.abort("ask_park_grace_exhausted");
213
- }, DISCONNECT_PARK_GRACE_MS);
214
- disconnectParkGrace.unref?.();
188
+ reqState.streamTaskId = earlyDurableTid;
189
+ let usageKey;
190
+ reqState.streamDetached = detachOnDisconnect;
191
+ sseHeaders(res, earlyDurableTid ? { "x-task-id": earlyDurableTid } : undefined);
192
+ if (earlyDurableTid)
193
+ writeMetaFrame(res, earlyDurableTid, prepared.spec.sessionId, prepared.warnings);
194
+ const ac = createRunAbort();
195
+ let closed = false;
196
+ let detachLogged = false;
197
+ let disconnectParkGrace;
198
+ const onDisconnect = () => {
199
+ if (detachOnDisconnect) {
200
+ if (res.writableEnded)
201
+ return;
202
+ if (!detachLogged) {
203
+ detachLogged = true;
204
+ res.on("error", () => undefined);
205
+ deps.logger?.info("stream_client_detached", { taskId: earlyDurableTid, sessionId: prepared.spec.sessionId, detached: true });
206
+ }
215
207
  return;
216
208
  }
217
- }
218
- closed = true;
219
- ac.abort("client_disconnected");
220
- };
221
- req.on("close", onDisconnect);
222
- res.on("close", () => {
223
- if (!res.writableEnded)
209
+ if (deps.checkpointStore && earlyDurableTid && disconnectParkGrace === undefined) {
210
+ const parked = deps.toolApproval?.parkOpenAsksForTask(earlyDurableTid) ?? 0;
211
+ if (parked > 0) {
212
+ res.on("error", () => undefined);
213
+ deps.logger?.info("stream_disconnect_ask_parked", { taskId: earlyDurableTid, sessionId: prepared.spec.sessionId, asks: parked, graceMs: DISCONNECT_PARK_GRACE_MS });
214
+ disconnectParkGrace = setTimeout(() => {
215
+ closed = true;
216
+ ac.abort("ask_park_grace_exhausted");
217
+ }, DISCONNECT_PARK_GRACE_MS);
218
+ disconnectParkGrace.unref?.();
219
+ return;
220
+ }
221
+ }
222
+ closed = true;
223
+ ac.abort("client_disconnected");
224
+ };
225
+ req.on("close", onDisconnect);
226
+ res.on("close", () => {
227
+ if (!res.writableEnded)
228
+ onDisconnect();
229
+ });
230
+ if ((res.destroyed || res.closed) && !res.writableEnded)
224
231
  onDisconnect();
225
- });
226
- if ((res.destroyed || res.closed) && !res.writableEnded)
227
- onDisconnect();
228
- const replayGate = resolveStreamApprovalGate({
229
- toolApprovalEnabled: Boolean(deps.toolApproval),
230
- streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
231
- backend: deps.backend,
232
- checkpointStore: deps.checkpointStore,
233
- });
234
- const replaySessionId = approvalPreambleReplays(approvalLegInput(replayGate.active)) ? prepared.spec.sessionId : undefined;
235
- const presentedOnConnection = new Set();
236
- const presentedCompleted = new Set();
237
- const admitPresentedComplete = (askId) => {
238
- if (!presentedOnConnection.has(askId))
232
+ const replayGate = resolveStreamApprovalGate({
233
+ toolApprovalEnabled: Boolean(deps.toolApproval),
234
+ streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
235
+ backend: deps.backend,
236
+ checkpointStore: deps.checkpointStore,
237
+ });
238
+ const replaySessionId = approvalPreambleReplays(approvalLegInput(replayGate.active)) ? prepared.spec.sessionId : undefined;
239
+ const presentedOnConnection = new Set();
240
+ const presentedCompleted = new Set();
241
+ const admitPresentedComplete = (askId) => {
242
+ if (!presentedOnConnection.has(askId))
243
+ return true;
244
+ if (presentedCompleted.has(askId))
245
+ return false;
246
+ presentedCompleted.add(askId);
239
247
  return true;
240
- if (presentedCompleted.has(askId))
241
- return false;
242
- presentedCompleted.add(askId);
243
- return true;
244
- };
245
- if (replaySessionId) {
246
- const replayOwner = gatedPrincipal(req, deps.config) ?? null;
247
- const askStore = replayGate.active ? replayGate.askStore : undefined;
248
- let presentedAskIds = [];
249
- const preambleFrames = await collectSsePreamble(async (signal) => {
250
- if (!askStore)
251
- return [];
252
- const rows = await askStore.listPendingBySession(replaySessionId, replayOwner, signal);
253
- const { frames, skipped, dropped } = buildApprovalPreamble(rows, Date.now(), deps.config.streamApproval.replayMax);
254
- presentedAskIds = frames.map((f) => f.askId);
255
- if (skipped > 0)
256
- deps.logger?.warn?.("approval_preamble_row_skipped", { sessionId: replaySessionId, skipped, face: "tasks.stream" });
257
- if (dropped > 0)
258
- deps.logger?.warn?.("approval_preamble_capped", { sessionId: replaySessionId, dropped, replayMax: deps.config.streamApproval.replayMax, face: "tasks.stream" });
259
- return buildApprovalPreambleSseFrames(frames);
260
- }, (reason, err) => deps.logger?.warn?.("approval_preamble_failed", { sessionId: replaySessionId, reason, face: "tasks.stream", error: err instanceof Error ? err.message : String(err ?? "") }));
261
- if (!res.writableEnded && !res.destroyed) {
262
- for (const f of preambleFrames)
263
- res.write(`event: ${f.event}\ndata: ${JSON.stringify(f.data)}\n\n`);
264
- if (deps.toolApproval && preambleFrames.length > 0) {
265
- for (const askId of presentedAskIds)
266
- presentedOnConnection.add(askId);
267
- const unwatch = deps.toolApproval.watchPresentedCards(presentedAskIds, (frame) => {
268
- if (res.writableEnded || res.destroyed || !admitPresentedComplete(frame.askId))
269
- return;
270
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
271
- });
272
- res.once("close", unwatch);
248
+ };
249
+ if (replaySessionId) {
250
+ const replayOwner = gatedPrincipal(req, deps.config) ?? null;
251
+ const askStore = replayGate.active ? replayGate.askStore : undefined;
252
+ let presentedAskIds = [];
253
+ const preambleFrames = await collectSsePreamble(async (signal) => {
254
+ if (!askStore)
255
+ return [];
256
+ const rows = await askStore.listPendingBySession(replaySessionId, replayOwner, signal);
257
+ const { frames, skipped, dropped } = buildApprovalPreamble(rows, Date.now(), deps.config.streamApproval.replayMax);
258
+ presentedAskIds = frames.map((f) => f.askId);
259
+ if (skipped > 0)
260
+ deps.logger?.warn?.("approval_preamble_row_skipped", { sessionId: replaySessionId, skipped, face: "tasks.stream" });
261
+ if (dropped > 0)
262
+ deps.logger?.warn?.("approval_preamble_capped", { sessionId: replaySessionId, dropped, replayMax: deps.config.streamApproval.replayMax, face: "tasks.stream" });
263
+ return buildApprovalPreambleSseFrames(frames);
264
+ }, (reason, err) => deps.logger?.warn?.("approval_preamble_failed", { sessionId: replaySessionId, reason, face: "tasks.stream", error: err instanceof Error ? err.message : String(err ?? "") }));
265
+ if (!res.writableEnded && !res.destroyed) {
266
+ for (const f of preambleFrames)
267
+ res.write(`event: ${f.event}\ndata: ${JSON.stringify(f.data)}\n\n`);
268
+ if (deps.toolApproval && preambleFrames.length > 0) {
269
+ for (const askId of presentedAskIds)
270
+ presentedOnConnection.add(askId);
271
+ const unwatch = deps.toolApproval.watchPresentedCards(presentedAskIds, (frame) => {
272
+ if (res.writableEnded || res.destroyed || !admitPresentedComplete(frame.askId))
273
+ return;
274
+ res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
275
+ });
276
+ res.once("close", unwatch);
277
+ }
273
278
  }
274
279
  }
275
- }
276
- const hb = setInterval(() => {
277
- if (!res.writableEnded && !res.destroyed)
278
- res.write(`event: heartbeat\ndata: {}\n\n`);
279
- }, 15_000);
280
- hb.unref?.();
281
- let ranLive = false;
282
- let resp;
283
- const runStreamSubmitLeg = async () => {
284
- ranLive = true;
285
- let finalResult;
286
- let runRowSettled = false;
287
- let durableTaskId;
288
- let durableHeartbeat;
289
- const cancelledResult = (errorMessage, cause) => mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId ?? "", startedAtMs: streamLegStartedAt, message: errorMessage, cause });
290
- let userMsgEntryId;
291
- const promptCommit = createPromptCommitReader();
292
- let anchorPut = false;
293
- const putRewindAnchor = () => {
294
- if (anchorPut || !userMsgEntryId || !durableTaskId || !prepared.spec.sessionId || !deps.resumeAnchorStore)
295
- return;
296
- anchorPut = true;
297
- void deps.resumeAnchorStore
298
- .put(prepared.spec.sessionId, durableTaskId, userMsgEntryId, principal ?? null)
299
- .catch(() => deps.metrics?.inc("resume_anchor_capture_failed"));
300
- };
301
- if (deps.runStore && prepared.spec.sessionId) {
302
- const tid = earlyDurableTid ?? uuidv7();
303
- const created = await deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null });
304
- if (created.ok)
305
- clearTurnActivity(tid);
306
- if (created.ok)
307
- recordResourceWindow(tid, prepared.spec.resourceSuspend);
308
- if (created.existing) {
309
- const replay = await replayOfExistingRun(created.existing, { principal: submitter, idem }, "sync", deps, deps.runStore);
310
- sseData(res, { type: "done", result: doneResultOfOutcome(replay), replay: true });
311
- return replay;
280
+ const hb = setInterval(() => {
281
+ if (!res.writableEnded && !res.destroyed)
282
+ res.write(`event: heartbeat\ndata: {}\n\n`);
283
+ }, 15_000);
284
+ hb.unref?.();
285
+ let ranLive = false;
286
+ let resp;
287
+ const runStreamSubmitLeg = async () => {
288
+ ranLive = true;
289
+ let finalResult;
290
+ let runRowSettled = false;
291
+ let durableTaskId;
292
+ let durableHeartbeat;
293
+ const cancelledResult = (errorMessage, cause) => mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId, startedAtMs: streamLegStartedAt, message: errorMessage, cause });
294
+ let userMsgEntryId;
295
+ const promptCommit = createPromptCommitReader();
296
+ let anchorPut = false;
297
+ const putRewindAnchor = () => {
298
+ if (anchorPut || !userMsgEntryId || !durableTaskId || !deps.resumeAnchorStore)
299
+ return;
300
+ anchorPut = true;
301
+ void deps.resumeAnchorStore
302
+ .put(prepared.spec.sessionId, durableTaskId, userMsgEntryId, principal ?? null)
303
+ .catch(() => deps.metrics?.inc("resume_anchor_capture_failed"));
304
+ };
305
+ if (deps.runStore) {
306
+ const tid = earlyDurableTid ?? uuidv7();
307
+ const created = await deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null });
308
+ if (created.ok)
309
+ clearTurnActivity(tid);
310
+ if (created.ok)
311
+ recordResourceWindow(tid, prepared.spec.resourceSuspend);
312
+ if (created.existing) {
313
+ const replay = await replayOfExistingRun(created.existing, { principal: submitter, idem }, "sync", deps, deps.runStore);
314
+ sseData(res, { type: "done", result: doneResultOfOutcome(replay), replay: true });
315
+ return replay;
316
+ }
317
+ if (created.sessionAbsent) {
318
+ const refused = rootSessionAbsentAnswer();
319
+ sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
320
+ return refused;
321
+ }
322
+ if (!created.ok) {
323
+ const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
324
+ const refused = { status: 409, body: conflict };
325
+ sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
326
+ return refused;
327
+ }
328
+ const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
329
+ if (placementReject) {
330
+ sseData(res, { type: "done", result: doneResultOfOutcome(placementReject) });
331
+ return placementReject;
332
+ }
333
+ durableTaskId = tid;
312
334
  }
313
- if (!created.ok) {
314
- const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
315
- const refused = { status: 409, body: conflict };
316
- sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
317
- return refused;
335
+ if (deps.checkpointStore) {
336
+ const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared.spec.sessionId, { body: prepared.body, memoryScope: prepared.auth?.memoryScope, writerVersion: serviceVersion() });
337
+ if (ctxRefusal) {
338
+ sseData(res, { type: "done", result: doneResultOfOutcome(ctxRefusal) });
339
+ return ctxRefusal;
340
+ }
318
341
  }
319
- const placementReject = await commitPlacement(deps, deps.runStore, tid, prepared.bindingIntent);
320
- if (placementReject) {
321
- const body = devicePlacementErrorBody(placementReject);
322
- const refused = { status: placementReject.status, body };
323
- sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
324
- return refused;
342
+ commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
343
+ markChildrenStoppedByUserOnAbort(ac.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.principal);
344
+ let ledgerSink;
345
+ let ledgerTerminal = false;
346
+ if (durableTaskId && deps.runStore) {
347
+ const rs = deps.runStore;
348
+ const tid = durableTaskId;
349
+ ledgerSink = createLedgerSink({ appendEvent: (seq, type, data) => rs.appendEvent(tid, seq, type, data), persistThinking: deps.config.traceThinking, onActivity: (kind, statusData) => recordTurnActivity(tid, kind, statusData), legSections: legWiringSections });
350
+ usageKey = tid;
351
+ deps.modelUsage?.register(tid);
352
+ const owner = principal ?? null;
353
+ const abortFromVerb = () => ac.abort("cancel_verb");
354
+ durableHeartbeat = setInterval(() => {
355
+ void rs.heartbeat(tid, owner).catch(() => undefined);
356
+ if (!ac.signal.aborted) {
357
+ void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c)
358
+ abortFromVerb(); }).catch(() => undefined);
359
+ }
360
+ }, HEARTBEAT_MS);
361
+ durableHeartbeat.unref?.();
362
+ inflightRuns.set(tid, ac);
363
+ void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c && !ac.signal.aborted)
364
+ abortFromVerb(); }).catch(() => undefined);
325
365
  }
326
- durableTaskId = tid;
327
- }
328
- if (deps.checkpointStore && prepared.spec.sessionId) {
329
- const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared.spec.sessionId, { body: prepared.body, memoryScope: prepared.auth?.memoryScope, writerVersion: serviceVersion() });
330
- if (ctxRefusal) {
331
- sseData(res, { type: "done", result: doneResultOfOutcome(ctxRefusal) });
332
- return ctxRefusal;
366
+ let fleetPub;
367
+ try {
368
+ fleetPub = durableTaskId
369
+ ? fleetRunPublisher(deps.fleetBus, { runId: durableTaskId, scope: gatedPrincipal(req, deps.config) ?? "default", rootTaskId: durableTaskId, sessionId: prepared.spec.sessionId, ...fleetRunLabels(prepared.spec.objective) })
370
+ : undefined;
333
371
  }
334
- }
335
- commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
336
- if (prepared.spec.sessionId)
337
- markChildrenStoppedByUserOnAbort(ac.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.principal);
338
- let ledgerSink;
339
- let ledgerTerminal = false;
340
- if (durableTaskId && deps.runStore) {
341
- const rs = deps.runStore;
342
- const tid = durableTaskId;
343
- ledgerSink = createLedgerSink({ appendEvent: (seq, type, data) => rs.appendEvent(tid, seq, type, data), persistThinking: deps.config.traceThinking, onActivity: (kind, statusData) => recordTurnActivity(tid, kind, statusData), legSections: legWiringSections });
344
- usageKey = tid;
345
- deps.modelUsage?.register(tid);
346
- const owner = principal ?? null;
347
- const abortFromVerb = () => ac.abort("cancel_verb");
348
- durableHeartbeat = setInterval(() => {
349
- void rs.heartbeat(tid, owner).catch(() => undefined);
350
- if (!ac.signal.aborted) {
351
- void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c)
352
- abortFromVerb(); }).catch(() => undefined);
353
- }
354
- }, HEARTBEAT_MS);
355
- durableHeartbeat.unref?.();
356
- inflightRuns.set(tid, ac);
357
- void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c && !ac.signal.aborted)
358
- abortFromVerb(); }).catch(() => undefined);
359
- }
360
- let fleetPub;
361
- try {
362
- fleetPub = durableTaskId
363
- ? fleetRunPublisher(deps.fleetBus, { runId: durableTaskId, scope: gatedPrincipal(req, deps.config) ?? "default", rootTaskId: durableTaskId, sessionId: prepared.spec.sessionId, ...fleetRunLabels(prepared.spec.objective) })
364
- : undefined;
365
- }
366
- catch (e) {
367
- if (durableHeartbeat)
368
- clearInterval(durableHeartbeat);
369
- if (durableTaskId && inflightRuns.get(durableTaskId) === ac)
370
- inflightRuns.delete(durableTaskId);
371
- throw e;
372
- }
373
- let fleetSettled = false;
374
- const settleFleet = (status, residuals) => {
375
- if (fleetSettled)
376
- return;
377
- fleetSettled = true;
378
- fleetPub?.onTerminal(status, residuals);
379
- };
380
- let liveStreamRef;
381
- const subagentHandleEvictions = [];
382
- let syncLegLive = true;
383
- const syncNotifiedKeys = new NotifiedKeys();
384
- try {
385
- fleetPub?.onStart();
386
- }
387
- catch (e) {
388
- if (durableHeartbeat)
389
- clearInterval(durableHeartbeat);
390
- if (durableTaskId && inflightRuns.get(durableTaskId) === ac)
391
- inflightRuns.delete(durableTaskId);
392
- settleFleet("failed");
393
- throw e;
394
- }
395
- const noticeLedger = ledgerSink;
396
- const unregisterEngineNotice = registerEngineNoticeLeg({
397
- sessionId: prepared.spec.sessionId,
398
- ...(prepared.engineNotices !== undefined ? { pending: prepared.engineNotices } : {}),
399
- live: (row) => {
400
- if (res.writableEnded || res.destroyed) {
401
- recordFailOpen(failOpenTagForDroppedFrame("engine_notice"), "frame=engine_notice");
372
+ catch (e) {
373
+ if (durableHeartbeat)
374
+ clearInterval(durableHeartbeat);
375
+ if (durableTaskId && inflightRuns.get(durableTaskId) === ac)
376
+ inflightRuns.delete(durableTaskId);
377
+ throw e;
378
+ }
379
+ let fleetSettled = false;
380
+ const settleFleet = (status, residuals) => {
381
+ if (fleetSettled)
402
382
  return;
403
- }
404
- sseData(res, { type: "engine_notice", ...row });
405
- },
406
- ...(noticeLedger
407
- ? {
408
- durable: (row) => noticeLedger.append("engine_notice", row).then(() => true, () => (recordFailOpen("server.engine-notice.durable-append-failed", `leg=sync code=${row.code} task=${durableTaskId ?? ""}`), false)),
409
- }
410
- : {}),
411
- });
412
- if (deps.userInputLedger && durableTaskId && prepared.spec.sessionId)
413
- await deps.userInputLedger.announceUndrained({ sessionId: prepared.spec.sessionId, taskId: durableTaskId });
414
- try {
415
- const streamBody = async () => {
416
- await withPrincipal(principal, async () => {
417
- const tailContentMode = prepared.spec.forwardSubagentEvents === true ? "on" : "progress_only";
418
- const childReasoning = createReasoningSegments();
419
- const topReasoning = createReasoningSegments();
420
- const heldDecisions = prepared.spec.sessionId !== undefined ? await heldWorkflowParkDecisions(deps, prepared.spec.sessionId) : {};
421
- const fwdInternals = {
422
- ...heldDecisions,
423
- onForwardEvent: (e) => {
424
- fleetPub?.onForwardEvent(e);
425
- ledgerSink?.onForwardEvent(e);
426
- {
427
- const bg = e.bgAgentId;
428
- if (bg !== undefined)
429
- defaultSubagentTailBus.onForwardFrame(bg, tailContentMode, e);
430
- }
431
- if (res.writableEnded)
432
- return;
433
- for (const end of childReasoning.onEvent(e))
383
+ fleetSettled = true;
384
+ fleetPub?.onTerminal(status, residuals);
385
+ };
386
+ let liveStreamRef;
387
+ const subagentHandleEvictions = [];
388
+ let syncLegLive = true;
389
+ const syncNotifiedKeys = new NotifiedKeys();
390
+ try {
391
+ fleetPub?.onStart();
392
+ }
393
+ catch (e) {
394
+ if (durableHeartbeat)
395
+ clearInterval(durableHeartbeat);
396
+ if (durableTaskId && inflightRuns.get(durableTaskId) === ac)
397
+ inflightRuns.delete(durableTaskId);
398
+ settleFleet("failed");
399
+ throw e;
400
+ }
401
+ const noticeLedger = ledgerSink;
402
+ const unregisterEngineNotice = registerEngineNoticeLeg({
403
+ sessionId: prepared.spec.sessionId,
404
+ ...(prepared.engineNotices !== undefined ? { pending: prepared.engineNotices } : {}),
405
+ live: (row) => {
406
+ if (res.writableEnded || res.destroyed) {
407
+ recordFailOpen(failOpenTagForDroppedFrame("engine_notice"), "frame=engine_notice");
408
+ return;
409
+ }
410
+ sseData(res, { type: "engine_notice", ...row });
411
+ },
412
+ ...(noticeLedger
413
+ ? {
414
+ durable: (row) => noticeLedger.append("engine_notice", row).then(() => true, () => (recordFailOpen("server.engine-notice.durable-append-failed", `leg=sync code=${row.code} task=${durableTaskId ?? ""}`), false)),
415
+ }
416
+ : {}),
417
+ });
418
+ if (deps.userInputLedger && durableTaskId)
419
+ await deps.userInputLedger.announceUndrained({ sessionId: prepared.spec.sessionId, taskId: durableTaskId });
420
+ try {
421
+ const streamBody = async () => {
422
+ await withPrincipal(principal, async () => {
423
+ const tailContentMode = prepared.spec.forwardSubagentEvents === true ? "on" : "progress_only";
424
+ const childReasoning = createReasoningSegments();
425
+ const topReasoning = createReasoningSegments();
426
+ const heldDecisions = await heldWorkflowParkDecisions(deps, prepared.spec.sessionId);
427
+ const fwdInternals = {
428
+ ...heldDecisions,
429
+ onForwardEvent: (e) => {
430
+ fleetPub?.onForwardEvent(e);
431
+ ledgerSink?.onForwardEvent(e);
432
+ {
433
+ const bg = e.bgAgentId;
434
+ if (bg !== undefined)
435
+ defaultSubagentTailBus.onForwardFrame(bg, tailContentMode, e);
436
+ }
437
+ if (res.writableEnded)
438
+ return;
439
+ for (const end of childReasoning.onEvent(e))
440
+ sseData(res, end);
441
+ const t = e.type;
442
+ if (t === "task_progress") {
443
+ sseData(res, { type: "task_progress", ...taskProgressEventData(e) });
444
+ }
445
+ else if (t === "task_started") {
446
+ sseData(res, { type: "task_started", ...taskStartedEventData(e) });
447
+ }
448
+ else if (t === "tool_start") {
449
+ const tsv = e;
450
+ sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
451
+ }
452
+ else if (t === "tool_end") {
453
+ const te = e;
454
+ sseData(res, { type: "tool_end", ...toolEndEventData(te) });
455
+ }
456
+ else if (t === "text_delta") {
457
+ const td = e;
458
+ sseData(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
459
+ }
460
+ else if (t === "text_end") {
461
+ const tend = textEndEventData(e);
462
+ if (tend !== null)
463
+ sseData(res, { type: "text_end", ...tend });
464
+ }
465
+ else if (t === "reasoning_delta") {
466
+ const rd = e;
467
+ sseData(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
468
+ }
469
+ },
470
+ onTaskNotification: (n, opts) => {
471
+ if (n.task_type === "workflow")
472
+ return;
473
+ if (!res.writableEnded)
474
+ for (const end of childReasoning.cut(reasoningStreamOfTask(n.task_id, n.sessionId)))
475
+ sseData(res, end);
476
+ defaultSubagentTailBus.forgetHandle(n.task_id);
477
+ if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
478
+ defaultSubagentTailBus.publish(n.task_id, { type: "task_settled", taskId: n.task_id, status: n.status, ...(typeof n.seq === "number" ? { seq: n.seq } : {}), ...(n.summary ? { summary: redactSecrets(n.summary) } : {}) });
479
+ }
480
+ const hadRow = isFleetAgentTerminalNotification(n) ? (fleetPub?.onChildTerminal(n.sessionId ?? n.task_id, n.status, n.task_id, n.toolUseId) ?? false) : false;
481
+ const deliverable = syncLegLive && !res.writableEnded && !res.destroyed;
482
+ const parked = !deliverable && deps.workflowCompletionInbox !== undefined;
483
+ deps.logger?.info?.("task_notification_observed", { route: "sync-stream", taskId: n.task_id, taskType: n.task_type, status: n.status, hadFleetRow: hadRow, legLive: syncLegLive, parkedDurable: parked });
484
+ if (parked) {
485
+ void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(prepared.spec.sessionId, askOwner, n, Date.now(), durableTaskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "sync-stream", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
486
+ }
487
+ else if (deliverable) {
488
+ const key = taskNotificationDedupKey(n);
489
+ if (syncNotifiedKeys.get(key) === undefined) {
490
+ syncNotifiedKeys.set(key, Promise.resolve(true));
491
+ sseData(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
492
+ }
493
+ }
494
+ },
495
+ ...(deps.subagentSteerRegistry && durableTaskId
496
+ ? {
497
+ onSubagentSpawn: (handle) => {
498
+ subagentHandleEvictions.push(deps.subagentSteerRegistry.register(durableTaskId, handle));
499
+ },
500
+ }
501
+ : {}),
502
+ };
503
+ const liveStream = prepared.runner.runTaskStream({ ...prepared.spec, signal: ac.signal, ...(durableTaskId ? { taskId: durableTaskId } : {}) }, undefined, fwdInternals);
504
+ liveStreamRef = liveStream;
505
+ void heldFor(prepared.peerLease, () => Promise.allSettled([Promise.resolve().then(() => liveStream.result())]));
506
+ if (durableTaskId)
507
+ steerableRuns.set(durableTaskId, liveStream);
508
+ prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => sseData(res, { ...frame }) });
509
+ const liveWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), legSessionWitnessOf(prepared.spec));
510
+ for await (const ev of liveStream) {
511
+ if (closed)
512
+ break;
513
+ for (const end of ev.type === "done" ? [...childReasoning.cut(), ...topReasoning.cut()] : topReasoning.onEvent(ev))
434
514
  sseData(res, end);
435
- const t = e.type;
436
- if (t === "task_progress") {
437
- sseData(res, { type: "task_progress", ...taskProgressEventData(e) });
515
+ const promptEntryId = promptCommit(ev);
516
+ if (promptEntryId !== undefined)
517
+ userMsgEntryId = promptEntryId;
518
+ const causeAtDone = ev.type === "done" ? ac.cause() : undefined;
519
+ await deps.userInputLedger?.observeLegEvent(liveStream, ev);
520
+ prepared.acceptance.observe(ev);
521
+ await liveWorkspace.observe(ev);
522
+ if (ev.type === "done") {
523
+ finalResult = await mintSubmitExitResult(ev.result, deps.checkpointStore);
524
+ if (durableTaskId && finalResult)
525
+ finalResult = { ...finalResult, taskId: durableTaskId };
526
+ if (causeAtDone !== undefined && finalResult !== undefined) {
527
+ finalResult = mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId, startedAtMs: streamLegStartedAt, message: "cancelled by user", cause: causeAtDone, engineResult: finalResult });
528
+ }
529
+ finalizeTaskResult(ev.result, principal, prepared.spec.objective);
530
+ noteRunOutcome(finalResult);
531
+ putRewindAnchor();
532
+ settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult));
533
+ if (ledgerSink && finalResult) {
534
+ if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
535
+ const rs2 = deps.runStore;
536
+ const tid2 = durableTaskId;
537
+ const fr = finalResult;
538
+ finalResult = await attachModelUsage(fr, { append: ledgerSink.append, getEvents: (_id, after) => rs2.getEvents(tid2, after), modelUsage: deps.modelUsage, taskId: usageKey }).catch(() => fr);
539
+ }
540
+ await ledgerSink.onDone(finalResult);
541
+ ledgerTerminal = true;
542
+ }
543
+ sseData(res, { ...ev, result: finalResult });
544
+ continue;
438
545
  }
439
- else if (t === "task_started") {
440
- sseData(res, { type: "task_started", ...taskStartedEventData(e) });
546
+ if (ledgerSink) {
547
+ await ledgerSink.onEvent(ev);
548
+ if (ev.type === "turn_end" && usageKey)
549
+ await appendModelUsageDelta(ledgerSink.append, deps.modelUsage, usageKey);
441
550
  }
442
- else if (t === "tool_start") {
443
- const tsv = e;
444
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
551
+ fleetPub?.onEvent(ev);
552
+ if (ev.type === "status")
553
+ deps.metrics?.inc("brain_retry_total", { phase: String(ev.phase) });
554
+ if (ev.type === "status") {
555
+ sseData(res, { type: "status", ...brainStatusEventData(ev) });
445
556
  }
446
- else if (t === "tool_end") {
447
- const te = e;
557
+ else if (ev.type === "tool_end") {
558
+ const te = ev;
448
559
  sseData(res, { type: "tool_end", ...toolEndEventData(te) });
449
560
  }
450
- else if (t === "text_delta") {
451
- const td = e;
452
- sseData(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
561
+ else if (ev.type === "tool_start") {
562
+ const tsv = ev;
563
+ sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
453
564
  }
454
- else if (t === "text_end") {
455
- const tend = textEndEventData(e);
456
- if (tend !== null)
457
- sseData(res, { type: "text_end", ...tend });
565
+ else if (ev.type === "task_notification") {
566
+ const tnv = ev.notification;
567
+ const tnvKey = taskNotificationStreamKeyOf(tnv);
568
+ const tnvPrior = tnvKey !== undefined ? syncNotifiedKeys.get(tnvKey) : undefined;
569
+ if (tnvPrior === undefined || !(await tnvPrior)) {
570
+ if (tnvKey !== undefined)
571
+ syncNotifiedKeys.set(tnvKey, Promise.resolve(true));
572
+ sseData(res, { type: "task_notification", ...taskNotificationEventData(ev) });
573
+ }
458
574
  }
459
- else if (t === "reasoning_delta") {
460
- const rd = e;
461
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
575
+ else if (ev.type === "reasoning_delta" && typeof ev.delta === "string") {
576
+ sseData(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
462
577
  }
463
- },
464
- onTaskNotification: (n, opts) => {
465
- if (n.task_type === "workflow")
466
- return;
467
- if (!res.writableEnded)
468
- for (const end of childReasoning.cut(reasoningStreamOfTask(n.task_id, n.sessionId)))
469
- sseData(res, end);
470
- defaultSubagentTailBus.forgetHandle(n.task_id);
471
- if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
472
- defaultSubagentTailBus.publish(n.task_id, { type: "task_settled", taskId: n.task_id, status: n.status, ...(typeof n.seq === "number" ? { seq: n.seq } : {}), ...(n.summary ? { summary: redactSecrets(n.summary) } : {}) });
578
+ else if (ev.type === "task_progress") {
579
+ sseData(res, { type: "task_progress", ...taskProgressEventData(ev) });
473
580
  }
474
- const hadRow = isFleetAgentTerminalNotification(n) ? (fleetPub?.onChildTerminal(n.sessionId ?? n.task_id, n.status, n.task_id, n.toolUseId) ?? false) : false;
475
- const deliverable = syncLegLive && !res.writableEnded && !res.destroyed;
476
- const parked = !deliverable && Boolean(deps.workflowCompletionInbox && prepared.spec.sessionId);
477
- deps.logger?.info?.("task_notification_observed", { route: "sync-stream", taskId: n.task_id, taskType: n.task_type, status: n.status, hadFleetRow: hadRow, legLive: syncLegLive, parkedDurable: parked });
478
- if (parked) {
479
- void deps.workflowCompletionInbox.enqueue(taskNotificationInboxEntry(prepared.spec.sessionId, askOwner, n, Date.now(), durableTaskId, opts?.priority)).catch((err) => deps.logger?.warn?.("park_enqueue_failed", { route: "sync-stream", taskId: n.task_id, err: err instanceof Error ? err.message : String(err) }));
581
+ else if (ev.type === "task_started") {
582
+ sseData(res, { type: "task_started", ...taskStartedEventData(ev) });
480
583
  }
481
- else if (deliverable) {
482
- const key = taskNotificationDedupKey(n);
483
- if (syncNotifiedKeys.get(key) === undefined) {
484
- syncNotifiedKeys.set(key, Promise.resolve(true));
485
- sseData(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
486
- }
584
+ else if (ev.type === "compacted") {
585
+ sseData(res, { type: "compacted", ...compactedEventData(ev) });
487
586
  }
488
- },
489
- ...(deps.subagentSteerRegistry && durableTaskId
490
- ? {
491
- onSubagentSpawn: (handle) => {
492
- subagentHandleEvictions.push(deps.subagentSteerRegistry.register(durableTaskId, handle));
493
- },
587
+ else if (ev.type === "diagnostics") {
588
+ sseData(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
494
589
  }
495
- : {}),
496
- };
497
- const liveStream = prepared.runner.runTaskStream({ ...prepared.spec, signal: ac.signal, ...(durableTaskId ? { taskId: durableTaskId } : {}) }, undefined, fwdInternals);
498
- liveStreamRef = liveStream;
499
- if (durableTaskId)
500
- steerableRuns.set(durableTaskId, liveStream);
501
- prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => sseData(res, { ...frame }) });
502
- for await (const ev of liveStream) {
503
- if (closed)
504
- break;
505
- for (const end of ev.type === "done" ? [...childReasoning.cut(), ...topReasoning.cut()] : topReasoning.onEvent(ev))
506
- sseData(res, end);
507
- const promptEntryId = promptCommit(ev);
508
- if (promptEntryId !== undefined)
509
- userMsgEntryId = promptEntryId;
510
- const causeAtDone = ev.type === "done" ? ac.cause() : undefined;
511
- await deps.userInputLedger?.observeLegEvent(liveStream, ev);
512
- prepared.acceptance.observe(ev);
513
- if (ev.type === "done") {
514
- finalResult = await mintSubmitExitResult(ev.result, deps.checkpointStore);
515
- if (durableTaskId && finalResult)
516
- finalResult = { ...finalResult, taskId: durableTaskId };
517
- if (causeAtDone !== undefined && finalResult !== undefined) {
518
- finalResult = mintCancelledResult({ taskId: durableTaskId ?? "", sessionId: prepared.spec.sessionId ?? "", startedAtMs: streamLegStartedAt, message: "cancelled by user", cause: causeAtDone, engineResult: finalResult });
590
+ else if (ev.type === "steering_injected") {
591
+ sseData(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
519
592
  }
520
- finalizeTaskResult(ev.result, principal, prepared.spec.objective);
521
- noteRunOutcome(finalResult);
522
- putRewindAnchor();
523
- settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult));
524
- if (ledgerSink && finalResult) {
525
- if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
526
- const rs2 = deps.runStore;
527
- const tid2 = durableTaskId;
528
- const fr = finalResult;
529
- finalResult = await attachModelUsage(fr, { append: ledgerSink.append, getEvents: (_id, after) => rs2.getEvents(tid2, after), modelUsage: deps.modelUsage, taskId: usageKey }).catch(() => fr);
530
- }
531
- await ledgerSink.onDone(finalResult);
532
- ledgerTerminal = true;
593
+ else if (ev.type === "workspace_changed") {
594
+ sseData(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
533
595
  }
534
- sseData(res, { ...ev, result: finalResult });
535
- continue;
536
- }
537
- if (ledgerSink) {
538
- await ledgerSink.onEvent(ev);
539
- if (ev.type === "turn_end" && usageKey)
540
- await appendModelUsageDelta(ledgerSink.append, deps.modelUsage, usageKey);
541
- }
542
- fleetPub?.onEvent(ev);
543
- if (ev.type === "status")
544
- deps.metrics?.inc("brain_retry_total", { phase: String(ev.phase) });
545
- if (ev.type === "status") {
546
- sseData(res, { type: "status", ...brainStatusEventData(ev) });
547
- }
548
- else if (ev.type === "tool_end") {
549
- const te = ev;
550
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
551
- }
552
- else if (ev.type === "tool_start") {
553
- const tsv = ev;
554
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
555
- }
556
- else if (ev.type === "task_notification") {
557
- const tnv = ev.notification;
558
- const tnvKey = taskNotificationStreamKeyOf(tnv);
559
- const tnvPrior = tnvKey !== undefined ? syncNotifiedKeys.get(tnvKey) : undefined;
560
- if (tnvPrior === undefined || !(await tnvPrior)) {
561
- if (tnvKey !== undefined)
562
- syncNotifiedKeys.set(tnvKey, Promise.resolve(true));
563
- sseData(res, { type: "task_notification", ...taskNotificationEventData(ev) });
596
+ else if (ev.type === "compaction_outcome") {
597
+ sseData(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
598
+ }
599
+ else if (ev.type === "compaction_started") {
600
+ sseData(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
601
+ }
602
+ else if (ev.type === "wiring_manifest") {
603
+ const wiringFace = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
604
+ wiringReceipt ??= wiringFace;
605
+ sseData(res, { type: "wiring_manifest", ...wiringFace });
606
+ }
607
+ else if (ev.type === "tool_roster_delta") {
608
+ const rosterDelta = toolRosterDeltaEventData(ev);
609
+ if (rosterDelta !== undefined)
610
+ sseData(res, { type: "tool_roster_delta", ...rosterDelta });
611
+ }
612
+ else if (ev.type === "tool_progress") {
613
+ const progress = toolProgressEventData(ev);
614
+ if (progress !== undefined)
615
+ sseData(res, { type: "tool_progress", ...progress });
616
+ }
617
+ else if (ev.type === "tool_disclosure") {
618
+ const disclosure = toolDisclosureEventData(ev);
619
+ if (disclosure !== undefined)
620
+ sseData(res, { type: "tool_disclosure", ...disclosure });
621
+ }
622
+ else if (ev.type === "human_input") {
623
+ sseData(res, { type: "human_input", ...humanInputEventData(ev) });
624
+ }
625
+ else if (ev.type === "text_delta" || ev.type === "text_end" || ev.type === "turn_end" || ev.type === "message_committed" || ev.type === "context_usage") {
626
+ const e = ev;
627
+ const ident = liveIdentityFields(e);
628
+ const textEnd = ev.type === "text_end" ? textEndEventData(e) : undefined;
629
+ const arm = ev.type === "text_delta"
630
+ ? { type: "text_delta", delta: e.delta, ...ident }
631
+ : ev.type === "text_end"
632
+ ?
633
+ textEnd === null || textEnd === undefined ? null : { type: "text_end", ...textEnd }
634
+ : ev.type === "turn_end"
635
+ ? { type: "turn_end", ...turnEndEventData(ev), ...ident }
636
+ : ev.type === "message_committed"
637
+ ? { type: "message_committed", entryId: e.entryId, role: e.role, ...(e.toolCallId !== undefined ? { toolCallId: e.toolCallId } : {}), ...ident }
638
+ : { type: "context_usage", ...contextUsageEventData(ev), ...ident };
639
+ if (arm !== null)
640
+ sseData(res, arm);
641
+ }
642
+ else {
643
+ sseData(res, { ...ev });
564
644
  }
565
645
  }
566
- else if (ev.type === "reasoning_delta" && typeof ev.delta === "string") {
567
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
568
- }
569
- else if (ev.type === "task_progress") {
570
- sseData(res, { type: "task_progress", ...taskProgressEventData(ev) });
571
- }
572
- else if (ev.type === "task_started") {
573
- sseData(res, { type: "task_started", ...taskStartedEventData(ev) });
574
- }
575
- else if (ev.type === "compacted") {
576
- sseData(res, { type: "compacted", ...compactedEventData(ev) });
577
- }
578
- else if (ev.type === "diagnostics") {
579
- sseData(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
580
- }
581
- else if (ev.type === "steering_injected") {
582
- sseData(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
583
- }
584
- else if (ev.type === "workspace_changed") {
585
- sseData(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
586
- }
587
- else if (ev.type === "compaction_outcome") {
588
- sseData(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
589
- }
590
- else if (ev.type === "compaction_started") {
591
- sseData(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
592
- }
593
- else if (ev.type === "wiring_manifest") {
594
- const wiringFace = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
595
- wiringReceipt ??= wiringFace;
596
- sseData(res, { type: "wiring_manifest", ...wiringFace });
597
- }
598
- else if (ev.type === "tool_roster_delta") {
599
- const rosterDelta = toolRosterDeltaEventData(ev);
600
- if (rosterDelta !== undefined)
601
- sseData(res, { type: "tool_roster_delta", ...rosterDelta });
602
- }
603
- else if (ev.type === "tool_progress") {
604
- const progress = toolProgressEventData(ev);
605
- if (progress !== undefined)
606
- sseData(res, { type: "tool_progress", ...progress });
607
- }
608
- else if (ev.type === "tool_disclosure") {
609
- const disclosure = toolDisclosureEventData(ev);
610
- if (disclosure !== undefined)
611
- sseData(res, { type: "tool_disclosure", ...disclosure });
612
- }
613
- else if (ev.type === "human_input") {
614
- sseData(res, { type: "human_input", ...humanInputEventData(ev) });
615
- }
616
- else if (ev.type === "text_delta" || ev.type === "text_end" || ev.type === "turn_end" || ev.type === "message_committed" || ev.type === "context_usage") {
617
- const e = ev;
618
- const ident = liveIdentityFields(e);
619
- const textEnd = ev.type === "text_end" ? textEndEventData(e) : undefined;
620
- const arm = ev.type === "text_delta"
621
- ? { type: "text_delta", delta: e.delta, ...ident }
622
- : ev.type === "text_end"
623
- ?
624
- textEnd === null || textEnd === undefined ? null : { type: "text_end", ...textEnd }
625
- : ev.type === "turn_end"
626
- ? { type: "turn_end", ...turnEndEventData(ev), ...ident }
627
- : ev.type === "message_committed"
628
- ? { type: "message_committed", entryId: e.entryId, role: e.role, ...(e.toolCallId !== undefined ? { toolCallId: e.toolCallId } : {}), ...ident }
629
- : { type: "context_usage", ...contextUsageEventData(ev), ...ident };
630
- if (arm !== null)
631
- sseData(res, arm);
632
- }
633
- else {
634
- sseData(res, { ...ev });
635
- }
636
- }
637
- });
638
- };
639
- const askTaskId = durableTaskId ?? uuidv7();
640
- const askOwner = gatedPrincipal(req, deps.config) ?? null;
641
- const emitAsk = (frame) => {
642
- if (res.writableEnded || res.destroyed) {
643
- recordFailOpen(failOpenTagForDroppedFrame(frame.type), `frame=${frame.type}`);
644
- return;
645
- }
646
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
647
- };
648
- const faceAlive = () => !res.writableEnded && !res.destroyed;
649
- const emitElicitation = createLedgerTwinEmit({ sink: ledgerSink, writeLive: emitAsk, liveReachable: faceAlive });
650
- const writeQuestionLive = (frame) => {
651
- if (!faceAlive())
652
- throw new Error("live stream ended — question frame undeliverable");
653
- emitAsk(frame);
654
- };
655
- const emitQuestion = createLedgerTwinEmit({ sink: ledgerSink, writeLive: writeQuestionLive, liveReachable: faceAlive });
656
- await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, prepared.spec.sessionId, askOwner, (frame) => {
657
- if (closed || res.writableEnded || res.destroyed)
658
- throw new Error("stream ended before the completion frame was written");
659
- const f = frame;
660
- const fKey = f.type === "task_notification" ? taskNotificationStreamKeyOf(f) : undefined;
661
- if (fKey !== undefined)
662
- syncNotifiedKeys.set(fKey, Promise.resolve(true));
663
- sseData(res, frame);
664
- }, { route: "sync-stream-open", connection: "live-sse", log: (m, x) => deps.logger?.info?.(m, x) });
665
- const withElicit = deps.elicitation
666
- ? () => deps.elicitation.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitElicitation, abortSignal: ac.signal }, streamBody)
667
- : streamBody;
668
- const withQuestion = () => deps.question
669
- ? deps.question.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitQuestion, abortSignal: ac.signal, deliverable: faceAlive }, withElicit)
670
- : withElicit();
671
- const emitApproval = (frame) => {
672
- if (res.writableEnded || res.destroyed)
673
- throw new Error("live stream ended — approval card undeliverable");
674
- emitAsk(frame);
675
- };
676
- const streamApprovalOn = resolveStreamApprovalGate({
677
- toolApprovalEnabled: Boolean(deps.toolApproval),
678
- streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
679
- backend: deps.backend,
680
- checkpointStore: deps.checkpointStore,
681
- }).active;
682
- const approvalLeg = assembleApprovalLeg(streamApprovalOn);
683
- const legDeadlineMonotonic = approvalLeg.legDeadlineMonotonic;
684
- const unattended = approvalLeg.unattended;
685
- const emitCard = createApprovalCardEmitter({
686
- ...(ledgerSink
687
- ? {
688
- appendDurable: async (frame) => {
689
- const { type, ...rest } = frame;
690
- await ledgerSink.append(type, rest);
691
- },
692
- }
693
- : {}),
694
- writeLive: (frame) => {
695
- if (res.writableEnded || res.destroyed)
696
- throw new Error("live stream ended");
697
- if (frame.type === "approval_complete" && !admitPresentedComplete(frame.askId))
646
+ });
647
+ };
648
+ const askTaskId = durableTaskId ?? uuidv7();
649
+ const askOwner = gatedPrincipal(req, deps.config) ?? null;
650
+ const emitAsk = (frame) => {
651
+ if (res.writableEnded || res.destroyed) {
652
+ recordFailOpen(failOpenTagForDroppedFrame(frame.type), `frame=${frame.type}`);
698
653
  return;
654
+ }
655
+ res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
656
+ };
657
+ const faceAlive = () => !res.writableEnded && !res.destroyed;
658
+ const emitElicitation = createLedgerTwinEmit({ sink: ledgerSink, writeLive: emitAsk, liveReachable: faceAlive });
659
+ const writeQuestionLive = (frame) => {
660
+ if (!faceAlive())
661
+ throw new Error("live stream ended — question frame undeliverable");
699
662
  emitAsk(frame);
700
- },
701
- });
702
- const emitRevokeLive = (frame) => {
703
- if (!res.writableEnded && !res.destroyed)
663
+ };
664
+ const emitQuestion = createLedgerTwinEmit({ sink: ledgerSink, writeLive: writeQuestionLive, liveReachable: faceAlive });
665
+ await emitPendingWorkflowCompletions(deps.workflowCompletionInbox, prepared.spec.sessionId, askOwner, (frame) => {
666
+ if (closed || res.writableEnded || res.destroyed)
667
+ throw new Error("stream ended before the completion frame was written");
668
+ const f = frame;
669
+ const fKey = f.type === "task_notification" ? taskNotificationStreamKeyOf(f) : undefined;
670
+ if (fKey !== undefined)
671
+ syncNotifiedKeys.set(fKey, Promise.resolve(true));
672
+ sseData(res, frame);
673
+ }, { route: "sync-stream-open", connection: "live-sse", log: (m, x) => deps.logger?.info?.(m, x) });
674
+ const withElicit = deps.elicitation
675
+ ? () => deps.elicitation.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitElicitation, abortSignal: ac.signal }, streamBody)
676
+ : streamBody;
677
+ const withQuestion = () => deps.question
678
+ ? deps.question.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitQuestion, abortSignal: ac.signal, deliverable: faceAlive }, withElicit)
679
+ : withElicit();
680
+ const emitApproval = (frame) => {
681
+ if (res.writableEnded || res.destroyed)
682
+ throw new Error("live stream ended — approval card undeliverable");
704
683
  emitAsk(frame);
705
- };
706
- const approvalCtx = deps.toolApproval && unattended === undefined
707
- ? {
708
- taskId: askTaskId,
709
- owner: askOwner,
710
- abortSignal: ac.signal,
711
- ...(prepared.spec.sessionId ? { sessionId: prepared.spec.sessionId } : {}),
712
- ...(streamApprovalOn
684
+ };
685
+ const streamApprovalOn = resolveStreamApprovalGate({
686
+ toolApprovalEnabled: Boolean(deps.toolApproval),
687
+ streamApprovalEnabled: deps.config.streamApproval?.enabled === true,
688
+ backend: deps.backend,
689
+ checkpointStore: deps.checkpointStore,
690
+ }).active;
691
+ const approvalLeg = assembleApprovalLeg(streamApprovalOn);
692
+ const legDeadlineMonotonic = approvalLeg.legDeadlineMonotonic;
693
+ const unattended = approvalLeg.unattended;
694
+ const emitCard = createApprovalCardEmitter({
695
+ ...(ledgerSink
713
696
  ? {
714
- emitCard,
715
- emitRevoke: emitRevokeLive,
716
- legKey: "",
717
- ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
718
- }
719
- : { emit: emitApproval }),
720
- }
721
- : undefined;
722
- if (deps.toolApproval) {
723
- const toolApproval = deps.toolApproval;
724
- prepared.spec.onAsk = unattended
725
- ? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, ...(prepared.spec.sessionId ? { sessionId: prepared.spec.sessionId } : {}) }, unattended)
726
- : toolApproval.boundAsk({
727
- owner: askOwner,
728
- taskId: askTaskId,
729
- ...(prepared.spec.sessionId ? { sessionId: prepared.spec.sessionId } : {}),
730
- ...(streamApprovalOn ? { legKey: "", ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
731
- });
732
- }
733
- const withApproval = () => approvalCtx && deps.toolApproval ? deps.toolApproval.runWithContext(approvalCtx, withQuestion) : withQuestion();
734
- await instructionLeg.run(prepared.spec.sessionId, () => withModelReachScope({ sessionId: prepared.spec.sessionId, taskId: durableTaskId }, () => deps.sendUserFile
735
- ? deps.sendUserFile.runWithContext({
736
- taskId: askTaskId,
737
- emit: async (f) => {
738
- void (await emitAsk(f));
739
- if (ledgerSink) {
740
- const { type, ...rest } = f;
741
- await ledgerSink.append(type, rest).catch(() => undefined);
697
+ appendDurable: async (frame) => {
698
+ const { type, ...rest } = frame;
699
+ await ledgerSink.append(type, rest);
700
+ },
742
701
  }
702
+ : {}),
703
+ writeLive: (frame) => {
704
+ if (res.writableEnded || res.destroyed)
705
+ throw new Error("live stream ended");
706
+ if (frame.type === "approval_complete" && !admitPresentedComplete(frame.askId))
707
+ return;
708
+ emitAsk(frame);
743
709
  },
744
- }, withApproval)
745
- : withApproval()));
746
- if (durableTaskId && deps.runStore) {
747
- const finalPlane = finalResult ? outwardPlane(finalResult.terminal) : undefined;
748
- if (finalResult && finalPlane?.status === "suspended" && deps.checkpointStore)
749
- await deps.runStore.setSuspended(durableTaskId, finalResult);
750
- else if (finalResult && finalPlane?.status === "needs_review" && deps.checkpointStore)
751
- await deps.runStore.setNeedsReview(durableTaskId, finalResult);
752
- else if (finalResult && finalPlane) {
753
- await deps.runStore.setTerminal(durableTaskId, finalPlane.status, finalResult, finalPlane.errorMessage ?? null);
754
- await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
755
- }
756
- else {
757
- putRewindAnchor();
758
- const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId);
759
- const dcCause = ac.cause();
760
- if (pending) {
761
- if (ledgerSink && !ledgerTerminal) {
762
- ledgerTerminal = true;
763
- await ledgerSink.flush().catch(() => undefined);
764
- await ledgerSink.appendParked("suspended", {}).catch(() => undefined);
765
- }
766
- await deps.runStore.setSuspended(durableTaskId, null);
767
- settleFleet("suspended");
710
+ });
711
+ const emitRevokeLive = (frame) => {
712
+ if (!res.writableEnded && !res.destroyed)
713
+ emitAsk(frame);
714
+ };
715
+ const approvalCtx = deps.toolApproval && unattended === undefined
716
+ ? {
717
+ taskId: askTaskId,
718
+ owner: askOwner,
719
+ abortSignal: ac.signal,
720
+ sessionId: prepared.spec.sessionId,
721
+ executionLane: prepared.execution.lane,
722
+ ...(streamApprovalOn
723
+ ? {
724
+ emitCard,
725
+ emitRevoke: emitRevokeLive,
726
+ legKey: "",
727
+ ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}),
728
+ }
729
+ : { emit: emitApproval }),
768
730
  }
769
- else if (dcCause !== undefined) {
770
- const dcErr = "stream client disconnected before completion (run aborted)";
771
- const dc = cancelledResult(dcErr, dcCause);
772
- if (ledgerSink && !ledgerTerminal) {
773
- ledgerTerminal = true;
774
- await ledgerSink.flush().catch(() => undefined);
775
- await ledgerSink.append("failed", buildCancelledLedgerRow(dc)).catch(() => undefined);
776
- }
777
- await deps.runStore.setTerminal(durableTaskId, "failed", dc, dcErr);
778
- noteRunOutcome(dc);
779
- settleFleet("failed");
731
+ : undefined;
732
+ if (deps.toolApproval) {
733
+ const toolApproval = deps.toolApproval;
734
+ prepared.spec.onAsk = unattended
735
+ ? toolApproval.boundUnattendedAsk({ owner: askOwner, taskId: askTaskId, sessionId: prepared.spec.sessionId, executionLane: prepared.execution.lane }, unattended)
736
+ : toolApproval.boundAsk({
737
+ owner: askOwner,
738
+ taskId: askTaskId,
739
+ sessionId: prepared.spec.sessionId,
740
+ executionLane: prepared.execution.lane,
741
+ ...(streamApprovalOn ? { legKey: "", ...(legDeadlineMonotonic !== undefined ? { legDeadlineMonotonic } : {}) } : {}),
742
+ });
743
+ }
744
+ const withApproval = () => approvalCtx && deps.toolApproval ? deps.toolApproval.runWithContext(approvalCtx, withQuestion) : withQuestion();
745
+ await instructionLeg.run(prepared.spec.sessionId, () => withModelReachScope({ sessionId: prepared.spec.sessionId, taskId: durableTaskId }, () => deps.sendUserFile
746
+ ? deps.sendUserFile.runWithContext({
747
+ taskId: askTaskId,
748
+ emit: async (f) => {
749
+ void (await emitAsk(f));
750
+ if (ledgerSink) {
751
+ const { type, ...rest } = f;
752
+ await ledgerSink.append(type, rest).catch(() => undefined);
753
+ }
754
+ },
755
+ }, withApproval)
756
+ : withApproval()));
757
+ if (durableTaskId && deps.runStore) {
758
+ const finalPlane = finalResult ? outwardPlane(finalResult.terminal) : undefined;
759
+ if (finalResult && finalPlane?.status === "suspended" && deps.checkpointStore)
760
+ await deps.runStore.setSuspended(durableTaskId, finalResult);
761
+ else if (finalResult && finalPlane?.status === "needs_review" && deps.checkpointStore)
762
+ await deps.runStore.setNeedsReview(durableTaskId, finalResult);
763
+ else if (finalResult && finalPlane) {
764
+ await deps.runStore.setTerminal(durableTaskId, finalPlane.status, finalResult, finalPlane.errorMessage ?? null);
765
+ await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
780
766
  }
781
767
  else {
782
- const err = "stream ended before a terminal event";
783
- if (ledgerSink && !ledgerTerminal) {
784
- ledgerTerminal = true;
785
- await ledgerSink.flush().catch(() => undefined);
786
- await ledgerSink.append("failed", { errorMessage: err }).catch(() => undefined);
787
- }
788
- await deps.runStore.setTerminal(durableTaskId, "failed", null, err);
789
- settleFleet("failed");
790
- }
791
- }
792
- runRowSettled = true;
793
- }
794
- }
795
- finally {
796
- syncLegLive = false;
797
- unregisterEngineNotice();
798
- if (durableHeartbeat)
799
- clearInterval(durableHeartbeat);
800
- if (durableTaskId && steerableRuns.get(durableTaskId) === liveStreamRef)
801
- steerableRuns.delete(durableTaskId);
802
- if (liveStreamRef !== undefined)
803
- await deps.userInputLedger?.settleLeg(liveStreamRef);
804
- if (durableTaskId && inflightRuns.get(durableTaskId) === ac)
805
- inflightRuns.delete(durableTaskId);
806
- for (const evict of subagentHandleEvictions)
807
- evict();
808
- if (!runRowSettled && durableTaskId && deps.runStore) {
809
- try {
810
- const row = await deps.runStore.getRun(durableTaskId);
811
- if (row?.status === "running") {
812
- const pending = prepared.spec.sessionId ? await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId) : undefined;
813
- const backstopCause = ac.cause();
768
+ putRewindAnchor();
769
+ const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId);
770
+ const dcCause = ac.cause();
814
771
  if (pending) {
815
772
  if (ledgerSink && !ledgerTerminal) {
816
773
  ledgerTerminal = true;
@@ -820,195 +777,256 @@ export async function handleTasks(req, res, match, ctx) {
820
777
  await deps.runStore.setSuspended(durableTaskId, null);
821
778
  settleFleet("suspended");
822
779
  }
823
- else if (finalResult) {
824
- if (ledgerSink && !ledgerTerminal) {
825
- ledgerTerminal = true;
826
- await ledgerSink.onDone(finalResult).catch(() => undefined);
827
- }
828
- const retryPlane = outwardPlane(finalResult.terminal);
829
- await deps.runStore.setTerminal(durableTaskId, retryPlane.status, finalResult, retryPlane.errorMessage ?? null);
830
- await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
831
- settleFleet(retryPlane.status, fleetRunResiduals(finalResult));
832
- }
833
- else if (backstopCause !== undefined) {
834
- const err = "stream aborted before completion (run cancelled)";
835
- const c = cancelledResult(err, backstopCause);
780
+ else if (dcCause !== undefined) {
781
+ const dcErr = "stream client disconnected before completion (run aborted)";
782
+ const dc = cancelledResult(dcErr, dcCause);
836
783
  if (ledgerSink && !ledgerTerminal) {
837
784
  ledgerTerminal = true;
838
785
  await ledgerSink.flush().catch(() => undefined);
839
- await ledgerSink.append("failed", buildCancelledLedgerRow(c)).catch(() => undefined);
786
+ await ledgerSink.append("failed", buildCancelledLedgerRow(dc)).catch(() => undefined);
840
787
  }
841
- await deps.runStore.setTerminal(durableTaskId, "failed", c, err);
788
+ await deps.runStore.setTerminal(durableTaskId, "failed", dc, dcErr);
789
+ noteRunOutcome(dc);
790
+ settleFleet("failed");
842
791
  }
843
792
  else {
844
- const err = "stream leg threw before a terminal event";
793
+ const err = "stream ended before a terminal event";
845
794
  if (ledgerSink && !ledgerTerminal) {
846
795
  ledgerTerminal = true;
847
796
  await ledgerSink.flush().catch(() => undefined);
848
797
  await ledgerSink.append("failed", { errorMessage: err }).catch(() => undefined);
849
798
  }
850
799
  await deps.runStore.setTerminal(durableTaskId, "failed", null, err);
800
+ settleFleet("failed");
851
801
  }
852
802
  }
853
- }
854
- catch {
803
+ runRowSettled = true;
855
804
  }
856
805
  }
857
- settleFleet("failed");
858
- }
859
- return { status: 200, body: finalResult };
860
- };
861
- counters.uncountedBillableInflight++;
862
- try {
863
- resp = await idemCache.run(inflightKey, async () => withRunReceipt(await runStreamSubmitLeg()));
864
- }
865
- catch (e) {
866
- deps.logger?.error("stream_error", { closed, err: redactHead(e instanceof Error ? e.message : String(e), 2000) });
867
- if (!closed)
868
- throw e;
869
- }
870
- finally {
871
- counters.uncountedBillableInflight--;
872
- clearInterval(hb);
873
- if (usageKey)
874
- deps.modelUsage?.clear(usageKey);
875
- }
876
- if (!ranLive && resp && !res.writableEnded) {
877
- sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
878
- }
879
- res.end();
880
- }
881
- else {
882
- const withSyncSubmitKeys = (body) => {
883
- const extra = {
884
- ...(prepared.verify || prepared.cascade ? { notice: MULTI_ATTEMPT_NO_EVENT_CHANNEL_NOTICE } : {}),
885
- ...(prepared.warnings !== undefined ? { warnings: prepared.warnings } : {}),
886
- };
887
- return Object.keys(extra).length > 0 ? { ...body, ...extra } : body;
888
- };
889
- const runSyncSubmitLeg = async () => {
890
- const syncLegStartedAt = Date.now();
891
- let durableTaskId;
892
- let durableHeartbeat;
893
- if (deps.runStore && prepared.spec.sessionId) {
894
- const tid = uuidv7();
895
- const created = await deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null });
896
- if (created.ok)
897
- clearTurnActivity(tid);
898
- if (created.ok)
899
- recordResourceWindow(tid, prepared.spec.resourceSuspend);
900
- if (created.existing)
901
- return await replayOfExistingRun(created.existing, { principal: submitter, idem }, "sync", deps, deps.runStore);
902
- if (!created.ok)
903
- return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId) };
904
- const placementReject = await commitPlacement(deps, deps.runStore, tid, prepared.bindingIntent);
905
- if (placementReject)
906
- return { status: placementReject.status, body: devicePlacementErrorBody(placementReject) };
907
- durableTaskId = tid;
908
- }
909
- if (deps.checkpointStore && prepared.spec.sessionId) {
910
- const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared.spec.sessionId, { body: prepared.body, memoryScope: prepared.auth?.memoryScope, writerVersion: serviceVersion() });
911
- if (ctxRefusal)
912
- return ctxRefusal;
913
- }
914
- commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
915
- const syncCancelCtrl = createRunAbort();
916
- if (prepared.spec.sessionId)
917
- markChildrenStoppedByUserOnAbort(syncCancelCtrl.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.principal);
918
- if (durableTaskId && deps.runStore) {
919
- const rs = deps.runStore;
920
- const tid = durableTaskId;
921
- const owner = principal ?? null;
922
- const abortFromVerb = () => syncCancelCtrl.abort("cancel_verb");
923
- durableHeartbeat = setInterval(() => {
924
- void rs.heartbeat(tid, owner).catch(() => undefined);
925
- if (!syncCancelCtrl.signal.aborted) {
926
- void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c)
927
- abortFromVerb(); }).catch(() => undefined);
806
+ finally {
807
+ syncLegLive = false;
808
+ unregisterEngineNotice();
809
+ if (durableHeartbeat)
810
+ clearInterval(durableHeartbeat);
811
+ if (durableTaskId && steerableRuns.get(durableTaskId) === liveStreamRef)
812
+ steerableRuns.delete(durableTaskId);
813
+ if (liveStreamRef !== undefined)
814
+ await deps.userInputLedger?.settleLeg(liveStreamRef);
815
+ if (durableTaskId && inflightRuns.get(durableTaskId) === ac)
816
+ inflightRuns.delete(durableTaskId);
817
+ for (const evict of subagentHandleEvictions)
818
+ evict();
819
+ if (!runRowSettled && durableTaskId && deps.runStore) {
820
+ try {
821
+ const row = await deps.runStore.getRun(durableTaskId);
822
+ if (row?.status === "running") {
823
+ const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId);
824
+ const backstopCause = ac.cause();
825
+ if (pending) {
826
+ if (ledgerSink && !ledgerTerminal) {
827
+ ledgerTerminal = true;
828
+ await ledgerSink.flush().catch(() => undefined);
829
+ await ledgerSink.appendParked("suspended", {}).catch(() => undefined);
830
+ }
831
+ await deps.runStore.setSuspended(durableTaskId, null);
832
+ settleFleet("suspended");
833
+ }
834
+ else if (finalResult) {
835
+ if (ledgerSink && !ledgerTerminal) {
836
+ ledgerTerminal = true;
837
+ await ledgerSink.onDone(finalResult).catch(() => undefined);
838
+ }
839
+ const retryPlane = outwardPlane(finalResult.terminal);
840
+ await deps.runStore.setTerminal(durableTaskId, retryPlane.status, finalResult, retryPlane.errorMessage ?? null);
841
+ await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
842
+ settleFleet(retryPlane.status, fleetRunResiduals(finalResult));
843
+ }
844
+ else if (backstopCause !== undefined) {
845
+ const err = "stream aborted before completion (run cancelled)";
846
+ const c = cancelledResult(err, backstopCause);
847
+ if (ledgerSink && !ledgerTerminal) {
848
+ ledgerTerminal = true;
849
+ await ledgerSink.flush().catch(() => undefined);
850
+ await ledgerSink.append("failed", buildCancelledLedgerRow(c)).catch(() => undefined);
851
+ }
852
+ await deps.runStore.setTerminal(durableTaskId, "failed", c, err);
853
+ }
854
+ else {
855
+ const err = "stream leg threw before a terminal event";
856
+ if (ledgerSink && !ledgerTerminal) {
857
+ ledgerTerminal = true;
858
+ await ledgerSink.flush().catch(() => undefined);
859
+ await ledgerSink.append("failed", { errorMessage: err }).catch(() => undefined);
860
+ }
861
+ await deps.runStore.setTerminal(durableTaskId, "failed", null, err);
862
+ }
863
+ }
864
+ }
865
+ catch {
866
+ }
928
867
  }
929
- }, HEARTBEAT_MS);
930
- durableHeartbeat.unref?.();
931
- inflightRuns.set(tid, syncCancelCtrl);
932
- void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c && !syncCancelCtrl.signal.aborted)
933
- abortFromVerb(); }).catch(() => undefined);
934
- }
935
- else if (durableTaskId) {
936
- inflightRuns.set(durableTaskId, syncCancelCtrl);
937
- }
938
- const specWithSignal = { ...prepared.spec, signal: syncCancelCtrl.signal, ...(durableTaskId ? { taskId: durableTaskId } : {}) };
939
- const observeSyncLegEvent = (ev) => {
940
- if (ev.type !== "wiring_manifest" || wiringReceipt !== undefined)
941
- return;
942
- wiringReceipt = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
868
+ settleFleet("failed");
869
+ }
870
+ return { status: 200, body: finalResult };
943
871
  };
944
- let result;
945
872
  counters.uncountedBillableInflight++;
946
873
  try {
947
- const heldDecisions = prepared.spec.sessionId !== undefined ? await heldWorkflowParkDecisions(deps, prepared.spec.sessionId) : {};
948
- const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, heldDecisions);
949
- const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), heldDecisions);
950
- const plainLeg = async () => {
951
- const stream = prepared.runner.runTaskStream(specWithSignal, undefined, heldDecisions);
952
- for await (const ev of stream) {
953
- observeSyncLegEvent(ev);
954
- prepared.acceptance.observe(ev);
955
- }
956
- return stream.result();
957
- };
958
- result = await instructionLeg.run(prepared.spec.sessionId, () => withPrincipal(principal, () => prepared.verify ? verifyLeg(prepared.verify) : prepared.cascade ? cascadeLeg() : plainLeg()));
874
+ resp = await idemCache.run(inflightKey, async () => withRunReceipt(await runStreamSubmitLeg()));
875
+ }
876
+ catch (e) {
877
+ deps.logger?.error("stream_error", { closed, err: redactHead(e instanceof Error ? e.message : String(e), 2000) });
878
+ if (!closed)
879
+ throw e;
959
880
  }
960
881
  finally {
961
882
  counters.uncountedBillableInflight--;
962
- if (durableHeartbeat)
963
- clearInterval(durableHeartbeat);
964
- if (durableTaskId && inflightRuns.get(durableTaskId) === syncCancelCtrl)
965
- inflightRuns.delete(durableTaskId);
883
+ clearInterval(hb);
884
+ if (usageKey)
885
+ deps.modelUsage?.clear(usageKey);
966
886
  }
967
- const syncAbortCause = syncCancelCtrl.cause();
968
- if (syncAbortCause !== undefined) {
969
- result = mintCancelledResult({
970
- taskId: durableTaskId ?? "",
971
- sessionId: prepared.spec.sessionId ?? "",
972
- startedAtMs: syncLegStartedAt,
973
- message: "cancelled by user",
974
- cause: syncAbortCause,
975
- engineResult: result,
976
- });
887
+ if (!ranLive && resp && !res.writableEnded) {
888
+ sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
977
889
  }
978
- const resumeAtStatus = syncRefusalHttpStatus(result);
979
- if (resumeAtStatus) {
980
- const resumeAtPlane = outwardPlane(result.terminal);
890
+ res.end();
891
+ }
892
+ else {
893
+ const withSyncSubmitKeys = (body) => {
894
+ const extra = {
895
+ ...(prepared.verify || prepared.cascade ? { notice: MULTI_ATTEMPT_NO_EVENT_CHANNEL_NOTICE } : {}),
896
+ ...(prepared.warnings !== undefined ? { warnings: prepared.warnings } : {}),
897
+ };
898
+ return Object.keys(extra).length > 0 ? { ...body, ...extra } : body;
899
+ };
900
+ const runSyncSubmitLeg = async () => {
901
+ const syncLegStartedAt = Date.now();
902
+ let durableTaskId;
903
+ let durableHeartbeat;
904
+ if (deps.runStore) {
905
+ const tid = uuidv7();
906
+ const created = await deps.runStore.createRun(tid, prepared.spec.sessionId, principal ?? null, deps.instanceId ?? "default", { ...runMeta(prepared, source), identity: runIdentityOf(req, deps.config, principal ?? null), idem: idem ?? null });
907
+ if (created.ok)
908
+ clearTurnActivity(tid);
909
+ if (created.ok)
910
+ recordResourceWindow(tid, prepared.spec.resourceSuspend);
911
+ if (created.existing)
912
+ return await replayOfExistingRun(created.existing, { principal: submitter, idem }, "sync", deps, deps.runStore);
913
+ if (created.sessionAbsent)
914
+ return rootSessionAbsentAnswer();
915
+ if (!created.ok)
916
+ return { status: 409, body: await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId) };
917
+ const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
918
+ if (placementReject)
919
+ return placementReject;
920
+ durableTaskId = tid;
921
+ }
922
+ if (deps.checkpointStore) {
923
+ const ctxRefusal = await persistSubmitCtx(deps.checkpointStore, deps, durableTaskId !== undefined && deps.runStore ? { runStore: deps.runStore, taskId: durableTaskId } : undefined, prepared.spec.sessionId, { body: prepared.body, memoryScope: prepared.auth?.memoryScope, writerVersion: serviceVersion() });
924
+ if (ctxRefusal)
925
+ return ctxRefusal;
926
+ }
927
+ commitSessionInheritEnv(deps, prepared.spec.sessionId, prepared.body);
928
+ const syncCancelCtrl = createRunAbort();
929
+ markChildrenStoppedByUserOnAbort(syncCancelCtrl.signal, durableTaskId ?? prepared.spec.sessionId, prepared.auth?.principal);
981
930
  if (durableTaskId && deps.runStore) {
982
- await deps.runStore.setTerminal(durableTaskId, "failed", sealResultForExit(result), resumeAtPlane.errorMessage ?? null);
983
- await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, result);
931
+ const rs = deps.runStore;
932
+ const tid = durableTaskId;
933
+ const owner = principal ?? null;
934
+ const abortFromVerb = () => syncCancelCtrl.abort("cancel_verb");
935
+ durableHeartbeat = setInterval(() => {
936
+ void rs.heartbeat(tid, owner).catch(() => undefined);
937
+ if (!syncCancelCtrl.signal.aborted) {
938
+ void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c)
939
+ abortFromVerb(); }).catch(() => undefined);
940
+ }
941
+ }, HEARTBEAT_MS);
942
+ durableHeartbeat.unref?.();
943
+ inflightRuns.set(tid, syncCancelCtrl);
944
+ void Promise.resolve(rs.isCancelRequested?.(tid, owner)).then((c) => { if (c && !syncCancelCtrl.signal.aborted)
945
+ abortFromVerb(); }).catch(() => undefined);
984
946
  }
985
- const retryAfterSec = resumeAtPlane.errorCode === "memory.admission_required" && result.retryAfterMs !== undefined
986
- ? Math.max(1, Math.ceil(result.retryAfterMs / 1000))
987
- : undefined;
988
- const refusalFacts = zeroWorkRefusalFacts(redactTerminalResult(sealResultForExit(result)).terminal, prepared.warnings);
989
- return { status: resumeAtStatus, body: refusalBody({ errorCode: httpErrorCode(resumeAtStatus, resumeAtPlane.errorCode), message: redactErrorMessage(resumeAtPlane.errorMessage) ?? "resume-at failed", facts: { ...(retryAfterSec !== undefined ? { retryAfterSec } : {}), ...refusalFacts } }) };
990
- }
991
- const exitResult = await mintSubmitExitResult(result, deps.checkpointStore);
992
- const syncPlane = outwardPlane(result.terminal);
993
- if (syncPlane.status === "suspended" && deps.checkpointStore && deps.runStore && durableTaskId && prepared.spec.sessionId) {
994
- await deps.runStore.setSuspended(durableTaskId, exitResult);
995
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "suspended" })) };
996
- }
997
- if (syncPlane.status === "needs_review" && deps.checkpointStore && deps.runStore && durableTaskId && prepared.spec.sessionId) {
998
- await deps.runStore.setNeedsReview(durableTaskId, exitResult);
999
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "needs_review" })) };
1000
- }
1001
- if (durableTaskId && deps.runStore)
1002
- await deps.runStore.setTerminal(durableTaskId, syncPlane.status, exitResult, syncPlane.errorMessage ?? null);
1003
- prepared.acceptance.settle(result);
1004
- finalizeTaskResult(result, principal, prepared.spec.objective);
1005
- noteRunOutcome(result);
1006
- return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult)) };
1007
- };
1008
- const resp = await idemCache.run(inflightKey, async () => withRunReceipt(await runSyncSubmitLeg()));
1009
- sendSubmitResult(res, resp);
947
+ else if (durableTaskId) {
948
+ inflightRuns.set(durableTaskId, syncCancelCtrl);
949
+ }
950
+ const specWithSignal = { ...prepared.spec, signal: syncCancelCtrl.signal, ...(durableTaskId ? { taskId: durableTaskId } : {}) };
951
+ const observeSyncLegEvent = (ev) => {
952
+ if (ev.type !== "wiring_manifest" || wiringReceipt !== undefined)
953
+ return;
954
+ wiringReceipt = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
955
+ };
956
+ let result;
957
+ counters.uncountedBillableInflight++;
958
+ try {
959
+ const heldDecisions = await heldWorkflowParkDecisions(deps, prepared.spec.sessionId);
960
+ const verifyLeg = (v) => runWithVerification(prepared.runner, specWithSignal, v, heldDecisions);
961
+ const cascadeLeg = () => runCascade(prepared.runner, specWithSignal, cascadeConfig(deps.config.cascadeLadder, prepared.spec.limits?.maxCostUsd), heldDecisions);
962
+ const plainLeg = async () => {
963
+ const stream = prepared.runner.runTaskStream(specWithSignal, undefined, heldDecisions);
964
+ const syncWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), legSessionWitnessOf(prepared.spec));
965
+ for await (const ev of stream) {
966
+ observeSyncLegEvent(ev);
967
+ prepared.acceptance.observe(ev);
968
+ await syncWorkspace.observe(ev);
969
+ }
970
+ return stream.result();
971
+ };
972
+ result = await instructionLeg.run(prepared.spec.sessionId, () => withPrincipal(principal, () => prepared.verify ? verifyLeg(prepared.verify) : prepared.cascade ? cascadeLeg() : plainLeg()));
973
+ }
974
+ finally {
975
+ counters.uncountedBillableInflight--;
976
+ if (durableHeartbeat)
977
+ clearInterval(durableHeartbeat);
978
+ if (durableTaskId && inflightRuns.get(durableTaskId) === syncCancelCtrl)
979
+ inflightRuns.delete(durableTaskId);
980
+ }
981
+ const syncAbortCause = syncCancelCtrl.cause();
982
+ if (syncAbortCause !== undefined) {
983
+ result = mintCancelledResult({
984
+ taskId: durableTaskId ?? "",
985
+ sessionId: prepared.spec.sessionId,
986
+ startedAtMs: syncLegStartedAt,
987
+ message: "cancelled by user",
988
+ cause: syncAbortCause,
989
+ engineResult: result,
990
+ });
991
+ }
992
+ const resumeAtStatus = syncRefusalHttpStatus(result);
993
+ if (resumeAtStatus) {
994
+ const resumeAtPlane = outwardPlane(result.terminal);
995
+ if (durableTaskId && deps.runStore) {
996
+ await deps.runStore.setTerminal(durableTaskId, "failed", sealResultForExit(result), resumeAtPlane.errorMessage ?? null);
997
+ await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, result);
998
+ }
999
+ const retryAfterSec = resumeAtPlane.errorCode === "memory.admission_required" && result.retryAfterMs !== undefined
1000
+ ? Math.max(1, Math.ceil(result.retryAfterMs / 1000))
1001
+ : undefined;
1002
+ const refusalFacts = zeroWorkRefusalFacts(redactTerminalResult(sealResultForExit(result)).terminal, prepared.warnings);
1003
+ return { status: resumeAtStatus, body: refusalBody({ errorCode: httpErrorCode(resumeAtStatus, resumeAtPlane.errorCode), message: redactErrorMessage(resumeAtPlane.errorMessage) ?? "resume-at failed", facts: { ...(retryAfterSec !== undefined ? { retryAfterSec } : {}), ...refusalFacts } }) };
1004
+ }
1005
+ const exitResult = await mintSubmitExitResult(result, deps.checkpointStore);
1006
+ const syncPlane = outwardPlane(result.terminal);
1007
+ if (syncPlane.status === "suspended" && deps.checkpointStore && deps.runStore && durableTaskId) {
1008
+ await deps.runStore.setSuspended(durableTaskId, exitResult);
1009
+ return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "suspended" })) };
1010
+ }
1011
+ if (syncPlane.status === "needs_review" && deps.checkpointStore && deps.runStore && durableTaskId) {
1012
+ await deps.runStore.setNeedsReview(durableTaskId, exitResult);
1013
+ return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "needs_review" })) };
1014
+ }
1015
+ if (durableTaskId && deps.runStore)
1016
+ await deps.runStore.setTerminal(durableTaskId, syncPlane.status, exitResult, syncPlane.errorMessage ?? null);
1017
+ prepared.acceptance.settle(result);
1018
+ finalizeTaskResult(result, principal, prepared.spec.objective);
1019
+ noteRunOutcome(result);
1020
+ return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult)) };
1021
+ };
1022
+ const resp = await idemCache.run(inflightKey, async () => withRunReceipt(await runSyncSubmitLeg()));
1023
+ sendSubmitResult(res, resp);
1024
+ }
1025
+ return;
1026
+ }
1027
+ finally {
1028
+ prepared.peerLease.release();
1010
1029
  }
1011
- return;
1012
1030
  }
1013
1031
  }
1014
1032
  export const TASKS_ROUTES = [