@sema-agent/server 7.149.0 → 7.151.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 (441) hide show
  1. package/MIGRATION.md +307 -9
  2. package/README.md +1 -1
  3. package/README.zh-CN.md +1 -1
  4. package/USAGE.md +92 -40
  5. package/deploy/sema-up/README.md +7 -1
  6. package/deploy/sema-up/chart/Chart.yaml +1 -1
  7. package/deploy/sema-up/chart/templates/NOTES.txt +5 -0
  8. package/deploy/sema-up/chart/templates/_helpers.tpl +15 -16
  9. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -3
  10. package/deploy/sema-up/chart/templates/server.yaml +5 -3
  11. package/deploy/sema-up/chart/values-full-single.yaml +3 -1
  12. package/deploy/sema-up/chart/values.yaml +8 -1
  13. package/deploy/sema-up/cluster-up.sh +1 -0
  14. package/deploy/sema-up/kube-up.sh +1 -1
  15. package/deploy/sema-up/lib/flagshape.sh +1 -1
  16. package/deploy/sema-up/lib/helm-values-cluster.py +2 -0
  17. package/deploy/sema-up/lib/helm-values-kube.py +2 -0
  18. package/dist/adoption/import.js +3 -3
  19. package/dist/approval-ask-machine.d.ts +1 -1
  20. package/dist/approval-card.d.ts +3 -3
  21. package/dist/approval-gate-currency.d.ts +2 -2
  22. package/dist/audit.d.ts +1 -1
  23. package/dist/audit.js +2 -2
  24. package/dist/auth-bridge.d.ts +20 -0
  25. package/dist/auth-bridge.js +9 -0
  26. package/dist/background-session-reap.d.ts +2 -2
  27. package/dist/bake-runner/main.d.ts +4 -2
  28. package/dist/bind-host.d.ts +2 -3
  29. package/dist/bind-host.js +2 -4
  30. package/dist/boot/budget-tracing.js +1 -1
  31. package/dist/boot/deferred-sandbox-path-env.d.ts +5 -3
  32. package/dist/boot/deferred-sandbox-path-env.js +1 -2
  33. package/dist/boot/engine-lease.d.ts +5 -0
  34. package/dist/boot/engine-lease.js +1 -0
  35. package/dist/boot/execution-env.d.ts +8 -14
  36. package/dist/boot/execution-env.js +54 -17
  37. package/dist/boot/execution-lane.js +32 -5
  38. package/dist/boot/late-binds.d.ts +8 -4
  39. package/dist/boot/late-binds.js +7 -1
  40. package/dist/boot/memory-consolidation.d.ts +3 -2
  41. package/dist/boot/memory-consolidation.js +6 -6
  42. package/dist/boot/parked-revive-gate.d.ts +5 -5
  43. package/dist/boot/parked-revive-gate.js +2 -3
  44. package/dist/boot/reapers.d.ts +5 -0
  45. package/dist/boot/reapers.js +12 -1
  46. package/dist/boot/resolve-spec.d.ts +7 -8
  47. package/dist/boot/resolve-spec.js +80 -35
  48. package/dist/boot/retention-lane.d.ts +1 -1
  49. package/dist/boot/runner-deps.d.ts +9 -2
  50. package/dist/boot/runner-deps.js +3 -3
  51. package/dist/boot/session-age-out.d.ts +36 -0
  52. package/dist/boot/session-age-out.js +101 -0
  53. package/dist/boot/session-faces.d.ts +5 -14
  54. package/dist/boot/session-faces.js +28 -24
  55. package/dist/boot/stage-01-config.js +2 -0
  56. package/dist/boot/stage-03-store-backend.js +2 -2
  57. package/dist/boot/stage-05-execution-env.d.ts +5 -3
  58. package/dist/boot/stage-05-execution-env.js +2 -2
  59. package/dist/boot/stage-06-runners.d.ts +7 -4
  60. package/dist/boot/stage-06-runners.js +16 -8
  61. package/dist/boot/stage-07-capability-layer.d.ts +7 -4
  62. package/dist/boot/stage-07-capability-layer.js +3 -2
  63. package/dist/boot/stage-08-reapers.d.ts +7 -4
  64. package/dist/boot/stage-08-reapers.js +4 -2
  65. package/dist/boot/stage-09-leader.d.ts +11 -5
  66. package/dist/boot/stage-09-leader.js +12 -3
  67. package/dist/boot/stage-10-http-server.d.ts +44 -6
  68. package/dist/boot/stage-10-http-server.js +12 -10
  69. package/dist/boot/web-admin.d.ts +1 -1
  70. package/dist/boot/web-admin.js +3 -1
  71. package/dist/boot/workflow-orchestration.d.ts +7 -2
  72. package/dist/boot/workflow-orchestration.js +24 -7
  73. package/dist/bounded-rotation.d.ts +29 -0
  74. package/dist/bounded-rotation.js +24 -0
  75. package/dist/capability-facts.d.ts +84 -66
  76. package/dist/capability-facts.js +58 -41
  77. package/dist/center-credential.d.ts +25 -6
  78. package/dist/center-credential.js +25 -5
  79. package/dist/config-catalog.d.ts +26 -7
  80. package/dist/config-catalog.js +15 -12
  81. package/dist/config-invariants.d.ts +2 -1
  82. package/dist/config-invariants.js +4 -4
  83. package/dist/config-types.d.ts +22 -15
  84. package/dist/config.d.ts +51 -2
  85. package/dist/config.js +35 -24
  86. package/dist/deployment-governance.d.ts +7 -28
  87. package/dist/deployment-governance.js +1 -14
  88. package/dist/deployment-shape.d.ts +9 -1
  89. package/dist/deployment-shape.js +2 -1
  90. package/dist/device-protocol.d.ts +5 -4
  91. package/dist/device-protocol.js +1 -1
  92. package/dist/device-ws-hub.d.ts +1 -0
  93. package/dist/device-ws-hub.js +66 -29
  94. package/dist/device-ws-protocol.d.ts +79 -12
  95. package/dist/device-ws-protocol.js +64 -26
  96. package/dist/engine-identity.d.ts +23 -5
  97. package/dist/engine-identity.js +13 -0
  98. package/dist/entry-mode-clamp-notice.d.ts +2 -1
  99. package/dist/execution-env-refusal.d.ts +23 -0
  100. package/dist/execution-env-refusal.js +5 -0
  101. package/dist/execution-lane-caps.d.ts +3 -1
  102. package/dist/field-conflict.d.ts +3 -3
  103. package/dist/file-history-capture.d.ts +11 -4
  104. package/dist/file-history-capture.js +9 -6
  105. package/dist/file-history-disclosure.d.ts +7 -5
  106. package/dist/file-history-disclosure.js +7 -5
  107. package/dist/fleet/drain-entry.d.ts +4 -0
  108. package/dist/fleet/engine-signal.d.ts +14 -1
  109. package/dist/fleet/engine-signal.js +5 -1
  110. package/dist/fleet/fleet-reconciler.d.ts +1 -1
  111. package/dist/fleet/serving-lease.d.ts +18 -3
  112. package/dist/fleet/serving-lease.js +81 -35
  113. package/dist/fleet-client.d.ts +13 -11
  114. package/dist/fleet-client.js +53 -33
  115. package/dist/history-anchor.js +1 -1
  116. package/dist/hitl-delivery.d.ts +1 -3
  117. package/dist/hitl-delivery.js +1 -1
  118. package/dist/hooks/hook-runner.js +2 -2
  119. package/dist/host-lsp-manager.d.ts +2 -2
  120. package/dist/http/active-run-conflict.d.ts +3 -7
  121. package/dist/http/active-run-conflict.js +2 -2
  122. package/dist/http/admission.js +19 -4
  123. package/dist/http/approval-sweeps.js +7 -6
  124. package/dist/http/caller-trust.d.ts +2 -2
  125. package/dist/http/caller-trust.js +3 -3
  126. package/dist/http/checkpoint-ctx.d.ts +20 -63
  127. package/dist/http/checkpoint-ctx.js +2 -24
  128. package/dist/http/claim-heartbeat.d.ts +4 -4
  129. package/dist/http/claim-heartbeat.js +3 -3
  130. package/dist/http/dispatch.d.ts +2 -1
  131. package/dist/http/dispatch.js +36 -29
  132. package/dist/http/durable-run-leg.js +17 -17
  133. package/dist/http/health-self-report.d.ts +9 -1
  134. package/dist/http/health-self-report.js +2 -0
  135. package/dist/http/owner-access.d.ts +264 -20
  136. package/dist/http/owner-access.js +215 -5
  137. package/dist/http/readiness.d.ts +4 -2
  138. package/dist/http/resume-ctx-read.js +38 -1
  139. package/dist/http/resume-legs.d.ts +2 -1
  140. package/dist/http/resume-legs.js +273 -89
  141. package/dist/http/route-ctx.d.ts +41 -19
  142. package/dist/http/route-table.d.ts +1 -1
  143. package/dist/http/routes/a2a-serve.js +15 -14
  144. package/dist/http/routes/admin-memory-optout.d.ts +1 -1
  145. package/dist/http/routes/agents-roster.js +2 -3
  146. package/dist/http/routes/approvals-assistant.d.ts +3 -2
  147. package/dist/http/routes/approvals-assistant.js +12 -12
  148. package/dist/http/routes/background.d.ts +3 -3
  149. package/dist/http/routes/capabilities.js +10 -6
  150. package/dist/http/routes/config-catalog.d.ts +1 -1
  151. package/dist/http/routes/fleet.js +10 -8
  152. package/dist/http/routes/mcp-reconnect.js +2 -2
  153. package/dist/http/routes/memory-origin.d.ts +1 -1
  154. package/dist/http/routes/notify-wake.js +2 -3
  155. package/dist/http/routes/projects.d.ts +4 -2
  156. package/dist/http/routes/projects.js +7 -6
  157. package/dist/http/routes/retention-ops.d.ts +1 -1
  158. package/dist/http/routes/run-permission-mode.d.ts +1 -1
  159. package/dist/http/routes/run-permission-mode.js +2 -2
  160. package/dist/http/routes/runs.d.ts +1 -1
  161. package/dist/http/routes/runs.js +125 -66
  162. package/dist/http/routes/session-memory-sync.js +4 -5
  163. package/dist/http/routes/session-sync.d.ts +4 -3
  164. package/dist/http/routes/session-sync.js +174 -83
  165. package/dist/http/routes/sessions-list.js +13 -7
  166. package/dist/http/routes/sessions.d.ts +1 -1
  167. package/dist/http/routes/sessions.js +26 -48
  168. package/dist/http/routes/tasks.js +38 -23
  169. package/dist/http/routes/trace-usage.js +14 -14
  170. package/dist/http/routes/workflows.d.ts +1 -0
  171. package/dist/http/routes/workflows.js +20 -38
  172. package/dist/http/server.d.ts +28 -30
  173. package/dist/http/server.js +7 -3
  174. package/dist/http/stored-body-replay.d.ts +3 -24
  175. package/dist/http/stored-body-replay.js +2 -12
  176. package/dist/http/submit-ctx.d.ts +1 -2
  177. package/dist/http/submit-ctx.js +8 -6
  178. package/dist/http/submit-replay.d.ts +15 -2
  179. package/dist/http/submit-replay.js +10 -4
  180. package/dist/http/wire-types.d.ts +19 -6
  181. package/dist/identity-source.d.ts +20 -3
  182. package/dist/identity-source.js +14 -0
  183. package/dist/index.d.ts +4 -0
  184. package/dist/lane-home-probe.d.ts +3 -7
  185. package/dist/lane-home-probe.js +0 -1
  186. package/dist/leader/endpoint.js +9 -8
  187. package/dist/leader/leader.d.ts +2 -1
  188. package/dist/leg-facts.d.ts +19 -5
  189. package/dist/leg-facts.js +3 -1
  190. package/dist/mcp-authorization-face.d.ts +18 -14
  191. package/dist/mcp-authorization-face.js +3 -2
  192. package/dist/memory-scope.d.ts +5 -4
  193. package/dist/memory-scope.js +4 -4
  194. package/dist/memory-store-refusal.d.ts +1 -1
  195. package/dist/memory-sync-client.d.ts +30 -2
  196. package/dist/memory-sync-client.js +16 -9
  197. package/dist/observability/corrupt-read-seat.d.ts +1 -1
  198. package/dist/observability/err-text.d.ts +7 -0
  199. package/dist/observability/err-text.js +5 -0
  200. package/dist/observability/fail-open.d.ts +12 -8
  201. package/dist/observability/fail-open.js +12 -8
  202. package/dist/observability/logger.d.ts +7 -0
  203. package/dist/observability/logger.js +3 -1
  204. package/dist/observability/metrics.js +1 -0
  205. package/dist/observability/run-terminal.d.ts +1 -1
  206. package/dist/orchestration/workflow-notify-journal.d.ts +18 -1
  207. package/dist/orchestration/workflow-notify-journal.js +12 -1
  208. package/dist/orchestration/workflow-park-decision.d.ts +70 -18
  209. package/dist/orchestration/workflow-park-decision.js +49 -10
  210. package/dist/orchestration/workflow-park-holder.d.ts +65 -0
  211. package/dist/orchestration/workflow-park-holder.js +98 -0
  212. package/dist/orchestration/workflow-record-fence.d.ts +36 -0
  213. package/dist/orchestration/workflow-record-fence.js +42 -0
  214. package/dist/owner-faces.d.ts +28 -4
  215. package/dist/owner-faces.js +2 -0
  216. package/dist/parked-decide.d.ts +104 -53
  217. package/dist/parked-decide.js +153 -117
  218. package/dist/peer-directory.d.ts +2 -2
  219. package/dist/peer-inbound-face.d.ts +2 -6
  220. package/dist/peer-inbound-face.js +0 -3
  221. package/dist/peer-seat.d.ts +1 -1
  222. package/dist/peer-seat.js +52 -59
  223. package/dist/permission-mode-admission.d.ts +41 -5
  224. package/dist/permission-mode-admission.js +29 -3
  225. package/dist/plugins/adoption-log-sql.d.ts +3 -1
  226. package/dist/plugins/adoption-log-sql.js +7 -1
  227. package/dist/plugins/approval-ask-store-file.d.ts +10 -2
  228. package/dist/plugins/approval-ask-store-file.js +8 -0
  229. package/dist/plugins/approval-ask-store-memory.d.ts +6 -1
  230. package/dist/plugins/approval-ask-store-memory.js +28 -9
  231. package/dist/plugins/approval-ask-store-sql.d.ts +43 -2
  232. package/dist/plugins/approval-ask-store-sql.js +34 -5
  233. package/dist/plugins/approval-exemption-store.js +3 -0
  234. package/dist/plugins/approval-nonce-store.js +2 -0
  235. package/dist/plugins/breaker-state-sql.js +2 -0
  236. package/dist/plugins/caching-session-store.d.ts +9 -15
  237. package/dist/plugins/caching-session-store.js +6 -0
  238. package/dist/plugins/device-store-sql.js +6 -0
  239. package/dist/plugins/error-origin.d.ts +18 -0
  240. package/dist/plugins/error-origin.js +10 -0
  241. package/dist/plugins/exec-path-law.d.ts +34 -0
  242. package/dist/plugins/exec-path-law.js +13 -0
  243. package/dist/plugins/execution-placement-sql.js +6 -6
  244. package/dist/plugins/file-run-store.js +1 -1
  245. package/dist/plugins/image-bake-store-sql.js +6 -0
  246. package/dist/plugins/image-index-sql.js +4 -0
  247. package/dist/plugins/landed-attendants.d.ts +212 -0
  248. package/dist/plugins/landed-attendants.js +161 -0
  249. package/dist/plugins/leader-run-store-sql.js +4 -0
  250. package/dist/plugins/local-checkpoint-store.d.ts +4 -1
  251. package/dist/plugins/local-checkpoint-store.js +3 -0
  252. package/dist/plugins/local-session-live-reference.d.ts +40 -0
  253. package/dist/plugins/local-session-live-reference.js +39 -0
  254. package/dist/plugins/local-session-store.d.ts +71 -33
  255. package/dist/plugins/local-session-store.js +129 -27
  256. package/dist/plugins/memory-engine-pg.js +4 -0
  257. package/dist/plugins/memory-engine-sql-apply.js +5 -2
  258. package/dist/plugins/memory-engine-tidb.js +4 -0
  259. package/dist/plugins/memory-optout-grant-store-sql.js +4 -0
  260. package/dist/plugins/memory-run-store.js +1 -1
  261. package/dist/plugins/memory-sync-store-pg.js +5 -0
  262. package/dist/plugins/memory-sync-store-tidb.js +5 -0
  263. package/dist/plugins/one-time-migrations.d.ts +80 -61
  264. package/dist/plugins/one-time-migrations.js +241 -104
  265. package/dist/plugins/org-delivery-quota-store.js +4 -1
  266. package/dist/plugins/outcome-ledger-sql.js +2 -0
  267. package/dist/plugins/permission-rule-store-sql.js +11 -4
  268. package/dist/plugins/pg-cost-quota.js +4 -0
  269. package/dist/plugins/pg-pool.js +28 -1
  270. package/dist/plugins/pg-rate-limiter.js +2 -0
  271. package/dist/plugins/posix-shell-fs.d.ts +6 -1
  272. package/dist/plugins/posix-shell-fs.js +8 -3
  273. package/dist/plugins/remote-env-adb.d.ts +19 -15
  274. package/dist/plugins/remote-env-adb.js +44 -17
  275. package/dist/plugins/remote-env-connect-seat.d.ts +105 -0
  276. package/dist/plugins/remote-env-connect-seat.js +72 -0
  277. package/dist/plugins/remote-env-device.d.ts +22 -5
  278. package/dist/plugins/remote-env-device.js +114 -14
  279. package/dist/plugins/remote-env-e2b.d.ts +18 -7
  280. package/dist/plugins/remote-env-e2b.js +53 -40
  281. package/dist/plugins/remote-env-file-error.js +6 -2
  282. package/dist/plugins/remote-env-host.d.ts +18 -1
  283. package/dist/plugins/remote-env-host.js +48 -47
  284. package/dist/plugins/remote-env-k8s.d.ts +41 -39
  285. package/dist/plugins/remote-env-k8s.js +56 -32
  286. package/dist/plugins/remote-env-local-docker.d.ts +13 -8
  287. package/dist/plugins/remote-env-local-docker.js +37 -43
  288. package/dist/plugins/remote-env-ssh.d.ts +18 -12
  289. package/dist/plugins/remote-env-ssh.js +64 -62
  290. package/dist/plugins/remote-shell.d.ts +101 -2
  291. package/dist/plugins/remote-shell.js +221 -3
  292. package/dist/plugins/replica-registration.d.ts +35 -0
  293. package/dist/plugins/replica-registration.js +48 -0
  294. package/dist/plugins/resume-anchor-store-sql.d.ts +11 -2
  295. package/dist/plugins/resume-anchor-store-sql.js +12 -5
  296. package/dist/plugins/retention-lane-store-sql.d.ts +1 -1
  297. package/dist/plugins/retention-lane-store-sql.js +4 -0
  298. package/dist/plugins/retention-sql.d.ts +20 -2
  299. package/dist/plugins/retention-sql.js +11 -0
  300. package/dist/plugins/run-store-sql.d.ts +22 -3
  301. package/dist/plugins/run-store-sql.js +33 -9
  302. package/dist/plugins/scenario-prefix-switch-m42.d.ts +6 -12
  303. package/dist/plugins/scenario-prefix-switch-m42.js +7 -5
  304. package/dist/plugins/schema-consistency.d.ts +9 -5
  305. package/dist/plugins/schema-consistency.js +48 -18
  306. package/dist/plugins/schema-drift-sentence.js +1 -1
  307. package/dist/plugins/send-file-ledger.js +3 -0
  308. package/dist/plugins/serving-requirement.d.ts +68 -0
  309. package/dist/plugins/serving-requirement.js +60 -0
  310. package/dist/plugins/session-birth.d.ts +6 -2
  311. package/dist/plugins/session-capture-record-store-sql.js +2 -0
  312. package/dist/plugins/session-ext-table.d.ts +14 -1
  313. package/dist/plugins/session-ext-table.js +5 -1
  314. package/dist/plugins/session-row-sql.d.ts +49 -2
  315. package/dist/plugins/session-row-sql.js +56 -13
  316. package/dist/plugins/session-store-sql.d.ts +34 -18
  317. package/dist/plugins/session-store-sql.js +98 -17
  318. package/dist/plugins/shared-memory-store-sql.d.ts +1 -0
  319. package/dist/plugins/shared-memory-store-sql.js +6 -2
  320. package/dist/plugins/sql-driver.d.ts +2 -1
  321. package/dist/plugins/sql-driver.js +18 -3
  322. package/dist/plugins/sql-errors.d.ts +11 -6
  323. package/dist/plugins/sql-errors.js +5 -6
  324. package/dist/plugins/stop-then-start-sentence.d.ts +48 -3
  325. package/dist/plugins/stop-then-start-sentence.js +48 -0
  326. package/dist/plugins/stop-then-start.d.ts +109 -0
  327. package/dist/plugins/stop-then-start.js +104 -0
  328. package/dist/plugins/store-backend.d.ts +40 -13
  329. package/dist/plugins/store-backend.js +169 -27
  330. package/dist/plugins/store-boundary.d.ts +57 -0
  331. package/dist/plugins/store-boundary.js +139 -0
  332. package/dist/plugins/store-contracts.d.ts +29 -2
  333. package/dist/plugins/store-contracts.js +3 -0
  334. package/dist/plugins/store-fault-sentence-m53.d.ts +7 -0
  335. package/dist/plugins/store-fault-sentence-m53.js +25 -0
  336. package/dist/plugins/store-fault.d.ts +26 -7
  337. package/dist/plugins/store-fault.js +18 -2
  338. package/dist/plugins/task-attachment-store.js +9 -0
  339. package/dist/plugins/task-list-store-sql.d.ts +2 -2
  340. package/dist/plugins/task-list-store-sql.js +10 -8
  341. package/dist/plugins/tidb-cost-quota.js +4 -0
  342. package/dist/plugins/tidb-pool.js +6 -1
  343. package/dist/plugins/tidb-rate-limiter.js +4 -0
  344. package/dist/plugins/user-input-ledger-sql.js +4 -0
  345. package/dist/plugins/workflow-run-store-sql.d.ts +28 -10
  346. package/dist/plugins/workflow-run-store-sql.js +64 -4
  347. package/dist/plugins/workspace-fill.d.ts +4 -7
  348. package/dist/plugins/workspace-fill.js +2 -1
  349. package/dist/plugins/write-behind-counter.js +5 -0
  350. package/dist/process-instance.d.ts +3 -0
  351. package/dist/process-instance.js +7 -0
  352. package/dist/project-context.d.ts +64 -0
  353. package/dist/project-context.js +66 -0
  354. package/dist/project-registry.d.ts +46 -0
  355. package/dist/project-registry.js +44 -0
  356. package/dist/question.d.ts +9 -21
  357. package/dist/question.js +28 -19
  358. package/dist/request-key-closure.js +1 -1
  359. package/dist/request-value-closure.d.ts +4 -0
  360. package/dist/request-value-closure.js +10 -0
  361. package/dist/run-acceptance.d.ts +3 -2
  362. package/dist/run-acceptance.js +4 -6
  363. package/dist/run-cancel-card.d.ts +1 -1
  364. package/dist/run-cancel-card.js +2 -1
  365. package/dist/run-local.js +1 -0
  366. package/dist/runs.d.ts +37 -8
  367. package/dist/runs.js +53 -12
  368. package/dist/runtime-governance.d.ts +5 -4
  369. package/dist/security.d.ts +31 -33
  370. package/dist/security.js +41 -7
  371. package/dist/server-secret-env.d.ts +12 -10
  372. package/dist/server-secret-env.js +24 -15
  373. package/dist/session-agent.d.ts +1 -10
  374. package/dist/session-agent.js +0 -6
  375. package/dist/session-bindings.d.ts +82 -0
  376. package/dist/session-bindings.js +18 -0
  377. package/dist/session-children-retire.d.ts +2 -2
  378. package/dist/session-children-retire.js +2 -6
  379. package/dist/session-deletion.d.ts +16 -1
  380. package/dist/session-error-wire.d.ts +3 -3
  381. package/dist/session-error-wire.js +3 -3
  382. package/dist/session-incarnation.d.ts +28 -4
  383. package/dist/session-incarnation.js +14 -2
  384. package/dist/session-kind.d.ts +57 -0
  385. package/dist/session-kind.js +22 -0
  386. package/dist/session-notify-door.d.ts +4 -4
  387. package/dist/session-notify-door.js +5 -6
  388. package/dist/session-row.d.ts +21 -1
  389. package/dist/session-row.js +7 -1
  390. package/dist/session-rules-seat.d.ts +4 -3
  391. package/dist/session-rules-seat.js +3 -11
  392. package/dist/session-sync-kernel.d.ts +24 -14
  393. package/dist/session-sync-kernel.js +3 -6
  394. package/dist/session-sync.d.ts +4 -98
  395. package/dist/session-sync.js +4 -74
  396. package/dist/session-titler.d.ts +10 -3
  397. package/dist/session-titler.js +19 -6
  398. package/dist/ssh-host-key.d.ts +5 -0
  399. package/dist/ssh-host-key.js +3 -0
  400. package/dist/stores-sql/checkpoint-store-sql.d.ts +21 -2
  401. package/dist/stores-sql/checkpoint-store-sql.js +106 -18
  402. package/dist/stores-sql/file-history-store-sql.d.ts +52 -2
  403. package/dist/stores-sql/file-history-store-sql.js +108 -70
  404. package/dist/stores-sql/pg-session-storage.d.ts +34 -7
  405. package/dist/stores-sql/pg-session-storage.js +37 -13
  406. package/dist/stores-sql/retention-store-sql.d.ts +2 -10
  407. package/dist/stores-sql/retention-store-sql.js +2 -10
  408. package/dist/stores-sql/session-policy-store-sql.d.ts +30 -7
  409. package/dist/stores-sql/session-policy-store-sql.js +61 -44
  410. package/dist/stores-sql/session-write-hooks.d.ts +11 -0
  411. package/dist/stores-sql/tidb-session-store.d.ts +58 -7
  412. package/dist/stores-sql/tidb-session-store.js +37 -13
  413. package/dist/submission-exit.d.ts +3 -2
  414. package/dist/submission-exit.js +9 -1
  415. package/dist/task-cwd.d.ts +6 -5
  416. package/dist/task-settings.d.ts +19 -5
  417. package/dist/task-settings.js +13 -7
  418. package/dist/terminal.d.ts +33 -2
  419. package/dist/terminal.js +139 -9
  420. package/dist/tool-approval.d.ts +147 -12
  421. package/dist/tool-approval.js +206 -109
  422. package/dist/trace/engine-notice-wire.d.ts +14 -0
  423. package/dist/trace/engine-notice-wire.js +18 -1
  424. package/dist/trace/project.d.ts +4 -3
  425. package/dist/trace/project.js +3 -2
  426. package/dist/trace/projection-table.d.ts +33 -2
  427. package/dist/trace/self-minted-wire.d.ts +422 -26
  428. package/dist/trace/self-minted-wire.js +149 -23
  429. package/dist/trace/tool-card.d.ts +3 -0
  430. package/dist/trace/tool-card.js +24 -0
  431. package/dist/trace/tool-output-media.d.ts +2 -1
  432. package/dist/unattended-permission-mode.d.ts +1 -1
  433. package/dist/web-admin-client/apply-effective.d.ts +1 -1
  434. package/dist/web-admin-client/effective-keys.d.ts +1 -1
  435. package/dist/web-admin-client/skills-mcp.d.ts +1 -1
  436. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +120 -41
  437. package/package.json +3 -3
  438. package/wire-changes/server@7.150.0.json +335 -0
  439. package/wire-changes/server@7.151.0.json +762 -0
  440. package/dist/http/session-inherit-env.d.ts +0 -36
  441. package/dist/http/session-inherit-env.js +0 -6
@@ -1,17 +1,20 @@
1
1
  import { declareWithheldEnv, hostChildEnv, inheritEnvPolicyProblem, inheritedHostEnv } from "@sema-agent/core";
2
- import { CONFIG_CATALOG } from "./config-catalog.js";
2
+ import { BAKE_RUNNER_CREDENTIAL_ENV, CONFIG_CATALOG } from "./config-catalog.js";
3
3
  import { parseApprovalHmacKeys, parseServiceAuthTokens } from "./auth-keys.js";
4
4
  import { ENV_NAME_ALLOWLIST_KNOB_NAMES } from "./env-name-allowlist-knobs.js";
5
5
  import { recordOwnCredentialValueNotWithheld, recordSecretEnvScrub } from "./observability/secret-env-scrub.js";
6
- export const CATALOG_SECRET_ENV_NAMES = new Set(CONFIG_CATALOG.filter((spec) => spec.type === "secret").map((spec) => spec.name));
6
+ const CREDENTIAL_FORM_OF = new Map([
7
+ ...CONFIG_CATALOG.flatMap((spec) => (spec.credentialForm === undefined ? [] : [[spec.name, spec.credentialForm]])),
8
+ ...Object.entries(BAKE_RUNNER_CREDENTIAL_ENV),
9
+ ]);
10
+ export const CREDENTIAL_ENV_NAMES = new Set([...CREDENTIAL_FORM_OF.keys()].sort());
7
11
  const NO_MODEL_ENTRIES = Object.freeze({});
8
12
  export function serverWithheldEnvNames(modelApiKeyEnv = NO_MODEL_ENTRIES) {
9
- return [...new Set([...CATALOG_SECRET_ENV_NAMES, ...ENV_NAME_ALLOWLIST_KNOB_NAMES, ...Object.values(modelApiKeyEnv)])].sort();
13
+ return [...new Set([...CREDENTIAL_ENV_NAMES, ...ENV_NAME_ALLOWLIST_KNOB_NAMES, ...Object.values(modelApiKeyEnv)])].sort();
10
14
  }
11
15
  export function serverCredentialValueSources(modelApiKeyEnv = NO_MODEL_ENTRIES) {
12
- return [...new Set([...CATALOG_SECRET_ENV_NAMES, ...Object.values(modelApiKeyEnv)])].sort();
16
+ return [...new Set([...CREDENTIAL_ENV_NAMES, ...Object.values(modelApiKeyEnv)])].sort();
13
17
  }
14
- const CREDENTIAL_FORM_OF = new Map(CONFIG_CATALOG.flatMap((spec) => (spec.credentialForm === undefined ? [] : [[spec.name, spec.credentialForm]])));
15
18
  const DROPPED_KEYS_TOLD_BY_LOAD_CONFIG = () => { };
16
19
  function credentialsIn(form, raw) {
17
20
  switch (form) {
@@ -21,6 +24,8 @@ function credentialsIn(form, raw) {
21
24
  return [raw, ...Object.keys(parseServiceAuthTokens(raw))];
22
25
  case "key-set":
23
26
  return [raw, ...parseApprovalHmacKeys(raw, DROPPED_KEYS_TOLD_BY_LOAD_CONFIG).map((k) => k.key)];
27
+ case "name-list":
28
+ return [];
24
29
  default: {
25
30
  const unreachable = form;
26
31
  throw new Error(`unhandled secret credential form: ${String(unreachable)}`);
@@ -32,15 +37,17 @@ let beforeLast;
32
37
  const valueRefusalAnnounced = new Set();
33
38
  let liveConfig;
34
39
  const envValueOf = (name) => process.env[name];
35
- function credentialsHeldBy(source) {
40
+ function credentialsHeldBy(source, keyEnvs) {
36
41
  const raw = envValueOf(source);
37
42
  if (raw === undefined || raw === "")
38
43
  return [];
39
- return [...new Set(credentialsIn(CREDENTIAL_FORM_OF.get(source) ?? "whole", raw))].filter((v) => v !== "");
44
+ const row = CREDENTIAL_FORM_OF.get(source);
45
+ const read = [...(row === undefined ? [] : credentialsIn(row, raw)), ...(keyEnvs.has(source) ? credentialsIn("whole", raw) : [])];
46
+ return [...new Set(read)].filter((v) => v !== "");
40
47
  }
41
- function heldValues(held) {
48
+ function heldValues(held, keyEnvs) {
42
49
  return [...held].flatMap(([source, at]) => {
43
- const all = credentialsHeldBy(source);
50
+ const all = credentialsHeldBy(source, keyEnvs);
44
51
  return [...at].flatMap((i) => {
45
52
  const value = all[i];
46
53
  return value === undefined ? [] : [value];
@@ -49,16 +56,17 @@ function heldValues(held) {
49
56
  }
50
57
  export function declareServerWithheldEnv(modelApiKeyEnv = NO_MODEL_ENTRIES) {
51
58
  const names = [...new Set([...(declared?.names ?? []), ...serverWithheldEnvNames(modelApiKeyEnv)])].sort();
59
+ const keyEnvs = new Set([...(declared?.keyEnvs ?? []), ...Object.values(modelApiKeyEnv)]);
52
60
  const held = new Map(declared?.held ?? []);
53
- declareWithheldEnv({ names, values: heldValues(held) });
61
+ declareWithheldEnv({ names, values: heldValues(held, keyEnvs) });
54
62
  for (const source of serverCredentialValueSources(modelApiKeyEnv)) {
55
63
  const at = new Set(held.get(source) ?? []);
56
64
  let refusal;
57
- credentialsHeldBy(source).forEach((_, i) => {
65
+ credentialsHeldBy(source, keyEnvs).forEach((_, i) => {
58
66
  if (at.has(i))
59
67
  return;
60
68
  try {
61
- declareWithheldEnv({ names, values: heldValues(new Map(held).set(source, new Set([...at, i]))) });
69
+ declareWithheldEnv({ names, values: heldValues(new Map(held).set(source, new Set([...at, i])), keyEnvs) });
62
70
  at.add(i);
63
71
  held.set(source, new Set(at));
64
72
  }
@@ -72,11 +80,11 @@ export function declareServerWithheldEnv(modelApiKeyEnv = NO_MODEL_ENTRIES) {
72
80
  }
73
81
  }
74
82
  beforeLast = declared;
75
- declared = { names: new Set(names), held };
83
+ declared = { names: new Set(names), held, keyEnvs };
76
84
  return names;
77
85
  }
78
86
  export function withdrawServerWithheldEnv() {
79
- declareWithheldEnv({ names: [...(beforeLast?.names ?? [])], values: heldValues(beforeLast?.held ?? new Map()) });
87
+ declareWithheldEnv({ names: [...(beforeLast?.names ?? [])], values: heldValues(beforeLast?.held ?? new Map(), beforeLast?.keyEnvs ?? new Set()) });
80
88
  declared = beforeLast;
81
89
  }
82
90
  export function bindOwnCredentialsConfig(config) {
@@ -102,7 +110,8 @@ export function ownCredentialValuesWithheld() {
102
110
  if (declared === undefined || liveConfig === undefined)
103
111
  return false;
104
112
  const held = declared.held;
105
- return serverCredentialValueSources(liveConfig.modelApiKeyEnv).every((source) => (held.get(source)?.size ?? 0) === credentialsHeldBy(source).length);
113
+ const keyEnvs = new Set([...declared.keyEnvs, ...Object.values(liveConfig.modelApiKeyEnv)]);
114
+ return serverCredentialValueSources(liveConfig.modelApiKeyEnv).every((source) => (held.get(source)?.size ?? 0) === credentialsHeldBy(source, keyEnvs).length);
106
115
  }
107
116
  export function ownCredentialVariable(name) {
108
117
  if (inheritEnvPolicyProblem([name]) !== undefined)
@@ -5,7 +5,7 @@
5
5
  * 店原样记下,首写不可变。三只持久会话店都存:SQL 两孪生在 `session_meta` 的 `placement_*` 列(`plugins/session-placement.ts` 的 `placementFromRow`),
6
6
  * local 后端(7.141.0 起)在会话存档行头(core 文件 repo)。读口是店的 `placementOf`(一行 PK 探针;店不交它 = 不存元组)。
7
7
  *
8
- * 读者(同一只读口 {@link readSessionAgent}、同一只投影 {@link sessionAgentOf},逐值同答):
8
+ * 读者(同一只读口 —— 属主存取器的 `readSessionAgent`(`http/owner-access.ts`:店的行读只在存取器里)—— 同一只投影 {@link sessionAgentOf},逐值同答):
9
9
  * · 会话视图 `GET /v1/sessions/:id` 体顶层的 `agent`(视图读才付探针;探针抛 ⇒ 视图读响亮失败,`boot/session-faces.ts`);
10
10
  * · 运维审批队列 `GET /v1/approvals` 的停驻行(`pending[]` 的 `checkpoint` 族)与 `/v1/approvals/stream` 的 `pending` 帧:行的身份就是它那只会话
11
11
  * (决断口 `/v1/approvals/:sessionId/decide`),行上的 `agent` = 同一只会话在视图上的 `agent`;一行读不出 ⇒ 只这一行缺键、F 类兜底计数
@@ -26,15 +26,6 @@ export interface SessionAgent {
26
26
  parentSessionId?: string;
27
27
  rootSessionId?: string;
28
28
  }
29
- /** 交委派元组读口的会话店面(本仓三只持久会话店与缓存包装层都交;内存店不交)。 */
30
- export interface PlacementReadingSessionStore {
31
- readonly placementOf?: (sessionId: string) => Promise<SessionPlacementRecord | undefined>;
32
- }
33
29
  /** {@link SessionAgent} 的唯一投影:店答出的委派元组 → `agent` 的值;`undefined`(普通会话 / 店没有这一面)⇒ 调用方不铸键。 */
34
30
  export declare function sessionAgentOf(placement: SessionPlacementRecord | undefined): SessionAgent | undefined;
35
- /**
36
- * `agent` 的**唯一读口**:店的 `placementOf` 一读 → {@link sessionAgentOf}。店不交 `placementOf` ⇒ `undefined`(这台部署不存元组,不探)。
37
- * 探针抛 ⇒ 原样上抛 —— 读不出怎么说归读者(视图读响亮失败;队列只缺那一行的键并计数),本函数不替任何一面把故障说成「不是子代」。
38
- */
39
- export declare function readSessionAgent(store: PlacementReadingSessionStore | undefined, sessionId: string): Promise<SessionAgent | undefined>;
40
31
  //# sourceMappingURL=session-agent.d.ts.map
@@ -7,10 +7,4 @@ export function sessionAgentOf(placement) {
7
7
  ...(placement.rootSessionId !== undefined ? { rootSessionId: placement.rootSessionId } : {}),
8
8
  };
9
9
  }
10
- export async function readSessionAgent(store, sessionId) {
11
- const placementOf = store?.placementOf;
12
- if (placementOf === undefined)
13
- return undefined;
14
- return sessionAgentOf(await placementOf.call(store, sessionId));
15
- }
16
10
  //# sourceMappingURL=session-agent.js.map
@@ -0,0 +1,82 @@
1
+ /**
2
+ * **会话绑定** —— 一次提交写在会话上的三格进程内事实(工作目录 · shell 环境 · 继承策略;host / device 工厂在 run 起跑那一拍按会话键现读)的唯一律。
3
+ *
4
+ * ## 律
5
+ * 会话绑定是**被受理的 run** 的事实,不是请求的事实:
6
+ * · **判在写之前** —— 装配器(`boot/resolve-spec.ts`)只判、只算这条腿要写的那一份({@link SessionBindings},随部署事实 `LegFacts.sessionBindings` 走);
7
+ * 工作目录那一格 = 这条腿**跑在**的那一枚(请求带的 ?? 项目继承来的 ?? 会话上已登记的),装配器自己的读者(hooks 的工作目录、真任务根、写门基准、组合腿的根)
8
+ * 与起跑时的工厂读的是同一枚 —— 提交点把它原样写进会话,装配读与起跑读之间别的提交的写改不了这条腿的落点;
9
+ * · **一个写点** —— run 认领之后、起跑之前的唯一提交点 {@link commitLegBindings}(四个认领点:流式提交 / 同步提交 / durable 建行腿 / 续跑驱动腿;
10
+ * 类级机器门 `test/inherit-env-request-key.test.ts`)。装配器之后、认领之前的一切拒(装配期的拒、路由层的建行 409 / placement / 续跑输入 / 起跑前复核)零写;
11
+ * · **写在判之后的,同一只撤回** —— 写了之后才收场 `refused` 的提交(引擎零工作的拒、受理之前取消)由提交出口(`submission-exit.ts`)按本次的回执撤回;
12
+ * 受理 / record 的落定。登记簿记的是「已落定的底 + 还没落定的各笔(按提交序)」,三张表恒是它的物化:撤回只抽掉这一笔、重新物化 —— 别的提交的写原样、原序,
13
+ * 两笔都被撤就回到底(不会把一笔被拒的写当成另一笔的「写之前」还原回来);围栏清过 / 会话删过 ⇒ 回执一笔不动。
14
+ * 行判撤的提交另由出口按住客清掉全部条目(与 `DELETE` 同一组,既有)。没有出口座的腿(续跑驱动腿 · 后台建行腿:认领即 record)写即落定。
15
+ *
16
+ * 一条被拒的提交因此不留任何它写下的会话绑定 —— 请求自带的 `cwd`、项目继承来的第一条 `folder`、`settings.env`、`inheritEnv` 同一条律,
17
+ * 与会话行(提交出口)、请求形的拒(`request-form.ts`,在铸点之前答)同一个「拒后零残留」。
18
+ *
19
+ * ## 三格的缺席语义(各自原样)
20
+ * · `cwd`:缺席 = 这条腿没有工作目录(请求没带、没继承、会话上也没登记)⇒ 不动;
21
+ * · `shellEnv`:缺席 = 不动(粘住上一条受理的 —— 壳每条请求重发,粘住无害;装配器不读这一格);
22
+ * · `inheritEnv`:缺席 = 清(缺省清洗 —— 粘住 = 替一个没说话的请求放宽凭据面;理由在 `boot/execution-env.ts` 的登记簿注)。
23
+ * 装配器没铸事实(嵌入方自带的装配器)⇒ 按「什么都没要」写:`inheritEnv` 清、其余不动(安全轴 fail-closed 的那一侧)。
24
+ *
25
+ * ## 残余(如实)
26
+ * · 登记簿仍按**会话**键控、工厂在起跑那一刻现读(core 的执行环境工厂上下文只带 sessionId / taskId,没有 per-run 座):有 run 店的部署上认领串行化同会话的 run,
27
+ * 「写 → 读」落在同一条认领窗里;没有 run 店的部署上同会话并发受理的两条 run 仍是「最后写者赢」。
28
+ * · 续跑腿没有提交出口:它在 markResuming 赢之后写**那条停驻任务自己**盘上的值(不是别的请求的);core 的 pre-CAS 守卫在那之后才拒的续跑照样留着它,
29
+ * 下一条受理的 run 照写覆盖。
30
+ * · 登记簿是每副本进程内的(围栏与清除只在处理该请求的副本上发生),见 `createSessionScopedRegistries` 头注。
31
+ */
32
+ import type { TaskInheritEnv } from "./request-value-closure.js";
33
+ /** 一条腿要写在会话上的绑定(装配器判出的那一份;提交点原样写)。缺席语义见本文件头注。 */
34
+ export interface SessionBindings {
35
+ /** 这条腿跑在的工作目录(请求带的 ?? 项目继承来的 ?? 会话上已登记的;前两者只在车道能力 `callerCwd` 成立且是宿主绝对路径时算数)。缺席 = 不动。 */
36
+ readonly cwd?: string;
37
+ /** 请求的 `settings.env`(只在 `callerCwd` 成立时在场)。缺席 = 不动。 */
38
+ readonly shellEnv?: Readonly<Record<string, string>>;
39
+ /** 请求的 `inheritEnv`(装配器判过值形 / 车道 / 射程)。缺席 = 清。 */
40
+ readonly inheritEnv?: TaskInheritEnv;
41
+ }
42
+ /**
43
+ * 三格的**唯一铸法**:在场(≠ `undefined`)的格才出键,缺席的格不出键。本函数只答「缺席 = 没有这个键」,不替任何一格选缺省 —— 每一格缺席读作什么见上面头注,由各读者按那一条读。
44
+ * 三个调用点同用:装配器算这条腿的绑定(`boot/resolve-spec.ts`)、登记簿读一份当下的三格、登记簿把一笔写叠在一份读数之上(`boot/execution-env.ts`)。
45
+ * 此前各写一遍三条件展开,`inheritEnv` 这个键在三处各被拼一次;现在这个键的属性字面量在 src 只此一处(类级门 `test/secret-env-scrub-host-legs.test.ts` 的 [ref] 格数的就是它)。
46
+ * `shellEnv` 的型随调用点(装配器交只读的、登记簿的表里是可变的)。
47
+ */
48
+ export declare function bindingsOf<E extends Readonly<Record<string, string>>>(cwd: string | undefined, shellEnv: E | undefined, inheritEnv: TaskInheritEnv | undefined): {
49
+ readonly cwd?: string;
50
+ readonly shellEnv?: E;
51
+ readonly inheritEnv?: TaskInheritEnv;
52
+ };
53
+ /** 一笔提交的回执(撤回 / 落定只认这一笔)。 */
54
+ export interface SessionBindingReceipt {
55
+ readonly sessionId: string;
56
+ /** 这一笔的回执号。 */
57
+ readonly token: symbol;
58
+ }
59
+ /** 登记簿的写座(`boot/execution-env.ts` `createSessionScopedRegistries` 铸;HTTP 面经 `ServiceDeps.sessionBindings` 拿到)。 */
60
+ export interface SessionBindingSeat {
61
+ /** 写一笔(唯一调用者 = {@link commitLegBindings}),交回回执。 */
62
+ commitSessionBindings(sessionId: string, bindings: SessionBindings): SessionBindingReceipt;
63
+ /** 撤回一笔:这一笔还没落定 ⇒ 抽掉它、三格重新物化(别的提交的写原样)、答 `true`;否则(已落定 / 已撤 / 清过)一笔不动、答 `false`。 */
64
+ withdrawSessionBindings(receipt: SessionBindingReceipt): boolean;
65
+ /** 落定一笔(这次提交被受理 / 交给了它自己的耐久 run):此后不可撤。已撤 / 清过 ⇒ 答 `false`。 */
66
+ settleSessionBindings(receipt: SessionBindingReceipt): boolean;
67
+ }
68
+ /** 提交点读的那一面:写座(缺席 = 夹具 / 嵌入方没接登记簿 ⇒ no-op)。 */
69
+ export interface LegBindingsCommitCtx {
70
+ readonly sessionBindings?: SessionBindingSeat | undefined;
71
+ }
72
+ /** 提交出口收回执的那一面(`submission-exit.ts` 的 `SubmissionSeat.noteBindings`):收场 `refused` ⇒ 撤回,`accepted` / `record` ⇒ 落定。 */
73
+ export interface BindingReceiptSink {
74
+ noteBindings(receipt: SessionBindingReceipt, face: Pick<SessionBindingSeat, "withdrawSessionBindings" | "settleSessionBindings">): void;
75
+ }
76
+ /**
77
+ * **唯一提交点**:在 run 认领(与执行放置、续跑输入、起跑前复核)之后、起跑之前调一次 —— 把这条腿的绑定写进它的根会话,回执交给这次提交的出口座
78
+ * (同步 / 流式两条提交腿:收场定撤还是落定);`exit` 缺席(续跑驱动腿没有座;后台建行腿认领即 record,之后不再有拒)⇒ 写即落定。
79
+ * `bindings` 缺席(装配器没铸事实)⇒ 按「什么都没要」写。
80
+ */
81
+ export declare function commitLegBindings(ctx: LegBindingsCommitCtx, exit: BindingReceiptSink | undefined, sessionId: string, bindings: SessionBindings | undefined): void;
82
+ //# sourceMappingURL=session-bindings.d.ts.map
@@ -0,0 +1,18 @@
1
+ export function bindingsOf(cwd, shellEnv, inheritEnv) {
2
+ return {
3
+ ...(cwd !== undefined ? { cwd } : {}),
4
+ ...(shellEnv !== undefined ? { shellEnv } : {}),
5
+ ...(inheritEnv !== undefined ? { inheritEnv } : {}),
6
+ };
7
+ }
8
+ export function commitLegBindings(ctx, exit, sessionId, bindings) {
9
+ const seat = ctx.sessionBindings;
10
+ if (seat === undefined)
11
+ return;
12
+ const receipt = seat.commitSessionBindings(sessionId, bindings ?? {});
13
+ if (exit !== undefined)
14
+ exit.noteBindings(receipt, seat);
15
+ else
16
+ seat.settleSessionBindings(receipt);
17
+ }
18
+ //# sourceMappingURL=session-bindings.js.map
@@ -89,8 +89,8 @@ export type RetireSessionChildrenOutcome = {
89
89
  };
90
90
  /**
91
91
  * 一只会话的**引擎租户分区** —— **唯一一处取**:以它为根的后台子代、它的后台 shell、它的会话信箱盒,都登记在这一分区(删除门、换绑 / 导入两门、结清口、
92
- * 删除协调器的信箱腿与 shell 收割腿、删后收尾的丢箱同读;属主串本身不是 scope)。引擎按任务规格的身份格登记,所以这里读的是**引擎交界**
93
- * (`engine-identity.ts` 的 `taskSpecIdentityOf`)从会话属主恢复出的那一格:没带场景的会话 = 属主(逐字节同改前);带场景的会话(属主 `_scn:<场景>:<人>`)=
92
+ * 删除协调器的信箱腿与 shell 收割腿、删后收尾的丢箱同读;属主串本身不是 scope)。引擎按任务规格的身份格登记,所以这里读的是**引擎身份那一格**
93
+ * (`engine-identity.ts` 的 `engineScopeOfOwner`,唯一换算):没带场景的会话 = 属主(逐字节同改前);带场景的会话(属主 `_scn:<场景>:<人>`)=
94
94
  * 引擎登记时用的那一个值(今天是人)—— 按属主串去枚举 / 退役 / 收割会打到一个空分区。无主 ⇒ `"default"`。
95
95
  */
96
96
  export declare function sessionTenantScope(owner: string | null): string;
@@ -1,13 +1,9 @@
1
- import { partsOf } from "./owner-brands.js";
2
- import { recoveredSubject } from "./owner-faces.js";
3
- import { taskSpecIdentityOf } from "./engine-identity.js";
1
+ import { engineScopeOfOwner } from "./engine-identity.js";
4
2
  import { expireCardUnderStoredScope } from "./card-settle-stored-scope.js";
5
3
  export const RETIRE_MAX_ROUNDS = 6;
6
4
  const RETIRE_BACKOFF_MS = [0, 25, 50, 100, 200, 400];
7
5
  export function sessionTenantScope(owner) {
8
- if (owner === null)
9
- return "default";
10
- return taskSpecIdentityOf(partsOf(recoveredSubject(owner))).principal ?? "default";
6
+ return engineScopeOfOwner(owner);
11
7
  }
12
8
  async function liveChildren(deps, rootSessionId, scope) {
13
9
  const out = new Map();
@@ -20,6 +20,7 @@
20
20
  * 持有者已死的在删行,重发的 DELETE 同样是接管。
21
21
  * 持久面:SQL = 旁表 `session_ext.deleting_token`(列属主 `plugins/session-ext-table.ts`);local = 会话元数据边档那一格的 `deleting`。
22
22
  */
23
+ import type { SessionKind } from "./session-kind.js";
23
24
  /** 围栏的回执:这一次删除的令牌 + 被删的那一位住客的化身(空间回收的键;存量行没有化身 ⇒ `undefined`)。 */
24
25
  export interface SessionDeletionTicket {
25
26
  readonly token: string;
@@ -36,10 +37,24 @@ export interface PendingSessionDeletion {
36
37
  * (某腿失败 / 被接管)—— 死的;`elsewhere` = 不是本进程铸的(上一个进程 / 别的副本)。
37
38
  */
38
39
  export type DeletionHolder = "running" | "ended" | "elsewhere";
39
- /** 围栏的选项:`holder` = 令牌持有者在哪(协调器的在飞表);`expect` = 只接管这一只令牌(收尾者;活行 / 别的令牌 ⇒ `undefined`)。 */
40
+ /**
41
+ * 老化的条件(会话种类的律在 `session-kind.ts`;唯一调用者 = 维护拍的老化腿 `boot/session-age-out.ts`):候选读只挑人,**判官是围栏根行锁里的这一判** ——
42
+ * 对一只**活**行,锁住根行之后、写令牌之前再判:住客仍是候选读到的那一位(`incarnation`:候选读之后同 id 被删并重登记的新住客不被碰)∧ 种类仍是 `kind`
43
+ * ∧ 最后活动仍早于 `idleBefore`(候选读之后一次 run / 追加 / 收场把它推前 ⇒ 不删)∧ 当下没有活引用(在跑的 run 的认领 —— 围栏本来就判 —— / 待决的检查点 /
44
+ * 在跑或停驻的后台子代以它为会话 · 父 · 根 / 它发起的在跑 workflow;SQL 两孪生与托管留存同读一只谓词)∧ 所在域不在保全中(SQL:托管留存的保全行锁)。
45
+ * 任一不成立 ⇒ 回滚、`undefined`,一个字节不写。在删行(一次失败的删除撂下的)照常按持有者判接管 —— 它已经在删,不回到活。
46
+ * 条件与收尾者的 `expect` 同位:一只围栏、一个可选条件,不是第二条删除路;`DELETE /v1/sessions/:id` 不带它。
47
+ */
48
+ export interface SessionAgeOutExpectation {
49
+ readonly incarnation: string | undefined;
50
+ readonly kind: SessionKind;
51
+ readonly idleBefore: Date;
52
+ }
53
+ /** 围栏的选项:`holder` = 令牌持有者在哪(协调器的在飞表);`expect` = 只接管这一只令牌(收尾者;活行 / 别的令牌 ⇒ `undefined`);`ageOut` = 老化的锁内条件({@link SessionAgeOutExpectation})。 */
40
54
  export interface SessionDeletionFenceOptions {
41
55
  readonly holder: (token: string) => DeletionHolder;
42
56
  readonly expect?: string;
57
+ readonly ageOut?: SessionAgeOutExpectation;
43
58
  }
44
59
  /** 围栏的答复:回执(本次立了 / 接管了)· `inProgress`(一次仍可能活着的删除持有这一行 —— 不接管)· `undefined`(行不在 / 属主不是这一位 / 收尾者的令牌对不上)。 */
45
60
  export type SessionDeletionFenceAnswer = SessionDeletionTicket | {
@@ -42,8 +42,8 @@
42
42
  * (请求 core 把种类放进错误,而不是在这里解析句子)。
43
43
  * · `invalid_entry` / `invalid_fork_target` —— 留白:本仓今天没有一条 wire 口把它们作为自己的
44
44
  * 应答(它们在 core 的追加 / 分叉面上抛,落进各站点既有的处置或通用 500)。给它们起名是另一件事、另一张票。
45
- * · `conflict` —— `import` 面 **409 `conflict`**(固定句 {@link STAGED_IMPORT_OWNER_CHANGED_SENTENCE});`open` 面留白。按码映射时 import 面上这个词只有一个来源:
46
- * 暂存提交的属主 CAS(`session-sync-kernel.ts` 的 `StagedCommitOwnerChangedError`,三家店在提交事务里比「此刻的属主格 = 这次导入的门判过的那一格」,
45
+ * · `conflict` —— `import` 面 **409 `conflict`**(固定句 {@link STAGED_IMPORT_OCCUPANT_CHANGED_SENTENCE});`open` 面留白。按码映射时 import 面上这个词只有一个来源:
46
+ * 暂存提交的住客 CAS(`session-sync-kernel.ts` 的 `StagedCommitOccupantChangedError`,三家店在提交事务里比「此刻的行 = 这次导入的门判过的那一位住客」(属主 ∧ 化身),
47
47
  * 不等 ⇒ 回滚)—— 码位与同族的提交期同步冲突(`SyncConflictError` ⇒ 409 `conflict`「sync conflict」)同一个,出路也相同:从第一阶段重来(重新过门)。
48
48
  * 本服务自铸的同码具名拒 {@link StampedSessionArchiveError}(local 店:存档仍带更早版本写下的属主戳)不按码映射 —— 出路不同(重来照样撞),它有**自己的 wire 码**:
49
49
  * 由 {@link sessionErrorWireOf} 按**型**先认:两面同答 409 `conflict.session_archive_stamped` + 固定句 {@link STAMPED_SESSION_ARCHIVE_SENTENCE}(与上一句的属主变更拒同状态、不同码:
@@ -90,7 +90,7 @@ export declare const PLACED_SESSION_SENTENCE = "this session holds a delegated a
90
90
  * import 面 `conflict` 的固定句:暂存提交时会话的属主格已不是开暂存时门判过的那一格(另一副本在导入流式进行期间删建 / 认领 / 新建了它),提交事务回滚。
91
91
  * 不发店的原句(它点名会话 id);固定句只说发生了什么与出路(冻结在 `test/api-error-text-freeze.test.ts` 的常量锚格)。
92
92
  */
93
- export declare const STAGED_IMPORT_OWNER_CHANGED_SENTENCE = "session owner changed while the import streamed; nothing was imported \u2014 start the sync again";
93
+ export declare const STAGED_IMPORT_OCCUPANT_CHANGED_SENTENCE = "session changed hands while the import streamed (deleted, re-created or re-owned); nothing was imported \u2014 start the sync again";
94
94
  /**
95
95
  * local 店的具名拒(唯一铸点 `plugins/local-session-store.ts` 的 `assertArchiveAnonymous`):这只会话的引擎存档仍带更早版本写下的属主戳(一次性迁移 M33 改写不了它,或数据根跳过了带这次迁移的版本)
96
96
  * ⇒ 不在它上面造新存档(fork),也不原地换它的日志(改日志的推送,含第一阶段对 fork / stale 的早拒);零写。`SessionError.code` 是 core 闭集的 `conflict`;句子(给运维日志,点名会话 id)归本错,
@@ -2,7 +2,7 @@ import { SessionError } from "@sema-agent/core";
2
2
  export const STAGED_IMPORT_INVALID_SENTENCE = "staged session log failed validation";
3
3
  export const PLACED_SESSION_SENTENCE = "this session holds a delegated agent's transcript, so session sync cannot overwrite it; sync into a different session id";
4
4
  const PLACEMENT_KIND = "subagent";
5
- export const STAGED_IMPORT_OWNER_CHANGED_SENTENCE = "session owner changed while the import streamed; nothing was imported — start the sync again";
5
+ export const STAGED_IMPORT_OCCUPANT_CHANGED_SENTENCE = "session changed hands while the import streamed (deleted, re-created or re-owned); nothing was imported — start the sync again";
6
6
  export class StampedSessionArchiveError extends SessionError {
7
7
  sessionId;
8
8
  constructor(sessionId) {
@@ -23,7 +23,7 @@ export const STAMPED_SESSION_ARCHIVE_SENTENCE = "this session's stored archive s
23
23
  const CORRUPT_SESSION = { status: 500, errorCode: "corrupt_session" };
24
24
  const INVALID_ENTRIES = { status: 422, errorCode: "invalid_entries", sentence: STAGED_IMPORT_INVALID_SENTENCE };
25
25
  const SESSION_PLACED = { status: 409, errorCode: "conflict.session_placed", sentence: PLACED_SESSION_SENTENCE, facts: { placement_kind: PLACEMENT_KIND } };
26
- const STAGED_IMPORT_OWNER_CHANGED = { status: 409, errorCode: "conflict", sentence: STAGED_IMPORT_OWNER_CHANGED_SENTENCE };
26
+ const STAGED_IMPORT_OCCUPANT_CHANGED = { status: 409, errorCode: "conflict", sentence: STAGED_IMPORT_OCCUPANT_CHANGED_SENTENCE };
27
27
  const STAMPED_SESSION_ARCHIVE = { status: 409, errorCode: "conflict.session_archive_stamped", sentence: STAMPED_SESSION_ARCHIVE_SENTENCE };
28
28
  export function sessionErrorWireOf(e, face) {
29
29
  return e instanceof StampedSessionArchiveError ? STAMPED_SESSION_ARCHIVE : sessionErrorHttp(e.code, face);
@@ -44,7 +44,7 @@ export function sessionErrorHttp(code, face) {
44
44
  case "placement_refused":
45
45
  return face === "import" ? SESSION_PLACED : undefined;
46
46
  case "conflict":
47
- return face === "import" ? STAGED_IMPORT_OWNER_CHANGED : undefined;
47
+ return face === "import" ? STAGED_IMPORT_OCCUPANT_CHANGED : undefined;
48
48
  case "not_found":
49
49
  case "invalid_entry":
50
50
  case "invalid_fork_target":
@@ -73,6 +73,8 @@ export declare function incarnationLogPrefix(incarnation: string): string;
73
73
  * 把其中每一只化身形的串截成 {@link incarnationLogPrefix}(前 8 位 + `…`)。规则只有一条:完整令牌不进日志正文;前 8 位留着对账。
74
74
  */
75
75
  export declare function redactIncarnations(text: string): string;
76
+ /** {@link SessionIncarnationMissingError} 的码(读到空化身的那一拒;k8s 车道按它把住客读拒分成立定的一形)。 */
77
+ export declare const SESSION_INCARNATION_MISSING = "session.incarnation_missing";
76
78
  /**
77
79
  * 会话行在、化身却是空的 —— 响亮拒(头注「读到空化身」一条)。具名类型:调用方按类型认它,不按文案。
78
80
  * 文案不带任何令牌(本来就是空的),只点名会话 id 与出路。
@@ -100,6 +102,14 @@ export declare function incarnationFromCell(sessionId: string, cell: unknown, em
100
102
  /** 一行原始列 → {@link SessionFace}(属主 + 一只令牌)的唯一口:化身那一格经 {@link incarnationFromCell} 的 `refuse` 读法(空 ⇒ 响亮拒)。
101
103
  * 按 id 的读者经 {@link sessionFaceOfHead};批量来源读(一次性迁移 M23 窗内的回填扫描)与 staged 换装的回读直接从行列经它。 */
102
104
  export declare function sessionFaceFromRow(sessionId: string, owner: string | null, incarnation: unknown): SessionFace;
105
+ /**
106
+ * 门承认的那一位住客在门后读的半途不再占着这只 id(删了、或删后同 id 被重建 —— 包括同一属主)。会话同步的拉取流在每页交出之前复判住客,不是那一位 ⇒ 抛它,
107
+ * 流在那里结束、不写尾行(客户端读作截断,重拉)—— 从不交出别一代住客的条目。不上 wire(流头已发,状态码改不了),只落一行运维 info。
108
+ */
109
+ export declare class SessionOccupantChangedError extends Error {
110
+ readonly sessionId: string;
111
+ constructor(sessionId: string);
112
+ }
103
113
  /**
104
114
  * 头的叶子那一格读不出 —— 会话**内容**读不出时的那只故障(local 店:会话存档读不出,例如存档首行的会话头坏了;行上的属主与住客照样读得出)。
105
115
  * {@link headFromRow} 收它:头照答属主与住客,叶子那一格带着这只故障,读 `leafId` 的那一位收到它本身(同一只错误对象,码与句子原样 ——
@@ -129,14 +139,28 @@ export declare function sessionFaceOfHead(sessionId: string, head: SessionHead):
129
139
  export declare function sessionFaceOfHead(sessionId: string, head: SessionHead | undefined): SessionFace | undefined;
130
140
  /**
131
141
  * 「这只会话店有没有按 id 读(`headOf`)」—— 全仓**只判这一处**:授权口、各路由的属主门、能力位、起服门、k8s 工作区空间的每 run 读与
132
- * 一次性迁移 M23(窗内)的回填读的都是这一只返回值。缺席 = 店没有实装 `headOf`(读不出属主 / 住客 / 叶子,调用方各按自己的 fail-closed 臂处置)。
142
+ * 一次性迁移 M23(窗内)的回填读的都是这一只判({@link headReadOf} 的在不在 = 它)。缺席 = 店没有实装 `headOf`(读不出属主 / 住客 / 叶子,调用方各按自己的 fail-closed 臂处置)。
143
+ * 收的是任意店形(路由层的封住视图也行:在不在照判,读口在型上调不了 —— 带属主的行只经属主存取器读,`http/owner-access.ts`)。
133
144
  */
134
- export declare function headReadOf(store: object | undefined): HeadRead | undefined;
145
+ export declare function headReadPresent(store: {
146
+ readonly headOf?: unknown;
147
+ } | undefined): boolean;
148
+ /** 会话店的按 id 读(绑好宿主的那一只;店没有 ⇒ `undefined`)。路由层的封住视图在这里读不出读口(封住的那一格型是 `undefined`,类型墙,`route-ctx.ts` 的 `RouteDeps`)。 */
149
+ export declare function headReadOf(store: {
150
+ readonly headOf?: HeadRead;
151
+ } | undefined): HeadRead | undefined;
135
152
  /**
136
153
  * 删除门(`DELETE /v1/sessions/:id` 的属主门 + 协调器的化身围栏)的头读 —— **只判这一处**:店交了 `deletionHeadOf`(删除已开始、还没收完的那一行也答得出属主与住客;local)⇒ 它;
137
- * 否则 ⇒ {@link headReadOf}(删除是一个事务的店,没有删到一半的行)。缺席 = 店没有按 id 读。
154
+ * 否则 ⇒ {@link headReadOf}(删除是一个事务的店,没有删到一半的行)。缺席 = 店没有按 id 读。同 {@link headReadOf}:只收值上交读口的店形。
138
155
  */
139
- export declare function deletionHeadReadOf(store: object | undefined): HeadRead | undefined;
156
+ export declare function deletionHeadReadOf(store: {
157
+ readonly deletionHeadOf?: HeadRead;
158
+ readonly headOf: HeadRead;
159
+ }): HeadRead;
160
+ export declare function deletionHeadReadOf(store: {
161
+ readonly deletionHeadOf?: HeadRead;
162
+ readonly headOf?: HeadRead;
163
+ } | undefined): HeadRead | undefined;
140
164
  /** 换装沿用的行格(化身 + fork 键):{@link carriedRowCells} 的答案。`forkKey: null` = 没有可沿用的键(新建行 / 行上本来没有)。 */
141
165
  export interface CarriedRowCells {
142
166
  readonly incarnation: string;
@@ -12,9 +12,10 @@ const INCARNATION_TOKEN_SHAPE = /[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9
12
12
  export function redactIncarnations(text) {
13
13
  return text.replace(INCARNATION_TOKEN_SHAPE, (token) => `${incarnationLogPrefix(token)}…`);
14
14
  }
15
+ export const SESSION_INCARNATION_MISSING = "session.incarnation_missing";
15
16
  export class SessionIncarnationMissingError extends Error {
16
17
  sessionId;
17
- code = "session.incarnation_missing";
18
+ code = SESSION_INCARNATION_MISSING;
18
19
  constructor(sessionId) {
19
20
  super(`session ${sessionId} has no incarnation token: every session row is minted one when it is created. An empty value means a write path ` +
20
21
  `that did not mint one, a hand-edited row, or a database upgraded from before 7.104.0 straight to a version after 7.135.x (a boot of any ` +
@@ -41,6 +42,14 @@ export function incarnationFromCell(sessionId, cell, empty = "refuse") {
41
42
  export function sessionFaceFromRow(sessionId, owner, incarnation) {
42
43
  return { owner, incarnation: incarnationFromCell(sessionId, incarnation) };
43
44
  }
45
+ export class SessionOccupantChangedError extends Error {
46
+ sessionId;
47
+ constructor(sessionId) {
48
+ super(`session ${sessionId}: the occupant the gate admitted no longer holds this id — the stream ends here`);
49
+ this.sessionId = sessionId;
50
+ this.name = "SessionOccupantChangedError";
51
+ }
52
+ }
44
53
  export class UnreadableLeaf {
45
54
  fault;
46
55
  constructor(fault) {
@@ -66,9 +75,12 @@ export function leafOfAdmittedHead(head) {
66
75
  export function sessionFaceOfHead(sessionId, head) {
67
76
  return head === undefined ? undefined : sessionFaceFromRow(sessionId, head.owner, head.incarnation);
68
77
  }
78
+ export function headReadPresent(store) {
79
+ return typeof store?.headOf === "function";
80
+ }
69
81
  export function headReadOf(store) {
70
82
  const read = store?.headOf;
71
- return typeof read === "function" ? read.bind(store) : undefined;
83
+ return headReadPresent(store) ? read.bind(store) : undefined;
72
84
  }
73
85
  export function deletionHeadReadOf(store) {
74
86
  const read = store?.deletionHeadOf;
@@ -0,0 +1,57 @@
1
+ /**
2
+ * **会话种类 `sessionKind`** —— 一只会话是不是用户的顶层对话,是它出生那一笔写下的一个事实(规则只写在这里一次;三只会话店、授权口、列表口、能力面与老化腿同读)。
3
+ *
4
+ * ## 律
5
+ * · 闭集 {@link SESSION_KINDS};**缺席 = 顶层对话**(存量行、老壳建的行、fork / 同步导入 / run-local / 定时与 A2A 起的会话恒缺席 —— 缺席不存缺省词,顶层只有一种拼法)。
6
+ * · **只有建这只会话的那一次提交写它**(提交体 `sessionKind`,授权口登记新行的那一笔:SQL = 建行事务里的建行钩、local = 建行那一笔格写),此后终身不改 ——
7
+ * 没有改写它的写口;整段换装就地改写同一行(种类随行),删后同 id 重登记是新住客(无种类)。
8
+ * · 它只决定两件事:**会话枚举的缺省视图列不列它**(列表与 peer 目录读同一只 lister 的同一只视图 {@link sessionKindListed};缺省视图 = 无种类,
9
+ * `?sessionKind=<词>` = 只列那一种)与**它按哪只视界老化**(有种类 ⇒ 最后活动之后 `BG_AGENT_RETENTION_MS`、无活引用时由维护拍删)。
10
+ * · 按 id 的每一口读写、属主判、执行放置、同步 / fork / 删除对它与对任何会话是同一句话:种类不是资格、不是面、不是访问谓词。
11
+ *
12
+ * ## 与委派分区不是一件事
13
+ * core 的委派分区(`session_meta.placement_*`,placed 行)是引擎写的、不是列表面的行、不能当执行根;种类是客户端经提交写的、是列表面的行(缺省视图不列)、可以当执行根。
14
+ * 两个事实答两个问题,一个推不出另一个;「列不列」这一问的读者只有一只(lister 的视图谓词)。
15
+ */
16
+ /** 会话种类的闭集(**顺序 = 拒句里的列举顺序**;加一个词 = 判它在缺省视图里列不列、按哪只视界老化,并逐处过编译)。 */
17
+ export declare const SESSION_KINDS: readonly ["sidechain"];
18
+ /** 一只会话的种类(缺席 = 顶层对话)。 */
19
+ export type SessionKind = (typeof SESSION_KINDS)[number];
20
+ /** 值是不是闭集里的一个词(判的是 wire 值 / 行上那一格的形;表外 ⇒ 不是)。 */
21
+ export declare function isSessionKind(v: unknown): v is SessionKind;
22
+ /**
23
+ * 🔴 **视图谓词的唯一判法**(local 店的 lister 与老化候选面同调;SQL 两孪生的同一句是 `plugins/session-store-sql.ts` 的 `sessionKindSql`):
24
+ * 一行进一只视图 ⇔ 行上的种类**等于**视图的种类(两边缺席相等 —— 缺省视图只列无种类的行)。
25
+ */
26
+ export declare function sessionKindListed(rowKind: SessionKind | undefined, view: SessionKind | undefined): boolean;
27
+ /** 按 id 读种类的答案:读到它时行上的住客(化身那一格,按 `absent` 读)与种类(缺席 = 顶层)。`undefined`(整只)= 没有这只会话。 */
28
+ export interface SessionKindReading {
29
+ readonly incarnation: string | undefined;
30
+ readonly kind: SessionKind | undefined;
31
+ }
32
+ /** 会话店的按 id 种类读(三只持久店都交;包装层原样转发)。 */
33
+ export interface SessionKindFace {
34
+ sessionKindOf(sessionId: string): Promise<SessionKindReading | undefined>;
35
+ }
36
+ /** 店上的种类读(没有 ⇒ `undefined`:这台部署记不了种类 —— 能力位 `sessionKinds` 为空、带键提交 400)。 */
37
+ export declare function sessionKindFaceOf(store: unknown): SessionKindFace | undefined;
38
+ /** 行上那一格 → 种类(SQL 列 / local 格的唯一解码):闭集里的词 ⇒ 它;NULL / 缺 ⇒ 缺席;别的值 ⇒ 响亮抛(手改库 / 将来的词落到旧构建上 —— 不猜成顶层)。 */
39
+ export declare function sessionKindFromCell(sessionId: string, cell: unknown): SessionKind | undefined;
40
+ /** 老化候选面的一行(候选读只挑人,判官是删除围栏根行锁里的那一判 —— `session-deletion.ts` 的 `SessionAgeOutExpectation`)。 */
41
+ export interface IdleSession {
42
+ readonly sessionId: string;
43
+ /** 行上的属主(删除协调器按它走)。 */
44
+ readonly owner: string | null;
45
+ /** 读到它时行上的住客(围栏比它:候选读之后同 id 被删并重登记的新住客不被碰)。 */
46
+ readonly incarnation: string | undefined;
47
+ /** 最后活动(ISO;SQL `updated_at`,local 新近标记 —— 与列表行的 `lastActivityAt` 同一读法)。 */
48
+ readonly lastActivityAt: string;
49
+ }
50
+ /** 老化候选面的续页键(`(lastActivityAt, sessionId)` 升序:最老先出)。 */
51
+ export interface IdleSessionCursor {
52
+ readonly lastActivityAt: string;
53
+ readonly sessionId: string;
54
+ }
55
+ /** 老化候选面的序:最老先出(`(lastActivityAt, sessionId)` 升序 —— SQL 两孪生的 `ORDER BY` 与 local 店的排序同读这一判)。 */
56
+ export declare function idleSessionAfter(row: IdleSessionCursor, cursor: IdleSessionCursor | undefined): boolean;
57
+ //# sourceMappingURL=session-kind.d.ts.map
@@ -0,0 +1,22 @@
1
+ export const SESSION_KINDS = ["sidechain"];
2
+ export function isSessionKind(v) {
3
+ return typeof v === "string" && SESSION_KINDS.includes(v);
4
+ }
5
+ export function sessionKindListed(rowKind, view) {
6
+ return rowKind === view;
7
+ }
8
+ export function sessionKindFaceOf(store) {
9
+ const s = store;
10
+ return typeof s?.sessionKindOf === "function" ? { sessionKindOf: s.sessionKindOf.bind(s) } : undefined;
11
+ }
12
+ export function sessionKindFromCell(sessionId, cell) {
13
+ if (cell === null || cell === undefined)
14
+ return undefined;
15
+ if (isSessionKind(cell))
16
+ return cell;
17
+ throw new Error(`session ${sessionId} carries a session kind this build does not know (${JSON.stringify(String(cell).slice(0, 32))}) — refusing to read it as a top-level session; a newer build wrote it, or the row was edited by hand`);
18
+ }
19
+ export function idleSessionAfter(row, cursor) {
20
+ return cursor === undefined || row.lastActivityAt > cursor.lastActivityAt || (row.lastActivityAt === cursor.lastActivityAt && row.sessionId > cursor.sessionId);
21
+ }
22
+ //# sourceMappingURL=session-kind.js.map
@@ -9,7 +9,7 @@
9
9
  * 别的抛 = 活流刚收尾的竞态 ⇒ 落空闲臂。
10
10
  * · **空闲**:这只会话的完成收件箱(`externalNotificationInboxEntry`,external 键域;脱敏 / 限长在入箱口内)⇒ 下次开流排空成 `task_notification` 帧。
11
11
  * 部署没有收件箱 ⇒ 如实交回 `no_inbox`(调用方各自答:HTTP 门 501,引擎完成告警)。
12
- * · **复核住客**:两臂的投递动作(注入 / 入箱)之前**紧邻**一次头读,与目标的住客比 —— 判官是仓里那一只 `sameOccupant`(`execution-placement.ts`:属主 ∧ 化身,
12
+ * · **复核住客**:两臂的投递动作(注入 / 入箱)之前**紧邻**一次头读,与目标的住客比(读与判在属主存取器的 `occupantRecheckOf`)—— 判官是仓里那一只 `sameOccupant`(`execution-placement.ts`:属主 ∧ 化身,
13
13
  * 写口与执行上下文解析器判的也是它):不在 ⇒ `withdrawn: gone`;两样里任一样变了 ⇒ `withdrawn: replaced`。会话店不铸化身(嵌入方自建的店)时两侧都没有令牌,
14
14
  * 判官只剩属主那一半:属主没变 ⇒ 投,变了 ⇒ 撤回。这一读是动作之前的最后一次让出:判活读(及活臂刚收尾时的那次注入)都在它前面 ——
15
15
  * 令牌永不复用,此刻还是那一位 ⇒ 判活读那一刻也是那一位 ⇒ 判出的 run 是它的 run。
@@ -33,7 +33,7 @@
33
33
  import type { ExternalNotificationInput, SessionHead, SubagentToolOptions, TaskStream } from "@sema-agent/core";
34
34
  import { type WorkflowCompletionInbox } from "./orchestration/workflow-completion-inbox.js";
35
35
  import type { DelegationRootWitness } from "./delegated-session-owner.js";
36
- import type { HeadRead } from "./session-incarnation.js";
36
+ import type { OwnerAwareSessionStore } from "./security.js";
37
37
  import type { Logger } from "./observability/logger.js";
38
38
  /** 门的一次投递结局(闭集;调用方 `switch` 穷尽)。 */
39
39
  export type SessionNotifyOutcome = {
@@ -74,8 +74,8 @@ export interface SessionNotifyDoorIo {
74
74
  /** 本副本持活 core 流的腿(taskId → 流)。 */
75
75
  readonly liveRuns: ReadonlyMap<string, Pick<TaskStream, "notify">>;
76
76
  readonly inbox: WorkflowCompletionInbox | undefined;
77
- /** 会话店的按 id 头读(复核住客的那一读)。店没有 ⇒ `undefined`:调用方先判(路由 501;后台完成 relay 照交,门响亮抛 ⇒ relay 告警)。 */
78
- readonly headOf: HeadRead | undefined;
77
+ /** 会话店(复核住客的那一读只经属主存取器)。店没有按 id 头读 ⇒ 调用方先判(路由 501;后台完成 relay 照交,门响亮抛 ⇒ relay 告警)。 */
78
+ readonly sessionStorage: Pick<OwnerAwareSessionStore, "headOf"> | undefined;
79
79
  }
80
80
  export declare function createSessionNotifyDoor(io: SessionNotifyDoorIo): SessionNotifyDoor;
81
81
  /** 委派工具挂载期的完成 sink 的型(取自 core 的选项型,不手抄)。 */
@@ -1,14 +1,13 @@
1
1
  import { externalNotificationInboxEntry } from "./orchestration/workflow-completion-inbox.js";
2
- import { sameOccupant } from "./execution-placement.js";
2
+ import { occupantRecheckOf } from "./http/owner-access.js";
3
3
  import { recordFailOpen } from "./observability/fail-open.js";
4
4
  export function createSessionNotifyDoor(io) {
5
+ const occupantNow = occupantRecheckOf(io.sessionStorage);
5
6
  async function recheck(target) {
6
- if (io.headOf === undefined)
7
+ if (occupantNow === undefined)
7
8
  throw new Error("session notify door: the session store has no head read (headOf); the occupant cannot be re-checked before delivery");
8
- const head = await io.headOf(target.sessionId);
9
- if (head === undefined)
10
- return { delivery: "withdrawn", reason: "gone" };
11
- return sameOccupant(target.occupant, head) ? undefined : { delivery: "withdrawn", reason: "replaced" };
9
+ const verdict = await occupantNow(target.sessionId, target.occupant);
10
+ return verdict === "same" ? undefined : { delivery: "withdrawn", reason: verdict };
12
11
  }
13
12
  return {
14
13
  async deliver(target, event) {