@sema-agent/server 7.139.0 → 7.141.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/MIGRATION.md +471 -0
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +94 -26
  5. package/dist/adoption/runner.js +1 -1
  6. package/dist/adoption/sql.js +1 -1
  7. package/dist/approval-batch-census.d.ts +27 -0
  8. package/dist/approval-batch-census.js +27 -0
  9. package/dist/approval-card.d.ts +37 -22
  10. package/dist/approval-card.js +6 -3
  11. package/dist/approval.d.ts +15 -0
  12. package/dist/approval.js +10 -0
  13. package/dist/audit.d.ts +4 -2
  14. package/dist/audit.js +2 -2
  15. package/dist/bench/s1/live-deps.js +3 -2
  16. package/dist/bench/s1/row.d.ts +5 -2
  17. package/dist/bench/s1/row.js +2 -22
  18. package/dist/boot/adoption.js +1 -1
  19. package/dist/boot/device-lane.d.ts +11 -0
  20. package/dist/boot/device-lane.js +16 -0
  21. package/dist/boot/engine-lease.d.ts +24 -3
  22. package/dist/boot/engine-lease.js +9 -2
  23. package/dist/boot/execution-env.js +18 -12
  24. package/dist/boot/execution-lane.d.ts +8 -0
  25. package/dist/boot/execution-lane.js +6 -1
  26. package/dist/boot/memory-boundary.d.ts +16 -53
  27. package/dist/boot/memory-boundary.js +10 -20
  28. package/dist/boot/memory-consolidation.d.ts +16 -12
  29. package/dist/boot/memory-consolidation.js +24 -13
  30. package/dist/boot/reapers.d.ts +2 -2
  31. package/dist/boot/resolve-spec.d.ts +3 -5
  32. package/dist/boot/resolve-spec.js +9 -8
  33. package/dist/boot/runner-deps.d.ts +3 -3
  34. package/dist/boot/runner-deps.js +1 -0
  35. package/dist/boot/session-faces.d.ts +1 -1
  36. package/dist/boot/session-faces.js +4 -3
  37. package/dist/boot/shutdown.js +5 -0
  38. package/dist/boot/stage-03-store-backend.d.ts +2 -6
  39. package/dist/boot/stage-03-store-backend.js +2 -3
  40. package/dist/boot/stage-04-stores.d.ts +2 -6
  41. package/dist/boot/stage-04-stores.js +5 -5
  42. package/dist/boot/stage-05-execution-env.d.ts +2 -6
  43. package/dist/boot/stage-05-execution-env.js +3 -1
  44. package/dist/boot/stage-06-runners.d.ts +2 -8
  45. package/dist/boot/stage-06-runners.js +3 -3
  46. package/dist/boot/stage-07-capability-layer.d.ts +2 -7
  47. package/dist/boot/stage-07-capability-layer.js +8 -10
  48. package/dist/boot/stage-08-reapers.d.ts +2 -7
  49. package/dist/boot/stage-09-leader.d.ts +2 -7
  50. package/dist/boot/stage-10-http-server.d.ts +2 -7
  51. package/dist/boot/stage-10-http-server.js +6 -4
  52. package/dist/boot/stores.d.ts +3 -6
  53. package/dist/boot/stores.js +37 -44
  54. package/dist/boot/task-list-lane.d.ts +1 -1
  55. package/dist/boot/task-list-lane.js +1 -1
  56. package/dist/boot/web-admin.js +36 -9
  57. package/dist/capabilities/execution-lane.d.ts +2 -2
  58. package/dist/capabilities/scenarios.d.ts +1 -1
  59. package/dist/capability-facts.d.ts +9 -0
  60. package/dist/capability-facts.js +9 -0
  61. package/dist/card-void.d.ts +38 -0
  62. package/dist/card-void.js +23 -0
  63. package/dist/config-catalog.js +12 -8
  64. package/dist/config-provider.d.ts +18 -17
  65. package/dist/config-provider.js +28 -36
  66. package/dist/config-types.d.ts +36 -9
  67. package/dist/config.js +56 -46
  68. package/dist/delegated-session-owner.d.ts +23 -20
  69. package/dist/delegated-session-owner.js +2 -2
  70. package/dist/deployment-shape.d.ts +9 -8
  71. package/dist/deployment-shape.js +4 -4
  72. package/dist/device-store.d.ts +7 -0
  73. package/dist/device-store.js +3 -0
  74. package/dist/execution-config-root.d.ts +22 -0
  75. package/dist/execution-config-root.js +35 -0
  76. package/dist/execution-lane-caps.d.ts +145 -107
  77. package/dist/execution-lane-caps.js +144 -83
  78. package/dist/execution-placement.d.ts +3 -0
  79. package/dist/execution-placement.js +7 -0
  80. package/dist/fleet/drain-entry.d.ts +3 -0
  81. package/dist/hosted-posture.d.ts +8 -0
  82. package/dist/hosted-posture.js +4 -0
  83. package/dist/http/admission.js +3 -3
  84. package/dist/http/caller-trust.d.ts +3 -2
  85. package/dist/http/caller-trust.js +2 -1
  86. package/dist/http/dispatch.js +4 -0
  87. package/dist/http/live-frame.d.ts +24 -0
  88. package/dist/http/live-frame.js +16 -0
  89. package/dist/http/memory-compliance-failure-reply.d.ts +3 -1
  90. package/dist/http/memory-compliance-failure-reply.js +5 -0
  91. package/dist/http/memory-layer-reply.d.ts +30 -0
  92. package/dist/http/memory-layer-reply.js +24 -0
  93. package/dist/http/resume-legs.js +49 -35
  94. package/dist/http/retired-service-deps.d.ts +1 -1
  95. package/dist/http/retired-service-deps.js +1 -1
  96. package/dist/http/route-table.js +2 -0
  97. package/dist/http/routes/adoption.js +1 -1
  98. package/dist/http/routes/approvals-assistant.js +1 -0
  99. package/dist/http/routes/capabilities.js +5 -4
  100. package/dist/http/routes/diagnostics.d.ts +0 -19
  101. package/dist/http/routes/diagnostics.js +16 -2
  102. package/dist/http/routes/memory-bundle.d.ts +2 -2
  103. package/dist/http/routes/memory-bundle.js +4 -1
  104. package/dist/http/routes/memory-compliance.js +9 -2
  105. package/dist/http/routes/memory-consolidation.js +12 -1
  106. package/dist/http/routes/memory-origin.js +14 -2
  107. package/dist/http/routes/memory-policy.js +7 -2
  108. package/dist/http/routes/run-permission-mode.d.ts +75 -0
  109. package/dist/http/routes/run-permission-mode.js +170 -0
  110. package/dist/http/routes/session-sync.d.ts +3 -6
  111. package/dist/http/routes/session-sync.js +7 -2
  112. package/dist/http/routes/sessions.js +33 -15
  113. package/dist/http/routes/tasks.js +67 -68
  114. package/dist/http/run-read-face.js +3 -3
  115. package/dist/http/send.d.ts +1 -1
  116. package/dist/http/send.js +2 -2
  117. package/dist/http/server.d.ts +14 -27
  118. package/dist/http/server.js +2 -2
  119. package/dist/http/sse-log.d.ts +3 -8
  120. package/dist/http/stored-body-replay.d.ts +3 -3
  121. package/dist/http/stored-body-replay.js +3 -1
  122. package/dist/identity-source.d.ts +1 -1
  123. package/dist/identity-source.js +1 -1
  124. package/dist/instruction-source-notice.d.ts +7 -0
  125. package/dist/instruction-source-notice.js +6 -6
  126. package/dist/lane-home-probe.d.ts +68 -42
  127. package/dist/lane-home-probe.js +53 -30
  128. package/dist/leader/wire.js +5 -4
  129. package/dist/mcp-assertion-header.d.ts +4 -0
  130. package/dist/mcp-assertion-header.js +5 -0
  131. package/dist/memory-bundle-engine.d.ts +16 -9
  132. package/dist/memory-bundle-engine.js +29 -6
  133. package/dist/memory-operator-faces.d.ts +85 -30
  134. package/dist/memory-operator-faces.js +136 -30
  135. package/dist/memory-posture.d.ts +1 -1
  136. package/dist/memory-project-layer.d.ts +3 -21
  137. package/dist/memory-project-layer.js +11 -8
  138. package/dist/memory-scope-stores.d.ts +73 -0
  139. package/dist/memory-scope-stores.js +86 -0
  140. package/dist/memory-scope.d.ts +33 -9
  141. package/dist/memory-scope.js +17 -5
  142. package/dist/memory-sync-client.d.ts +34 -9
  143. package/dist/memory-sync-client.js +108 -28
  144. package/dist/observability/fail-open.d.ts +30 -2
  145. package/dist/observability/fail-open.js +30 -2
  146. package/dist/observability/metrics.js +0 -1
  147. package/dist/observability/run-terminal.d.ts +6 -2
  148. package/dist/observability/run-terminal.js +25 -26
  149. package/dist/observability/secret-env-scrub.d.ts +20 -1
  150. package/dist/observability/secret-env-scrub.js +14 -0
  151. package/dist/orchestration/workflow-completion-inbox.d.ts +5 -2
  152. package/dist/orchestration/workflow-completion-inbox.js +13 -5
  153. package/dist/orchestration/workflow-notify-journal.d.ts +5 -3
  154. package/dist/orchestration/workflow-notify-journal.js +2 -1
  155. package/dist/permission-mode-admission.d.ts +68 -0
  156. package/dist/permission-mode-admission.js +23 -0
  157. package/dist/permission-rule-list.d.ts +55 -6
  158. package/dist/permission-rule-list.js +52 -5
  159. package/dist/plugins/adoption-log-sql.js +4 -4
  160. package/dist/plugins/approval-ask-store-sql.js +14 -14
  161. package/dist/plugins/approval-nonce-store.js +4 -4
  162. package/dist/plugins/blob-backend.d.ts +4 -4
  163. package/dist/plugins/blob-backend.js +7 -7
  164. package/dist/plugins/breaker-state-sql.js +2 -2
  165. package/dist/plugins/caching-session-store.d.ts +6 -0
  166. package/dist/plugins/caching-session-store.js +3 -0
  167. package/dist/plugins/checkpoint-index-columns.js +2 -2
  168. package/dist/plugins/checkpoint-store-sql.d.ts +65 -17
  169. package/dist/plugins/checkpoint-store-sql.js +90 -19
  170. package/dist/plugins/device-store-sql.d.ts +5 -2
  171. package/dist/plugins/device-store-sql.js +23 -20
  172. package/dist/plugins/ensure-index.d.ts +1 -2
  173. package/dist/plugins/execution-placement-sql.d.ts +19 -9
  174. package/dist/plugins/execution-placement-sql.js +20 -9
  175. package/dist/plugins/file-history-store-sql.d.ts +2 -2
  176. package/dist/plugins/file-history-store-sql.js +4 -4
  177. package/dist/plugins/file-run-store.d.ts +2 -2
  178. package/dist/plugins/file-run-store.js +1 -1
  179. package/dist/plugins/fork-routing-session-store.d.ts +10 -32
  180. package/dist/plugins/fork-routing-session-store.js +2 -61
  181. package/dist/plugins/image-bake-store-sql.js +9 -9
  182. package/dist/plugins/image-index-sql.js +11 -11
  183. package/dist/plugins/k8s-exec-protocol.d.ts +4 -1
  184. package/dist/plugins/k8s-exec-protocol.js +6 -1
  185. package/dist/plugins/leader-run-store-sql.js +4 -4
  186. package/dist/plugins/local-checkpoint-store.d.ts +10 -1
  187. package/dist/plugins/local-checkpoint-store.js +22 -0
  188. package/dist/plugins/local-session-store.d.ts +227 -35
  189. package/dist/plugins/local-session-store.js +518 -37
  190. package/dist/plugins/local-session-window.d.ts +17 -3
  191. package/dist/plugins/local-session-window.js +7 -13
  192. package/dist/plugins/mailbox-store-sql.d.ts +2 -1
  193. package/dist/plugins/mailbox-store-sql.js +4 -4
  194. package/dist/plugins/memory-engine-tidb.js +5 -5
  195. package/dist/plugins/memory-optout-grant-store-sql.js +1 -1
  196. package/dist/plugins/memory-run-store.d.ts +2 -2
  197. package/dist/plugins/memory-run-store.js +1 -1
  198. package/dist/plugins/memory-sync-store-tidb.js +3 -3
  199. package/dist/plugins/one-time-migrations.d.ts +52 -11
  200. package/dist/plugins/one-time-migrations.js +101 -39
  201. package/dist/plugins/org-delivery-quota-store.js +2 -2
  202. package/dist/plugins/outcome-ledger-sql.js +2 -2
  203. package/dist/plugins/permission-rule-store-sql.d.ts +4 -4
  204. package/dist/plugins/permission-rule-store-sql.js +16 -16
  205. package/dist/plugins/pg-pool.js +3 -2
  206. package/dist/plugins/pg-session-storage.d.ts +2 -0
  207. package/dist/plugins/pg-session-storage.js +3 -2
  208. package/dist/plugins/remote-env-adb.d.ts +7 -24
  209. package/dist/plugins/remote-env-adb.js +22 -5
  210. package/dist/plugins/remote-env-device.d.ts +2 -28
  211. package/dist/plugins/remote-env-device.js +2 -1
  212. package/dist/plugins/remote-env-e2b.d.ts +40 -27
  213. package/dist/plugins/remote-env-e2b.js +180 -20
  214. package/dist/plugins/remote-env-file-error.d.ts +1 -1
  215. package/dist/plugins/remote-env-file-error.js +8 -2
  216. package/dist/plugins/remote-env-host.d.ts +19 -35
  217. package/dist/plugins/remote-env-host.js +26 -3
  218. package/dist/plugins/remote-env-k8s.d.ts +22 -14
  219. package/dist/plugins/remote-env-k8s.js +150 -26
  220. package/dist/plugins/remote-env-local-docker.d.ts +27 -24
  221. package/dist/plugins/remote-env-local-docker.js +91 -24
  222. package/dist/plugins/remote-env-ssh.d.ts +4 -24
  223. package/dist/plugins/remote-env-ssh.js +4 -3
  224. package/dist/plugins/resume-anchor-store-sql.js +2 -2
  225. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  226. package/dist/plugins/retention-lane-store-sql.js +2 -2
  227. package/dist/plugins/retention-store-sql.d.ts +1 -1
  228. package/dist/plugins/retention-store-sql.js +6 -6
  229. package/dist/plugins/run-store-sql.d.ts +3 -3
  230. package/dist/plugins/run-store-sql.js +19 -18
  231. package/dist/plugins/sandbox-read-floor.d.ts +273 -0
  232. package/dist/plugins/sandbox-read-floor.js +608 -0
  233. package/dist/plugins/schema-consistency.d.ts +6 -6
  234. package/dist/plugins/schema-consistency.js +1 -1
  235. package/dist/plugins/schema-ensure-legs.d.ts +2 -3
  236. package/dist/plugins/schema-ensure-legs.js +2 -2
  237. package/dist/plugins/schema-live-columns.d.ts +1 -1
  238. package/dist/plugins/session-capture-record-store-sql.js +1 -1
  239. package/dist/plugins/session-ownership.d.ts +2 -1
  240. package/dist/plugins/session-placement.d.ts +17 -4
  241. package/dist/plugins/session-placement.js +2 -1
  242. package/dist/plugins/session-rules-column.d.ts +1 -1
  243. package/dist/plugins/session-rules-column.js +1 -1
  244. package/dist/plugins/session-store.d.ts +18 -20
  245. package/dist/plugins/session-store.js +4 -12
  246. package/dist/plugins/session-workspace-cell.d.ts +1 -1
  247. package/dist/plugins/session-workspace-cell.js +1 -1
  248. package/dist/plugins/shared-memory-store-sql.js +2 -2
  249. package/dist/plugins/sql-driver.d.ts +10 -5
  250. package/dist/plugins/sql-driver.js +6 -6
  251. package/dist/plugins/sql-errors.js +1 -1
  252. package/dist/plugins/store-backend.d.ts +35 -6
  253. package/dist/plugins/store-backend.js +27 -10
  254. package/dist/plugins/store-contracts.d.ts +9 -2
  255. package/dist/plugins/task-list-store-sql.js +11 -11
  256. package/dist/plugins/tidb-pool.js +7 -6
  257. package/dist/plugins/tidb-session-storage.js +4 -4
  258. package/dist/plugins/tidb-session-store.d.ts +4 -1
  259. package/dist/plugins/tidb-session-store.js +16 -15
  260. package/dist/plugins/tool-result-store-sql.d.ts +2 -2
  261. package/dist/plugins/tool-result-store-sql.js +3 -3
  262. package/dist/plugins/user-input-ledger-sql.js +2 -2
  263. package/dist/plugins/workflow-journal-store-sql.js +5 -5
  264. package/dist/plugins/workflow-run-store-sql.js +19 -19
  265. package/dist/plugins/write-behind-counter.d.ts +2 -3
  266. package/dist/plugins/write-behind-counter.js +5 -5
  267. package/dist/resource-suspend.d.ts +14 -12
  268. package/dist/resource-suspend.js +1 -1
  269. package/dist/resource-window.d.ts +4 -3
  270. package/dist/run-cancel-context.d.ts +34 -0
  271. package/dist/run-cancel-context.js +7 -0
  272. package/dist/run-local.js +14 -19
  273. package/dist/runs.d.ts +47 -16
  274. package/dist/runs.js +112 -113
  275. package/dist/security.d.ts +2 -2
  276. package/dist/server-secret-env.d.ts +2 -1
  277. package/dist/server-secret-env.js +2 -4
  278. package/dist/session-error-wire.d.ts +22 -4
  279. package/dist/session-error-wire.js +16 -0
  280. package/dist/session-incarnation.d.ts +10 -4
  281. package/dist/session-incarnation.js +1 -1
  282. package/dist/session-policy-wire.d.ts +1 -1
  283. package/dist/session-sync-kernel.d.ts +42 -1
  284. package/dist/session-sync-kernel.js +17 -0
  285. package/dist/session-sync.js +16 -4
  286. package/dist/sql-engine-coordinates.d.ts +49 -0
  287. package/dist/sql-engine-coordinates.js +27 -0
  288. package/dist/sql-engine-posture.d.ts +1 -1
  289. package/dist/sql-engine-posture.js +1 -1
  290. package/dist/standing-answer-grant.d.ts +31 -2
  291. package/dist/standing-answer-grant.js +14 -2
  292. package/dist/store-posture.d.ts +1 -1
  293. package/dist/{plugins → stores-sql}/background-agent-store-sql.d.ts +2 -2
  294. package/dist/{plugins → stores-sql}/background-agent-store-sql.js +8 -8
  295. package/dist/{plugins → stores-sql}/session-policy-store-sql.d.ts +7 -5
  296. package/dist/{plugins → stores-sql}/session-policy-store-sql.js +12 -12
  297. package/dist/{plugins → stores-sql}/usage-window-store-sql.d.ts +1 -1
  298. package/dist/{plugins → stores-sql}/usage-window-store-sql.js +3 -3
  299. package/dist/task-a2a.d.ts +1 -1
  300. package/dist/task-a2a.js +5 -6
  301. package/dist/task-mcp.d.ts +21 -8
  302. package/dist/task-mcp.js +17 -9
  303. package/dist/task-settings.d.ts +52 -25
  304. package/dist/task-settings.js +91 -28
  305. package/dist/terminal.d.ts +103 -19
  306. package/dist/terminal.js +72 -20
  307. package/dist/trace/core-keyset-guard.d.ts +79 -2
  308. package/dist/trace/exit-seat.d.ts +7 -0
  309. package/dist/trace/exit-seat.js +1 -0
  310. package/dist/trace/model-segment.d.ts +2 -2
  311. package/dist/trace/redact.d.ts +3 -1
  312. package/dist/trace/redact.js +395 -110
  313. package/dist/trace/self-minted-wire.d.ts +226 -2
  314. package/dist/trace/self-minted-wire.js +79 -0
  315. package/dist/verifier-pause-card.d.ts +8 -0
  316. package/dist/verifier-pause-card.js +19 -0
  317. package/dist/web-admin-client/apply-effective.d.ts +5 -7
  318. package/dist/web-admin-client/apply-effective.js +2 -2
  319. package/dist/web-admin-client/candidate-gate.d.ts +11 -7
  320. package/dist/web-admin-client/candidate-gate.js +1 -1
  321. package/dist/web-admin-client/http-client.d.ts +5 -4
  322. package/dist/web-admin-client/http-client.js +2 -2
  323. package/dist/web-admin-client/read-warnings.d.ts +7 -17
  324. package/dist/web-admin-client/read-warnings.js +5 -9
  325. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +3 -2
  326. package/package.json +2 -2
  327. package/wire-changes/server@7.140.0.json +184 -0
  328. package/wire-changes/server@7.141.0.json +367 -0
@@ -1,8 +1,9 @@
1
1
  import { redactErrorMessage, redactHead, redactTerminalResult } from "../../observability/run-terminal.js";
2
2
  import { runWithVerification, runCascade, taskNotificationDedupKey, uuidv7 } from "@sema-agent/core";
3
3
  import { heldFor } from "../../peer-seat.js";
4
- import { graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, HEARTBEAT_MS } from "../../runs.js";
5
- import { sealResultForExit, outwardPlane } from "../../terminal.js";
4
+ import { graftParkToolCallId, markChildrenStoppedByUserOnAbort, syncRefusalHttpStatus, zeroWorkRefusalFacts, releaseKeyIfZeroWorkRefusal, createPromptCommitReader, settleResumeAnchor, HEARTBEAT_MS } from "../../runs.js";
5
+ import { atHostBoundary, sealResultForExit, outwardPlane } from "../../terminal.js";
6
+ import { voidVerifierPauseCard } from "../../verifier-pause-card.js";
6
7
  import { withPrincipal } from "../../observability/principal-context.js";
7
8
  import { fleetRunPublisher, fleetRunLabels, fleetRunResiduals, isFleetAgentTerminalNotification } from "../../fleet/fleet-bus.js";
8
9
  import { defaultSubagentTailBus } from "../../fleet/subagent-tail-bus.js";
@@ -14,14 +15,14 @@ import { clearTurnActivity, readTurnActivityMs, recordTurnActivity } from "../..
14
15
  import { buildCancelledLedgerRow, createRunAbort, mintCancelledResult } from "../../run-cancel-context.js";
15
16
  import { recordResourceWindow } from "../../resource-window.js";
16
17
  import { redactSecrets } from "../../trace/redact.js";
17
- import { liveToolEndForBacklog } from "../../trace/tool-output-media.js";
18
+ import { writeLiveFrame, writeLiveHeartbeat } from "../live-frame.js";
18
19
  import { contextUsageEventData, turnEndEventData, toolStartEventData, toolEndEventData, taskProgressEventData, taskStartedEventData, taskNotificationEventData, compactedEventData, diagnosticsEventData, brainStatusEventData, steeringInjectedEventData, compactionOutcomeEventData, compactionStartedEventData, workspaceChangedEventData, wiringManifestFaceEventData, toolRosterDeltaEventData, toolProgressEventData, toolDisclosureEventData, humanInputEventData, appendModelUsageDelta, attachModelUsage, textEndEventData, liveIdentityFields } from "../../trace/project.js";
19
20
  import { cascadeConfig, runMeta } from "../run-meta.js";
20
21
  import { idemCallerOf, inflightKeyOf, submissionIdemOf } from "../idempotency.js";
21
22
  import { replayOfExistingRun } from "../submit-replay.js";
22
23
  import { httpErrorCode, sendJson, sendError, sseHeaders } from "../send.js";
23
24
  import { collectSsePreamble } from "../sse-log.js";
24
- import { buildApprovalPreamble, buildApprovalPreambleSseFrames } from "../../approval-card.js";
25
+ import { buildApprovalPreamble } from "../../approval-card.js";
25
26
  import { approvalPreambleReplays, createApprovalCardEmitter, declaredApprovalFrameFamilies, resolveApprovalLeg, resolveStreamApprovalGate } from "../../tool-approval.js";
26
27
  import { buildActiveRunConflict, isActiveRunConflictBody, toDoneFrameResult } from "../active-run-conflict.js";
27
28
  import { commitExecutionContext } from "../execution-context.js";
@@ -42,12 +43,6 @@ import { refusalBody } from "../refusal-body.js";
42
43
  import { heldWorkflowParkDecisions } from "../../parked-decide.js";
43
44
  import { createSessionWorkspaceRecorder, legSessionWitnessOf, sessionWorkspaceStoreOf } from "../../session-workspace.js";
44
45
  const DISCONNECT_PARK_GRACE_MS = 10_000;
45
- function sseData(res, payload) {
46
- const anchor = payload.eventId;
47
- const idLine = typeof anchor === "string" && anchor.length > 0 ? `id: ${anchor}\n` : "";
48
- const frame = payload.type === "tool_end" ? liveToolEndForBacklog(payload, res.writableLength) : payload;
49
- res.write(`${idLine}data: ${JSON.stringify(frame)}\n\n`);
50
- }
51
46
  async function mintSubmitExitResult(result, checkpoints) {
52
47
  return redactTerminalResult(sealResultForExit(await graftParkToolCallId(result, checkpoints)));
53
48
  }
@@ -68,7 +63,7 @@ function sendSubmitResult(res, resp) {
68
63
  sendJson(res, 200, body);
69
64
  }
70
65
  function writeMetaFrame(res, taskId, sessionId, warnings) {
71
- res.write(`event: meta\ndata: ${JSON.stringify({ type: "meta", taskId, ...(sessionId ? { sessionId } : {}), ...(warnings !== undefined ? { warnings } : {}) })}\n\n`);
66
+ writeLiveFrame(res, { type: "meta", taskId, ...(sessionId ? { sessionId } : {}), ...(warnings !== undefined ? { warnings } : {}) });
72
67
  }
73
68
  function refusalDoneResult(body) {
74
69
  if (isActiveRunConflictBody(body))
@@ -116,7 +111,7 @@ export async function handleTasks(req, res, match, ctx) {
116
111
  if (liveStream && replay.status === 200) {
117
112
  sseHeaders(res, { "x-task-id": keyedRow.taskId });
118
113
  writeMetaFrame(res, keyedRow.taskId, keyedRow.sessionId);
119
- sseData(res, { type: "done", result: replay.body, replay: true });
114
+ writeLiveFrame(res, { type: "done", result: replay.body, replay: true });
120
115
  res.end();
121
116
  }
122
117
  else {
@@ -129,14 +124,14 @@ export async function handleTasks(req, res, match, ctx) {
129
124
  sseHeaders(res);
130
125
  const hb = setInterval(() => {
131
126
  if (!res.writableEnded)
132
- res.write(`event: heartbeat\ndata: {}\n\n`);
127
+ writeLiveHeartbeat(res);
133
128
  }, 15_000);
134
129
  hb.unref?.();
135
130
  res.on("close", () => clearInterval(hb));
136
131
  try {
137
132
  const resp = await cached;
138
133
  if (!res.writableEnded)
139
- sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
134
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
140
135
  }
141
136
  finally {
142
137
  clearInterval(hb);
@@ -260,18 +255,18 @@ export async function handleTasks(req, res, match, ctx) {
260
255
  deps.logger?.warn?.("approval_preamble_row_skipped", { sessionId: replaySessionId, skipped, face: "tasks.stream" });
261
256
  if (dropped > 0)
262
257
  deps.logger?.warn?.("approval_preamble_capped", { sessionId: replaySessionId, dropped, replayMax: deps.config.streamApproval.replayMax, face: "tasks.stream" });
263
- return buildApprovalPreambleSseFrames(frames);
258
+ return frames;
264
259
  }, (reason, err) => deps.logger?.warn?.("approval_preamble_failed", { sessionId: replaySessionId, reason, face: "tasks.stream", error: err instanceof Error ? err.message : String(err ?? "") }));
265
260
  if (!res.writableEnded && !res.destroyed) {
266
261
  for (const f of preambleFrames)
267
- res.write(`event: ${f.event}\ndata: ${JSON.stringify(f.data)}\n\n`);
262
+ writeLiveFrame(res, { ...f });
268
263
  if (deps.toolApproval && preambleFrames.length > 0) {
269
264
  for (const askId of presentedAskIds)
270
265
  presentedOnConnection.add(askId);
271
266
  const unwatch = deps.toolApproval.watchPresentedCards(presentedAskIds, (frame) => {
272
267
  if (res.writableEnded || res.destroyed || !admitPresentedComplete(frame.askId))
273
268
  return;
274
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
269
+ writeLiveFrame(res, { ...frame });
275
270
  });
276
271
  res.once("close", unwatch);
277
272
  }
@@ -279,7 +274,7 @@ export async function handleTasks(req, res, match, ctx) {
279
274
  }
280
275
  const hb = setInterval(() => {
281
276
  if (!res.writableEnded && !res.destroyed)
282
- res.write(`event: heartbeat\ndata: {}\n\n`);
277
+ writeLiveHeartbeat(res);
283
278
  }, 15_000);
284
279
  hb.unref?.();
285
280
  let ranLive = false;
@@ -294,13 +289,14 @@ export async function handleTasks(req, res, match, ctx) {
294
289
  let userMsgEntryId;
295
290
  const promptCommit = createPromptCommitReader();
296
291
  let anchorPut = false;
297
- const putRewindAnchor = () => {
298
- if (anchorPut || !userMsgEntryId || !durableTaskId || !deps.resumeAnchorStore)
292
+ const putRewindAnchor = async () => {
293
+ const store = deps.resumeAnchorStore;
294
+ const key = durableTaskId;
295
+ const entryId = userMsgEntryId;
296
+ if (anchorPut || !entryId || !key || !store)
299
297
  return;
300
298
  anchorPut = true;
301
- void deps.resumeAnchorStore
302
- .put(prepared.spec.sessionId, durableTaskId, userMsgEntryId, principal ?? null)
303
- .catch(() => deps.metrics?.inc("resume_anchor_capture_failed"));
299
+ await settleResumeAnchor(() => store.put(prepared.spec.sessionId, key, entryId, principal ?? null), { leg: "stream", kind: "prompt" });
304
300
  };
305
301
  if (deps.runStore) {
306
302
  const tid = earlyDurableTid ?? uuidv7();
@@ -311,23 +307,23 @@ export async function handleTasks(req, res, match, ctx) {
311
307
  recordResourceWindow(tid, prepared.spec.resourceSuspend);
312
308
  if (created.existing) {
313
309
  const replay = await replayOfExistingRun(created.existing, { principal: submitter, idem }, "sync", deps, deps.runStore);
314
- sseData(res, { type: "done", result: doneResultOfOutcome(replay), replay: true });
310
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(replay), replay: true });
315
311
  return replay;
316
312
  }
317
313
  if (created.sessionAbsent) {
318
314
  const refused = rootSessionAbsentAnswer();
319
- sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
315
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(refused) });
320
316
  return refused;
321
317
  }
322
318
  if (!created.ok) {
323
319
  const conflict = await buildActiveRunConflict({ runStore: deps.runStore, checkpointStore: deps.checkpointStore, governance: deps.config, runStaleSec: deps.config.runStaleSec, turnActivity: readTurnActivityMs }, prepared.spec.sessionId, created.activeTaskId);
324
320
  const refused = { status: 409, body: conflict };
325
- sseData(res, { type: "done", result: doneResultOfOutcome(refused) });
321
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(refused) });
326
322
  return refused;
327
323
  }
328
324
  const placementReject = await commitExecutionContext(deps, { kind: "run", runStore: deps.runStore, taskId: tid }, prepared.execution);
329
325
  if (placementReject) {
330
- sseData(res, { type: "done", result: doneResultOfOutcome(placementReject) });
326
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(placementReject) });
331
327
  return placementReject;
332
328
  }
333
329
  durableTaskId = tid;
@@ -335,7 +331,7 @@ export async function handleTasks(req, res, match, ctx) {
335
331
  if (deps.checkpointStore) {
336
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() });
337
333
  if (ctxRefusal) {
338
- sseData(res, { type: "done", result: doneResultOfOutcome(ctxRefusal) });
334
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(ctxRefusal) });
339
335
  return ctxRefusal;
340
336
  }
341
337
  }
@@ -407,7 +403,7 @@ export async function handleTasks(req, res, match, ctx) {
407
403
  recordFailOpen(failOpenTagForDroppedFrame("engine_notice"), "frame=engine_notice");
408
404
  return;
409
405
  }
410
- sseData(res, { type: "engine_notice", ...row });
406
+ writeLiveFrame(res, { type: "engine_notice", ...row });
411
407
  },
412
408
  ...(noticeLedger
413
409
  ? {
@@ -437,34 +433,34 @@ export async function handleTasks(req, res, match, ctx) {
437
433
  if (res.writableEnded)
438
434
  return;
439
435
  for (const end of childReasoning.onEvent(e))
440
- sseData(res, end);
436
+ writeLiveFrame(res, end);
441
437
  const t = e.type;
442
438
  if (t === "task_progress") {
443
- sseData(res, { type: "task_progress", ...taskProgressEventData(e) });
439
+ writeLiveFrame(res, { type: "task_progress", ...taskProgressEventData(e) });
444
440
  }
445
441
  else if (t === "task_started") {
446
- sseData(res, { type: "task_started", ...taskStartedEventData(e) });
442
+ writeLiveFrame(res, { type: "task_started", ...taskStartedEventData(e) });
447
443
  }
448
444
  else if (t === "tool_start") {
449
445
  const tsv = e;
450
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
446
+ writeLiveFrame(res, { type: "tool_start", ...toolStartEventData(tsv) });
451
447
  }
452
448
  else if (t === "tool_end") {
453
449
  const te = e;
454
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
450
+ writeLiveFrame(res, { type: "tool_end", ...toolEndEventData(te) });
455
451
  }
456
452
  else if (t === "text_delta") {
457
453
  const td = e;
458
- sseData(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
454
+ writeLiveFrame(res, { type: "text_delta", delta: td.delta, ...(td.eventId ? { eventId: td.eventId } : {}), ...(td.parentToolCallId ? { parentToolCallId: td.parentToolCallId } : {}) });
459
455
  }
460
456
  else if (t === "text_end") {
461
457
  const tend = textEndEventData(e);
462
458
  if (tend !== null)
463
- sseData(res, { type: "text_end", ...tend });
459
+ writeLiveFrame(res, { type: "text_end", ...tend });
464
460
  }
465
461
  else if (t === "reasoning_delta") {
466
462
  const rd = e;
467
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
463
+ writeLiveFrame(res, { type: "reasoning_delta", delta: redactSecrets(rd.delta), ...(rd.eventId ? { eventId: rd.eventId } : {}), ...(rd.parentToolCallId ? { parentToolCallId: rd.parentToolCallId } : {}) });
468
464
  }
469
465
  },
470
466
  onTaskNotification: (n, opts) => {
@@ -472,7 +468,7 @@ export async function handleTasks(req, res, match, ctx) {
472
468
  return;
473
469
  if (!res.writableEnded)
474
470
  for (const end of childReasoning.cut(reasoningStreamOfTask(n.task_id, n.sessionId)))
475
- sseData(res, end);
471
+ writeLiveFrame(res, end);
476
472
  defaultSubagentTailBus.forgetHandle(n.task_id);
477
473
  if (defaultSubagentTailBus.hasSubscribers(n.task_id)) {
478
474
  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) } : {}) });
@@ -488,7 +484,7 @@ export async function handleTasks(req, res, match, ctx) {
488
484
  const key = taskNotificationDedupKey(n);
489
485
  if (syncNotifiedKeys.get(key) === undefined) {
490
486
  syncNotifiedKeys.set(key, Promise.resolve(true));
491
- sseData(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
487
+ writeLiveFrame(res, { type: "task_notification", ...taskNotificationEventData({ notification: n, ...(opts?.priority !== undefined ? { priority: opts.priority } : {}) }) });
492
488
  }
493
489
  }
494
490
  },
@@ -505,13 +501,13 @@ export async function handleTasks(req, res, match, ctx) {
505
501
  void heldFor(prepared.peerLease, () => Promise.allSettled([Promise.resolve().then(() => liveStream.result())]));
506
502
  if (durableTaskId)
507
503
  steerableRuns.set(durableTaskId, liveStream);
508
- prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => sseData(res, { ...frame }) });
504
+ prepared.acceptance.attachStream({ reachable: () => !closed && !res.writableEnded && !res.destroyed, write: (frame) => writeLiveFrame(res, { ...frame }) });
509
505
  const liveWorkspace = createSessionWorkspaceRecorder(sessionWorkspaceStoreOf(deps.sessionStorage), legSessionWitnessOf(prepared.spec));
510
506
  for await (const ev of liveStream) {
511
507
  if (closed)
512
508
  break;
513
509
  for (const end of ev.type === "done" ? [...childReasoning.cut(), ...topReasoning.cut()] : topReasoning.onEvent(ev))
514
- sseData(res, end);
510
+ writeLiveFrame(res, end);
515
511
  const promptEntryId = promptCommit(ev);
516
512
  if (promptEntryId !== undefined)
517
513
  userMsgEntryId = promptEntryId;
@@ -528,7 +524,7 @@ export async function handleTasks(req, res, match, ctx) {
528
524
  }
529
525
  finalizeTaskResult(ev.result, principal, prepared.spec.objective);
530
526
  noteRunOutcome(finalResult);
531
- putRewindAnchor();
527
+ await putRewindAnchor();
532
528
  settleFleet(outwardPlane(finalResult.terminal).status, fleetRunResiduals(finalResult));
533
529
  if (ledgerSink && finalResult) {
534
530
  if (usageKey && deps.modelUsage && deps.runStore && durableTaskId) {
@@ -540,7 +536,7 @@ export async function handleTasks(req, res, match, ctx) {
540
536
  await ledgerSink.onDone(finalResult);
541
537
  ledgerTerminal = true;
542
538
  }
543
- sseData(res, { ...ev, result: finalResult });
539
+ writeLiveFrame(res, { ...ev, result: finalResult });
544
540
  continue;
545
541
  }
546
542
  if (ledgerSink) {
@@ -552,15 +548,15 @@ export async function handleTasks(req, res, match, ctx) {
552
548
  if (ev.type === "status")
553
549
  deps.metrics?.inc("brain_retry_total", { phase: String(ev.phase) });
554
550
  if (ev.type === "status") {
555
- sseData(res, { type: "status", ...brainStatusEventData(ev) });
551
+ writeLiveFrame(res, { type: "status", ...brainStatusEventData(ev) });
556
552
  }
557
553
  else if (ev.type === "tool_end") {
558
554
  const te = ev;
559
- sseData(res, { type: "tool_end", ...toolEndEventData(te) });
555
+ writeLiveFrame(res, { type: "tool_end", ...toolEndEventData(te) });
560
556
  }
561
557
  else if (ev.type === "tool_start") {
562
558
  const tsv = ev;
563
- sseData(res, { type: "tool_start", ...toolStartEventData(tsv) });
559
+ writeLiveFrame(res, { type: "tool_start", ...toolStartEventData(tsv) });
564
560
  }
565
561
  else if (ev.type === "task_notification") {
566
562
  const tnv = ev.notification;
@@ -569,58 +565,58 @@ export async function handleTasks(req, res, match, ctx) {
569
565
  if (tnvPrior === undefined || !(await tnvPrior)) {
570
566
  if (tnvKey !== undefined)
571
567
  syncNotifiedKeys.set(tnvKey, Promise.resolve(true));
572
- sseData(res, { type: "task_notification", ...taskNotificationEventData(ev) });
568
+ writeLiveFrame(res, { type: "task_notification", ...taskNotificationEventData(ev) });
573
569
  }
574
570
  }
575
571
  else if (ev.type === "reasoning_delta" && typeof ev.delta === "string") {
576
- sseData(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
572
+ writeLiveFrame(res, { type: "reasoning_delta", delta: redactSecrets(ev.delta), ...(ev.eventId ? { eventId: ev.eventId } : {}), ...(ev.parentToolCallId ? { parentToolCallId: ev.parentToolCallId } : {}) });
577
573
  }
578
574
  else if (ev.type === "task_progress") {
579
- sseData(res, { type: "task_progress", ...taskProgressEventData(ev) });
575
+ writeLiveFrame(res, { type: "task_progress", ...taskProgressEventData(ev) });
580
576
  }
581
577
  else if (ev.type === "task_started") {
582
- sseData(res, { type: "task_started", ...taskStartedEventData(ev) });
578
+ writeLiveFrame(res, { type: "task_started", ...taskStartedEventData(ev) });
583
579
  }
584
580
  else if (ev.type === "compacted") {
585
- sseData(res, { type: "compacted", ...compactedEventData(ev) });
581
+ writeLiveFrame(res, { type: "compacted", ...compactedEventData(ev) });
586
582
  }
587
583
  else if (ev.type === "diagnostics") {
588
- sseData(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
584
+ writeLiveFrame(res, { type: "diagnostics", ...diagnosticsEventData(ev) });
589
585
  }
590
586
  else if (ev.type === "steering_injected") {
591
- sseData(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
587
+ writeLiveFrame(res, { type: "steering_injected", ...steeringInjectedEventData(ev) });
592
588
  }
593
589
  else if (ev.type === "workspace_changed") {
594
- sseData(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
590
+ writeLiveFrame(res, { type: "workspace_changed", ...workspaceChangedEventData(ev) });
595
591
  }
596
592
  else if (ev.type === "compaction_outcome") {
597
- sseData(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
593
+ writeLiveFrame(res, { type: "compaction_outcome", ...compactionOutcomeEventData(ev) });
598
594
  }
599
595
  else if (ev.type === "compaction_started") {
600
- sseData(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
596
+ writeLiveFrame(res, { type: "compaction_started", ...compactionStartedEventData(ev) });
601
597
  }
602
598
  else if (ev.type === "wiring_manifest") {
603
599
  const wiringFace = wiringManifestFaceEventData(ev, wiringOperatorFace, legWiringSections());
604
600
  wiringReceipt ??= wiringFace;
605
- sseData(res, { type: "wiring_manifest", ...wiringFace });
601
+ writeLiveFrame(res, { type: "wiring_manifest", ...wiringFace });
606
602
  }
607
603
  else if (ev.type === "tool_roster_delta") {
608
604
  const rosterDelta = toolRosterDeltaEventData(ev);
609
605
  if (rosterDelta !== undefined)
610
- sseData(res, { type: "tool_roster_delta", ...rosterDelta });
606
+ writeLiveFrame(res, { type: "tool_roster_delta", ...rosterDelta });
611
607
  }
612
608
  else if (ev.type === "tool_progress") {
613
609
  const progress = toolProgressEventData(ev);
614
610
  if (progress !== undefined)
615
- sseData(res, { type: "tool_progress", ...progress });
611
+ writeLiveFrame(res, { type: "tool_progress", ...progress });
616
612
  }
617
613
  else if (ev.type === "tool_disclosure") {
618
614
  const disclosure = toolDisclosureEventData(ev);
619
615
  if (disclosure !== undefined)
620
- sseData(res, { type: "tool_disclosure", ...disclosure });
616
+ writeLiveFrame(res, { type: "tool_disclosure", ...disclosure });
621
617
  }
622
618
  else if (ev.type === "human_input") {
623
- sseData(res, { type: "human_input", ...humanInputEventData(ev) });
619
+ writeLiveFrame(res, { type: "human_input", ...humanInputEventData(ev) });
624
620
  }
625
621
  else if (ev.type === "text_delta" || ev.type === "text_end" || ev.type === "turn_end" || ev.type === "message_committed" || ev.type === "context_usage") {
626
622
  const e = ev;
@@ -637,10 +633,10 @@ export async function handleTasks(req, res, match, ctx) {
637
633
  ? { type: "message_committed", entryId: e.entryId, role: e.role, ...(e.toolCallId !== undefined ? { toolCallId: e.toolCallId } : {}), ...ident }
638
634
  : { type: "context_usage", ...contextUsageEventData(ev), ...ident };
639
635
  if (arm !== null)
640
- sseData(res, arm);
636
+ writeLiveFrame(res, arm);
641
637
  }
642
638
  else {
643
- sseData(res, { ...ev });
639
+ writeLiveFrame(res, { ...ev });
644
640
  }
645
641
  }
646
642
  });
@@ -652,7 +648,7 @@ export async function handleTasks(req, res, match, ctx) {
652
648
  recordFailOpen(failOpenTagForDroppedFrame(frame.type), `frame=${frame.type}`);
653
649
  return;
654
650
  }
655
- res.write(`event: ${frame.type}\ndata: ${JSON.stringify(frame)}\n\n`);
651
+ writeLiveFrame(res, { ...frame });
656
652
  };
657
653
  const faceAlive = () => !res.writableEnded && !res.destroyed;
658
654
  const emitElicitation = createLedgerTwinEmit({ sink: ledgerSink, writeLive: emitAsk, liveReachable: faceAlive });
@@ -669,7 +665,7 @@ export async function handleTasks(req, res, match, ctx) {
669
665
  const fKey = f.type === "task_notification" ? taskNotificationStreamKeyOf(f) : undefined;
670
666
  if (fKey !== undefined)
671
667
  syncNotifiedKeys.set(fKey, Promise.resolve(true));
672
- sseData(res, frame);
668
+ writeLiveFrame(res, frame);
673
669
  }, { route: "sync-stream-open", connection: "live-sse", log: (m, x) => deps.logger?.info?.(m, x) });
674
670
  const withElicit = deps.elicitation
675
671
  ? () => deps.elicitation.runWithContext({ taskId: askTaskId, owner: askOwner, emit: emitElicitation, abortSignal: ac.signal }, streamBody)
@@ -765,7 +761,7 @@ export async function handleTasks(req, res, match, ctx) {
765
761
  await releaseKeyIfZeroWorkRefusal(deps.runStore, durableTaskId, finalResult);
766
762
  }
767
763
  else {
768
- putRewindAnchor();
764
+ await putRewindAnchor();
769
765
  const pending = await deps.checkpointStore?.findPendingTokenBySession(prepared.spec.sessionId);
770
766
  const dcCause = ac.cause();
771
767
  if (pending) {
@@ -885,7 +881,7 @@ export async function handleTasks(req, res, match, ctx) {
885
881
  deps.modelUsage?.clear(usageKey);
886
882
  }
887
883
  if (!ranLive && resp && !res.writableEnded) {
888
- sseData(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
884
+ writeLiveFrame(res, { type: "done", result: doneResultOfOutcome(resp), replay: true });
889
885
  }
890
886
  res.end();
891
887
  }
@@ -969,7 +965,7 @@ export async function handleTasks(req, res, match, ctx) {
969
965
  }
970
966
  return stream.result();
971
967
  };
972
- result = await instructionLeg.run(prepared.spec.sessionId, () => withPrincipal(principal, () => prepared.verify ? verifyLeg(prepared.verify) : prepared.cascade ? cascadeLeg() : plainLeg()));
968
+ result = atHostBoundary(await instructionLeg.run(prepared.spec.sessionId, () => withPrincipal(principal, () => prepared.verify ? verifyLeg(prepared.verify) : prepared.cascade ? cascadeLeg() : plainLeg())), prepared.spec.sessionId);
973
969
  }
974
970
  finally {
975
971
  counters.uncountedBillableInflight--;
@@ -979,6 +975,7 @@ export async function handleTasks(req, res, match, ctx) {
979
975
  inflightRuns.delete(durableTaskId);
980
976
  }
981
977
  const syncAbortCause = syncCancelCtrl.cause();
978
+ await voidVerifierPauseCard(result, deps.checkpointStore);
982
979
  if (syncAbortCause !== undefined) {
983
980
  result = mintCancelledResult({
984
981
  taskId: durableTaskId ?? "",
@@ -1006,10 +1003,12 @@ export async function handleTasks(req, res, match, ctx) {
1006
1003
  const syncPlane = outwardPlane(result.terminal);
1007
1004
  if (syncPlane.status === "suspended" && deps.checkpointStore && deps.runStore && durableTaskId) {
1008
1005
  await deps.runStore.setSuspended(durableTaskId, exitResult);
1006
+ prepared.acceptance.settle(result);
1009
1007
  return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "suspended" })) };
1010
1008
  }
1011
1009
  if (syncPlane.status === "needs_review" && deps.checkpointStore && deps.runStore && durableTaskId) {
1012
1010
  await deps.runStore.setNeedsReview(durableTaskId, exitResult);
1011
+ prepared.acceptance.settle(result);
1013
1012
  return { status: 200, body: withSyncSubmitKeys(buildSyncSubmitBody(exitResult, { taskId: durableTaskId, sessionId: prepared.spec.sessionId, status: "needs_review" })) };
1014
1013
  }
1015
1014
  if (durableTaskId && deps.runStore)
@@ -1,5 +1,5 @@
1
1
  import { persistedPlaneOf } from "../terminal.js";
2
- import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, redactTerminalResult } from "../observability/run-terminal.js";
2
+ import { memoRedactedRead, memoRedactTerminalResult, redactErrorMessage, sealRunRowResult } from "../observability/run-terminal.js";
3
3
  import { RUN_HOLDER_DEATH_CODES, isTerminalRunStatus } from "../plugins/store-contracts.js";
4
4
  import { composeSupervisorCost, infraCost, infraUsageFromEvents, hasInfraPricing } from "../observability/cost-taxonomy.js";
5
5
  import { recordFailOpen } from "../observability/fail-open.js";
@@ -53,14 +53,14 @@ export async function readRunFace(deps, runStore, run) {
53
53
  status: stale ? "failed" : run.status,
54
54
  ...(lastActivityAt !== undefined ? { msSinceLastActivity: Math.max(0, Date.now() - lastActivityAt) } : {}),
55
55
  ...(crossSliceUsage !== undefined ? { crossSliceUsage } : {}),
56
- result: isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : redactTerminalResult(run.result ?? undefined),
56
+ result: isTerminalRunStatus(run.status) ? memoRedactTerminalResult("run.result", run.result ?? undefined) : (sealRunRowResult(run.result ?? null, "run.result") ?? undefined),
57
57
  supervisorCost,
58
58
  suggestions,
59
59
  errorCode: stale ? RUN_HOLDER_DEATH_CODES.stalled : (persistedPlaneOf(run.result).errorCode ?? run.errorCode ?? undefined),
60
60
  error: stale ? "run stalled (instance lost?)" : isTerminalRunStatus(run.status) ? memoRedactedRead("run.error", run.error ?? undefined, redactErrorMessage) : redactErrorMessage(run.error ?? undefined),
61
61
  jobId: run.jobId ?? undefined,
62
62
  source: run.source ?? undefined,
63
- heldBy: run.instanceId ?? null,
63
+ heldBy: isTerminalRunStatus(run.status) ? null : (run.instanceId ?? null),
64
64
  cancelRequested: run.cancelRequested,
65
65
  };
66
66
  }
@@ -113,7 +113,7 @@ export declare function sendHttpError(res: ServerResponse, e: HttpError): void;
113
113
  */
114
114
  export declare function sendSessionPolicyError(res: ServerResponse, e: unknown, sentencePrefix?: string): boolean;
115
115
  /**
116
- * [ref] —— core `SessionError` → 应答,经 {@link sessionErrorHttp} 那**一只**映射(`src/session-error-wire.ts`)。
116
+ * [ref] —— core `SessionError` → 应答,经 {@link sessionErrorWireOf} 那**一只**映射(`src/session-error-wire.ts`;本服务自铸的同码具名拒按型先认,其余按码)。
117
117
  * 回 `true` = 已应答,调用点 `return`;`false` = 不是 `SessionError`,或这个词在这一面上是登记过的留白(站点的既有
118
118
  * 处置照旧 —— 通常是继续上抛到全局兜底)。
119
119
  *
package/dist/http/send.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SessionError, SessionPolicyError } from "@sema-agent/core";
2
2
  import { sessionPolicyErrorFacts, sessionPolicyErrorHttp, sessionPolicyErrorSentence } from "../session-policy-wire.js";
3
- import { sessionErrorHttp } from "../session-error-wire.js";
3
+ import { sessionErrorWireOf } from "../session-error-wire.js";
4
4
  import { redactErrorMessage, redactHead } from "../observability/run-terminal.js";
5
5
  import { createCodedHttpError } from "../security.js";
6
6
  import { refusalBody } from "./refusal-body.js";
@@ -79,7 +79,7 @@ export function sendSessionPolicyError(res, e, sentencePrefix = "") {
79
79
  export function sendSessionError(res, e, face) {
80
80
  if (!(e instanceof SessionError))
81
81
  return false;
82
- const wire = sessionErrorHttp(e.code, face);
82
+ const wire = sessionErrorWireOf(e, face);
83
83
  if (wire === undefined)
84
84
  return false;
85
85
  sendError(res, wire.status, wire.errorCode, wire.sentence ?? redactErrorMessage(e.message) ?? "session store error", wire.detail === undefined ? undefined : { detail: wire.detail });
@@ -1,8 +1,8 @@
1
1
  import http from "node:http";
2
- import type { MemoryComplianceFaces } from "../memory-operator-faces.js";
2
+ import type { MemoryComplianceFaces, MemoryOriginFaces, SessionMemoryStatusFace } from "../memory-operator-faces.js";
3
3
  import type { SideQueryAccounting } from "../budget.js";
4
4
  import type { IncomingMessage } from "node:http";
5
- import { type Runner, type TaskSpec, type TaskResult, type WorkflowRunStore, type MemoryEntry, type MemoryExportBundle, type MemoryImportReport, type EntryProvenanceAccount, type MemoryEntryOrigin, type OriginClearanceRow, type SessionMemoryStatus, type ConsolidationRunReceipt, type ConsolidationDriverRunRow, type SideQuerySpec, type SideQueryResult, type Brain, type EngineNotice } from "@sema-agent/core";
5
+ import { type Runner, type TaskSpec, type TaskResult, type WorkflowRunStore, type MemoryEntry, type MemoryExportBundle, type MemoryImportReport, type ConsolidationRunReceipt, type ConsolidationDriverRunRow, type SideQuerySpec, type SideQueryResult, type Brain, type EngineNotice } from "@sema-agent/core";
6
6
  import type { TaskRequestBody } from "./wire-types.js";
7
7
  import type { ServiceConfig } from "../config-types.js";
8
8
  import { type SessionMirrorRuling } from "../web-admin-client/facade.js";
@@ -13,6 +13,7 @@ import type { ExecutionRoot, ResolvedTaskSpec } from "./execution-context.js";
13
13
  import type { RunStore, ImageIndex, ImageBake, CheckpointStoreFull, ResumeAnchorStore, ApprovalExemptionStore, ApprovalNonceStore, ServiceSessionPolicyStore, ServiceFileHistoryStore, ToolResultStoreFull, StoreBackend } from "../plugins/store-backend.js";
14
14
  import type { RuleConsentLane } from "../rules-consent.js";
15
15
  import { type MemorySyncRequest, type MemorySyncResponse } from "../memory-sync.js";
16
+ import type { MemorySyncRunner } from "../memory-sync-client.js";
16
17
  import type { TaskAttachmentStore } from "../plugins/task-attachment-store.js";
17
18
  import type { LeaderEndpoint } from "../leader/endpoint.js";
18
19
  import { type WorkflowAgentRegistry } from "../orchestration/workflow-agent-steer.js";
@@ -463,7 +464,7 @@ export interface ServiceSeamDeps {
463
464
  }>;
464
465
  /** 142-S5 §1.4: per-scope memory export reader (main.ts wires `exportMemoryScope` over the DB memory
465
466
  * backend). Enables GET /v1/memory/export — present ONLY on a DB memory plane (MEMORY_ENGINE_BACKEND=
466
- * pg|tidb); absent / file posture ⇒ 501 (single-user file memory exports by copying the memory dir). */
467
+ * pg|mysql); absent / file posture ⇒ 501 (single-user file memory exports by copying the memory dir). */
467
468
  memoryExport?: (scope: string) => Promise<MemoryEntry[]>;
468
469
  /**
469
470
  * [ref](core 5.57.0 `routePairingStatus`)—— **key↔URL 配对读面**:`GET /v1/models` 每行的
@@ -479,7 +480,7 @@ export interface ServiceSeamDeps {
479
480
  /** 142-S2.5(设计 §2.5;裁定 plan 随数据走,core 零运行时半场):one full sync round for one
480
481
  * (scope, peer) — main.ts wires `performMemorySync` over the DB memory backend + the sync-cursor
481
482
  * store. Enables POST /v1/memory/sync/:scope — present ONLY on a DB memory plane
482
- * (MEMORY_ENGINE_BACKEND=pg|tidb); absent / file posture ⇒ 501 honestly (a single-user file plane
483
+ * (MEMORY_ENGINE_BACKEND=pg|mysql); absent / file posture ⇒ 501 honestly (a single-user file plane
483
484
  * IS the TOC side of a sync — it has no central-authority half to serve). */
484
485
  memorySync?: (scope: string, syncReq: MemorySyncRequest) => Promise<MemorySyncResponse>;
485
486
  /** [ref] v2-c(core 5.40.0 `MemoryEngine.exportMemoryScopes`):治理完备包的**携出**面。main.ts 把它接到
@@ -518,9 +519,7 @@ export interface ServiceSeamDeps {
518
519
  * (工厂返 undefined),与 compliance/origin 两族同一条 F-9 裁。
519
520
  * 🔴 face 的五键**全可选**(core `SessionMemoryStatus`):absent = 该事实源不可读,路由逐键透传缺席,
520
521
  * 恒不铸 false/0 替身;`optOutSource:"fault"` = capture 态 indeterminate(383 片2/3 轴直投)。 */
521
- sessionMemoryStatus?: {
522
- status: (sessionId: string) => Promise<SessionMemoryStatus>;
523
- };
522
+ sessionMemoryStatus?: SessionMemoryStatusFace;
524
523
  /**
525
524
  * [ref](core 7.22.0 [ref] W1)—— 本**部署**的自动整理武装事实,`GET /v1/sessions/:id/memory-status`
526
525
  * 的 `autoConsolidationArmed` 格。
@@ -535,6 +534,12 @@ export interface ServiceSeamDeps {
535
534
  * 装配漏接 ⇒ tsc 红(本行就是通知);测试桩在 `test/helpers/boot.ts` 显式给 false。
536
535
  */
537
536
  memoryAutoConsolidationArmed: boolean;
537
+ /**
538
+ * [ref] —— 本**部署**的记忆同步腿(客户端半场):`MEMORY_SYNC_URL` 设了且 file 记忆引擎亮着、执行器起了才在场(`boot/stores.ts`)。
539
+ * `GET /v1/sessions/:id/memory-status` 的 `memorySync` 格只读它的 `parked()` —— 停驻事实的唯一读口(写者 = 执行器的轮,运维行 `memory_sync_layer_parked` 读同一份);
540
+ * 缺席 ⇒ 那一格缺席(没有同步腿)。与 `memoryAutoConsolidationArmed` 同类:部署事实,不随会话、不随层座。
541
+ */
542
+ memorySyncLeg?: Pick<MemorySyncRunner, "parked">;
538
543
  /**
539
544
  * [ref] / [ref] + 车PI 修复轮 ④ —— 记忆整理阀门的**生效判决**(boot 第 4 段 `createConsolidationValve`:显式词,或出厂缺省按
540
545
  * 装配结果派生)。配置目录那一行(`GET /v1/config/catalog` 的 `MEMORY_CONSOLIDATION_DRIVER` `effectiveValue`)读它 —— 那一列的契约是
@@ -552,25 +557,7 @@ export interface ServiceSeamDeps {
552
557
  * ——落在副本本地盘上 = pod 重建即永久丢失。全文见 src/memory-operator-faces.ts 头注。
553
558
  * 🔴 `listClearances` 是**同步**的(core 的读面就是一次严格 sidecar 读),且账本损坏时**抛**
554
559
  * `ControlPlaneCorruptError` —— 那是 fail-closed 信号,不是空数组。 */
555
- memoryOriginFace?: {
556
- listExternal: (scopes: readonly string[]) => Promise<Array<{
557
- id: string;
558
- slug: string;
559
- scope: string;
560
- origin: MemoryEntryOrigin;
561
- provenance: EntryProvenanceAccount;
562
- }>>;
563
- listClearances: () => OriginClearanceRow[];
564
- clear: (entryId: string, input: {
565
- requestId: string;
566
- reason: string;
567
- }) => Promise<{
568
- entryId: string;
569
- clearanceId: string;
570
- origin: MemoryEntryOrigin;
571
- landedSlug: string;
572
- }>;
573
- };
560
+ memoryOriginFace?: MemoryOriginFaces;
574
561
  /** [ref](core 5.58.0 `runMemoryConsolidationDriver`):记忆 **consolidation 阀门**的操作面。
575
562
  * 启用 `POST /v1/admin/memory/consolidation/run` 与 `GET /v1/admin/memory/consolidation`(两口 operator-only)。
576
563
  * main.ts 把它接到 `createMemoryConsolidationFaces` 的产物上。
@@ -827,7 +814,7 @@ export interface ServiceDeploymentDeps {
827
814
  * 7.132.0 前这一席是 `sqlEngineFacts: () => SqlEngineFacts | null`(只给事实、不给方言);照旧传它 ⇒ `createHttpServer` 起服拒。
828
815
  * 🔴 **SQL 后端在场(`backend` 交出了 `mysqlPool()` / `pgPool()`)⇒ 本席必填**,缺席 ⇒ `createHttpServer` 起服拒(席缺席只表示「没有 SQL 后端」,不能是「忘了给」);
829
816
  * 本服务自己的装配(`boot/stores.ts` → `stage-10`)按同一个谓词(`sqlPoolsOf`)建立它,恒给。值形也在起服时判(同一只判官 `sqlEngineSeatIssue` 的另一臂):
830
- * `{ dialect: "tidb" | "pg", facts }`,`facts` 是 `null` 或带 `maxRowBytes` / `maxPacketBytes` / `wallSources` 的引擎事实;只改了键名的 `() => facts` 之类 ⇒ 起服拒。 */
817
+ * `{ dialect: "mysql" | "pg", facts }`,`facts` 是 `null` 或带 `maxRowBytes` / `maxPacketBytes` / `wallSources` 的引擎事实;只改了键名的 `() => facts` 之类 ⇒ 起服拒。 */
831
818
  sqlEngine?: import("../plugins/sql-driver.js").SqlEngineReading;
832
819
  /** [ref]:**写保护名表**的姿态(`write-protection.ts` 的 boot 期单一推导点 —— 与递给每只 Runner 的
833
820
  * `writeProtectedPaths` 座同一份 config 决定)。两个读面共用:`GET /v1/diagnostics/wiring` 的
@@ -76,9 +76,9 @@ export function createHttpServer(rawDeps) {
76
76
  if (issue !== undefined) {
77
77
  switch (issue) {
78
78
  case "required":
79
- throw new Error("createHttpServer: sqlEngine is required when a SQL store backend is wired (the backend hands out a SQL pool) — pass the pool's engine reading as sqlEngine: `{ dialect: \"tidb\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded; refusing to start rather than read the database's row and statement limits as absent and admit task bodies the database cannot store");
79
+ throw new Error("createHttpServer: sqlEngine is required when a SQL store backend is wired (the backend hands out a SQL pool) — pass the pool's engine reading as sqlEngine: `{ dialect: \"mysql\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded; refusing to start rather than read the database's row and statement limits as absent and admit task bodies the database cannot store");
80
80
  case "bad_shape":
81
- throw new Error(`createHttpServer: sqlEngine must be the SQL pool's engine reading \`{ dialect: "tidb" | "pg", facts }\` where \`facts\` is read live (a getter) and is null while the pool's connection setup has not succeeded, otherwise the engine facts object (maxRowBytes, maxPacketBytes and wallSources included) — got ${typeof deps.sqlEngine === "function" ? "a function (the 7.131.x reader \`() => facts\` goes in as \`{ dialect, get facts() { return f(); } }\`)" : describeValueShape(deps.sqlEngine)}; refusing to start rather than answer every task submission with a 500`);
81
+ throw new Error(`createHttpServer: sqlEngine must be the SQL pool's engine reading \`{ dialect: "mysql" | "pg", facts }\` where \`facts\` is read live (a getter) and is null while the pool's connection setup has not succeeded, otherwise the engine facts object (maxRowBytes, maxPacketBytes and wallSources included) — got ${typeof deps.sqlEngine === "function" ? "a function (the 7.131.x reader \`() => facts\` goes in as \`{ dialect, get facts() { return f(); } }\`)" : describeValueShape(deps.sqlEngine)}; refusing to start rather than answer every task submission with a 500`);
82
82
  default: {
83
83
  const unhandled = issue;
84
84
  throw new Error(`sqlEngine seat issue without a refusal: ${String(unhandled)}`);