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