@sema-agent/server 7.132.0 → 7.133.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 (402) hide show
  1. package/MIGRATION.md +266 -0
  2. package/README.md +8 -9
  3. package/README.zh-CN.md +7 -6
  4. package/USAGE.md +174 -55
  5. package/deploy/sema-up/README.md +19 -1
  6. package/deploy/sema-up/chart/templates/server-v4pro.yaml +5 -2
  7. package/deploy/sema-up/chart/templates/server.yaml +5 -2
  8. package/deploy/sema-up/stack/compose.yaml +3 -0
  9. package/deploy/sema-up/stack/sema-stack-cluster.yaml +4 -2
  10. package/dist/adoption/plan.d.ts +3 -2
  11. package/dist/adoption/plan.js +7 -5
  12. package/dist/adoption/runner.js +3 -10
  13. package/dist/adoption/sql.d.ts +3 -2
  14. package/dist/adoption/sql.js +3 -5
  15. package/dist/adoption/wire.d.ts +4 -1
  16. package/dist/adoption/wire.js +1 -0
  17. package/dist/approval-ask-audit-store.d.ts +31 -13
  18. package/dist/approval-ask-audit-store.js +272 -74
  19. package/dist/approval-ask-machine.d.ts +15 -0
  20. package/dist/approval-ask-machine.js +6 -0
  21. package/dist/approval-ask-retention.d.ts +136 -0
  22. package/dist/approval-ask-retention.js +102 -0
  23. package/dist/approval-card.d.ts +79 -19
  24. package/dist/approval-card.js +44 -13
  25. package/dist/approval-deny-reasons.d.ts +1 -1
  26. package/dist/approval.d.ts +9 -0
  27. package/dist/approval.js +24 -3
  28. package/dist/audit.d.ts +27 -10
  29. package/dist/audit.js +12 -16
  30. package/dist/bake-runner/main.js +3 -2
  31. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  32. package/dist/boot/execution-env.js +9 -7
  33. package/dist/boot/execution-lane.js +11 -0
  34. package/dist/boot/leader.js +2 -0
  35. package/dist/boot/memory-boundary.js +2 -2
  36. package/dist/boot/memory-consolidation.d.ts +5 -4
  37. package/dist/boot/memory-consolidation.js +7 -6
  38. package/dist/boot/org-delivery.d.ts +28 -0
  39. package/dist/boot/org-delivery.js +20 -0
  40. package/dist/boot/reapers.d.ts +3 -0
  41. package/dist/boot/reapers.js +21 -1
  42. package/dist/boot/resolve-spec.d.ts +3 -0
  43. package/dist/boot/resolve-spec.js +60 -81
  44. package/dist/boot/runner-deps.js +1 -0
  45. package/dist/boot/session-faces.d.ts +1 -0
  46. package/dist/boot/session-faces.js +4 -2
  47. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  48. package/dist/boot/stage-06-runners.d.ts +2 -0
  49. package/dist/boot/stage-06-runners.js +6 -3
  50. package/dist/boot/stage-07-capability-layer.d.ts +2 -0
  51. package/dist/boot/stage-07-capability-layer.js +24 -3
  52. package/dist/boot/stage-08-reapers.d.ts +2 -0
  53. package/dist/boot/stage-08-reapers.js +2 -2
  54. package/dist/boot/stage-09-leader.d.ts +3 -0
  55. package/dist/boot/stage-10-http-server.d.ts +3 -0
  56. package/dist/boot/stage-10-http-server.js +5 -6
  57. package/dist/boot/stores.js +2 -2
  58. package/dist/boot/web-admin.d.ts +4 -0
  59. package/dist/boot/web-admin.js +151 -63
  60. package/dist/boot/workflow-orchestration.d.ts +2 -0
  61. package/dist/boot/workflow-orchestration.js +2 -1
  62. package/dist/brain.js +8 -3
  63. package/dist/breaker-key.d.ts +6 -0
  64. package/dist/breaker-key.js +29 -0
  65. package/dist/caller-text-echo.d.ts +9 -6
  66. package/dist/caller-text-echo.js +8 -11
  67. package/dist/capabilities/center-plugins.d.ts +7 -0
  68. package/dist/capabilities/center-plugins.js +1 -1
  69. package/dist/capabilities/composite-members.d.ts +1 -1
  70. package/dist/capabilities/composite-members.js +1 -1
  71. package/dist/capabilities/execution-lane.js +2 -2
  72. package/dist/capabilities/hands-lane.d.ts +21 -0
  73. package/dist/capabilities/hands-lane.js +10 -0
  74. package/dist/capabilities/mcp-probe.d.ts +36 -4
  75. package/dist/capabilities/mcp-probe.js +27 -4
  76. package/dist/capabilities/scenarios.d.ts +63 -7
  77. package/dist/capabilities/scenarios.js +39 -7
  78. package/dist/capability-facts.d.ts +34 -4
  79. package/dist/capability-facts.js +28 -2
  80. package/dist/center-config-tier.d.ts +69 -0
  81. package/dist/center-config-tier.js +42 -0
  82. package/dist/checkpoint-identity.d.ts +16 -0
  83. package/dist/checkpoint-identity.js +19 -0
  84. package/dist/config-catalog.d.ts +17 -10
  85. package/dist/config-catalog.js +43 -28
  86. package/dist/config-d-migration.d.ts +3 -1
  87. package/dist/config-d-migration.js +2 -2
  88. package/dist/config-dir-trust.d.ts +114 -0
  89. package/dist/config-dir-trust.js +388 -0
  90. package/dist/config-invariants.d.ts +18 -5
  91. package/dist/config-invariants.js +35 -3
  92. package/dist/config-provider.d.ts +6 -1
  93. package/dist/config-provider.js +6 -2
  94. package/dist/config-types.d.ts +71 -14
  95. package/dist/config-types.js +8 -0
  96. package/dist/config.d.ts +13 -0
  97. package/dist/config.js +121 -59
  98. package/dist/delegated-session-owner.d.ts +185 -0
  99. package/dist/delegated-session-owner.js +119 -0
  100. package/dist/device-protocol.d.ts +5 -3
  101. package/dist/device-protocol.js +1 -1
  102. package/dist/device-ws-hub.js +21 -2
  103. package/dist/device-ws-protocol.d.ts +70 -6
  104. package/dist/device-ws-protocol.js +50 -23
  105. package/dist/elicitation.js +3 -2
  106. package/dist/entry-problems.d.ts +34 -0
  107. package/dist/entry-problems.js +14 -0
  108. package/dist/execution-lane-caps.d.ts +49 -10
  109. package/dist/execution-lane-caps.js +43 -4
  110. package/dist/field-conflict.d.ts +43 -0
  111. package/dist/field-conflict.js +20 -0
  112. package/dist/fleet/fleet-bus.d.ts +80 -6
  113. package/dist/fleet/fleet-bus.js +41 -9
  114. package/dist/hooks/classic-stations.d.ts +10 -5
  115. package/dist/hooks/classic-stations.js +4 -4
  116. package/dist/hooks/command-spawn.d.ts +57 -0
  117. package/dist/hooks/command-spawn.js +139 -0
  118. package/dist/hooks/hook-llm.js +2 -2
  119. package/dist/hooks/hook-runner.d.ts +127 -25
  120. package/dist/hooks/hook-runner.js +668 -287
  121. package/dist/hooks/hook-source.d.ts +44 -0
  122. package/dist/hooks/hook-source.js +40 -0
  123. package/dist/http/active-run-conflict.d.ts +5 -13
  124. package/dist/http/active-run-conflict.js +17 -27
  125. package/dist/http/admission.js +103 -60
  126. package/dist/http/approval-sweeps.js +55 -18
  127. package/dist/http/caller-trust.d.ts +77 -0
  128. package/dist/http/caller-trust.js +143 -0
  129. package/dist/http/checkpoint-ctx.d.ts +16 -16
  130. package/dist/http/checkpoint-ctx.js +13 -10
  131. package/dist/http/claimed-run.d.ts +4 -3
  132. package/dist/http/device-placement.d.ts +2 -4
  133. package/dist/http/device-placement.js +2 -1
  134. package/dist/http/dispatch.js +10 -4
  135. package/dist/http/durable-run-leg.d.ts +4 -32
  136. package/dist/http/durable-run-leg.js +34 -10
  137. package/dist/http/owner-access.d.ts +56 -0
  138. package/dist/http/owner-access.js +42 -0
  139. package/dist/http/principal-gate.d.ts +48 -23
  140. package/dist/http/principal-gate.js +39 -12
  141. package/dist/http/readiness.d.ts +11 -5
  142. package/dist/http/readiness.js +10 -3
  143. package/dist/http/request-guards.d.ts +16 -23
  144. package/dist/http/request-guards.js +30 -15
  145. package/dist/http/resume-ctx-read.d.ts +2 -5
  146. package/dist/http/resume-ctx-read.js +7 -4
  147. package/dist/http/resume-legs.d.ts +3 -4
  148. package/dist/http/resume-legs.js +126 -69
  149. package/dist/http/retired-service-deps.d.ts +43 -0
  150. package/dist/http/retired-service-deps.js +18 -0
  151. package/dist/http/route-ctx.d.ts +44 -28
  152. package/dist/http/route-ctx.js +4 -0
  153. package/dist/http/route-table.js +2 -0
  154. package/dist/http/routes/a2a-serve.js +3 -4
  155. package/dist/http/routes/admin-config-refresh.js +1 -1
  156. package/dist/http/routes/admin-drain.js +1 -1
  157. package/dist/http/routes/admin-memory-optout.js +5 -1
  158. package/dist/http/routes/adoption.js +2 -9
  159. package/dist/http/routes/approvals-assistant.js +49 -48
  160. package/dist/http/routes/background.js +3 -2
  161. package/dist/http/routes/capabilities.js +20 -4
  162. package/dist/http/routes/config-catalog.d.ts +3 -3
  163. package/dist/http/routes/config-catalog.js +1 -1
  164. package/dist/http/routes/devices.js +3 -17
  165. package/dist/http/routes/diagnostics.js +5 -1
  166. package/dist/http/routes/images.js +6 -7
  167. package/dist/http/routes/leader.js +1 -8
  168. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  169. package/dist/http/routes/mcp-reconnect.js +3 -2
  170. package/dist/http/routes/memory-bundle.js +1 -1
  171. package/dist/http/routes/memory-compliance.js +1 -1
  172. package/dist/http/routes/memory-consolidation.js +1 -1
  173. package/dist/http/routes/memory-origin.js +1 -1
  174. package/dist/http/routes/memory-policy.d.ts +1 -1
  175. package/dist/http/routes/memory-policy.js +3 -2
  176. package/dist/http/routes/notify-wake.js +8 -21
  177. package/dist/http/routes/observability.js +2 -2
  178. package/dist/http/routes/principal-inbox.d.ts +39 -0
  179. package/dist/http/routes/principal-inbox.js +76 -0
  180. package/dist/http/routes/retention-ops.js +2 -9
  181. package/dist/http/routes/rules.js +5 -18
  182. package/dist/http/routes/runs.d.ts +5 -0
  183. package/dist/http/routes/runs.js +33 -106
  184. package/dist/http/routes/session-sync.js +15 -28
  185. package/dist/http/routes/sessions.js +30 -40
  186. package/dist/http/routes/side-query.js +6 -4
  187. package/dist/http/routes/tasks.js +50 -14
  188. package/dist/http/routes/workflows.d.ts +351 -0
  189. package/dist/http/routes/workflows.js +153 -119
  190. package/dist/http/send.d.ts +24 -3
  191. package/dist/http/send.js +14 -2
  192. package/dist/http/server.d.ts +17 -18
  193. package/dist/http/server.js +15 -13
  194. package/dist/http/stored-body-replay.js +17 -4
  195. package/dist/http/submit-ctx.js +4 -3
  196. package/dist/http/submit-replay.d.ts +4 -3
  197. package/dist/http/submit-replay.js +5 -4
  198. package/dist/http/wire-types.d.ts +10 -7
  199. package/dist/index.d.ts +1 -1
  200. package/dist/index.js +0 -1
  201. package/dist/lane-home-probe.d.ts +78 -9
  202. package/dist/lane-home-probe.js +78 -12
  203. package/dist/leader/endpoint.d.ts +4 -1
  204. package/dist/leader/endpoint.js +11 -10
  205. package/dist/limit-refusal.d.ts +17 -5
  206. package/dist/limit-refusal.js +4 -1
  207. package/dist/mcp-assertion-header.d.ts +31 -10
  208. package/dist/mcp-assertion-header.js +10 -3
  209. package/dist/mcp-tool-faces.js +1 -3
  210. package/dist/memory-project-layer.d.ts +37 -0
  211. package/dist/memory-project-layer.js +46 -0
  212. package/dist/memory-scope.d.ts +23 -16
  213. package/dist/memory-scope.js +24 -8
  214. package/dist/memory-sync-client.d.ts +27 -13
  215. package/dist/memory-sync-client.js +107 -18
  216. package/dist/model-entry-refusal.d.ts +9 -1
  217. package/dist/model-entry-refusal.js +6 -1
  218. package/dist/model-plane-face.d.ts +51 -0
  219. package/dist/model-plane-face.js +24 -0
  220. package/dist/model-provider.d.ts +5 -0
  221. package/dist/model-provider.js +4 -2
  222. package/dist/model-route-endpoint.d.ts +8 -11
  223. package/dist/model-route-endpoint.js +4 -7
  224. package/dist/model-route-env.d.ts +22 -0
  225. package/dist/model-route-env.js +2 -0
  226. package/dist/model-route-gap.d.ts +60 -30
  227. package/dist/model-route-gap.js +21 -15
  228. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  229. package/dist/observability/corrupt-read-seat.js +9 -0
  230. package/dist/observability/err-text.d.ts +6 -0
  231. package/dist/observability/err-text.js +18 -4
  232. package/dist/observability/fail-open.d.ts +35 -9
  233. package/dist/observability/fail-open.js +35 -9
  234. package/dist/observability/metrics.js +1 -0
  235. package/dist/observability/prompt-manifest.d.ts +3 -17
  236. package/dist/observability/prompt-manifest.js +45 -42
  237. package/dist/observability/tool-trace.js +9 -9
  238. package/dist/operator-ask.d.ts +10 -0
  239. package/dist/operator-ask.js +3 -0
  240. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  241. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  242. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  243. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  244. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  245. package/dist/orchestration/workflow-notify-journal.js +27 -34
  246. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  247. package/dist/orchestration/workflow-park-decision.js +118 -0
  248. package/dist/org-delivery-gate.d.ts +81 -0
  249. package/dist/org-delivery-gate.js +59 -0
  250. package/dist/panel-tool-names.d.ts +23 -0
  251. package/dist/panel-tool-names.js +8 -0
  252. package/dist/parked-decide.d.ts +39 -6
  253. package/dist/parked-decide.js +98 -51
  254. package/dist/parked-revive-surface.d.ts +9 -2
  255. package/dist/parked-revive-surface.js +11 -8
  256. package/dist/permission-rule-list.d.ts +1 -1
  257. package/dist/permission-rule-list.js +2 -2
  258. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  259. package/dist/plugins/approval-ask-store-file.js +21 -0
  260. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  261. package/dist/plugins/approval-ask-store-memory.js +34 -2
  262. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  263. package/dist/plugins/approval-ask-store-sql.js +37 -1
  264. package/dist/plugins/blob-backend.d.ts +38 -25
  265. package/dist/plugins/blob-backend.js +29 -19
  266. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  267. package/dist/plugins/breaker-state-sql.js +4 -4
  268. package/dist/plugins/caching-session-store.d.ts +3 -0
  269. package/dist/plugins/caching-session-store.js +3 -0
  270. package/dist/plugins/checkpoint-store-sql.d.ts +14 -0
  271. package/dist/plugins/checkpoint-store-sql.js +20 -2
  272. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  273. package/dist/plugins/file-history-store-sql.js +3 -1
  274. package/dist/plugins/file-run-store.d.ts +5 -13
  275. package/dist/plugins/file-run-store.js +9 -0
  276. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  277. package/dist/plugins/fork-routing-session-store.js +12 -1
  278. package/dist/plugins/host-platform.d.ts +2 -0
  279. package/dist/plugins/host-platform.js +2 -1
  280. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  281. package/dist/plugins/local-checkpoint-store.js +6 -1
  282. package/dist/plugins/local-session-store.d.ts +1 -1
  283. package/dist/plugins/local-session-window.d.ts +39 -0
  284. package/dist/plugins/local-session-window.js +54 -0
  285. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  286. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  287. package/dist/plugins/mailbox-store-sql.js +77 -52
  288. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  289. package/dist/plugins/memory-run-store.d.ts +5 -13
  290. package/dist/plugins/memory-run-store.js +8 -0
  291. package/dist/plugins/one-time-migrations.d.ts +110 -5
  292. package/dist/plugins/one-time-migrations.js +320 -8
  293. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  294. package/dist/plugins/org-delivery-quota-store.js +228 -0
  295. package/dist/plugins/pg-pool.js +39 -7
  296. package/dist/plugins/pg-session-storage.d.ts +17 -4
  297. package/dist/plugins/pg-session-storage.js +29 -6
  298. package/dist/plugins/remote-env-adb.d.ts +6 -12
  299. package/dist/plugins/remote-env-adb.js +12 -2
  300. package/dist/plugins/remote-env-k8s.d.ts +8 -12
  301. package/dist/plugins/remote-env-k8s.js +23 -5
  302. package/dist/plugins/remote-env-local-docker.d.ts +10 -15
  303. package/dist/plugins/remote-env-local-docker.js +12 -9
  304. package/dist/plugins/remote-env-ssh.d.ts +10 -16
  305. package/dist/plugins/remote-env-ssh.js +17 -11
  306. package/dist/plugins/run-store-sql.d.ts +16 -14
  307. package/dist/plugins/run-store-sql.js +22 -2
  308. package/dist/plugins/schema-indexes.js +2 -0
  309. package/dist/plugins/send-user-file.js +2 -2
  310. package/dist/plugins/session-epoch-anchor.d.ts +32 -6
  311. package/dist/plugins/session-epoch-anchor.js +2 -3
  312. package/dist/plugins/session-store.d.ts +18 -8
  313. package/dist/plugins/session-store.js +15 -4
  314. package/dist/plugins/sql-driver.d.ts +74 -11
  315. package/dist/plugins/sql-driver.js +210 -12
  316. package/dist/plugins/sql-errors.d.ts +23 -0
  317. package/dist/plugins/sql-errors.js +21 -0
  318. package/dist/plugins/store-backend.d.ts +36 -1
  319. package/dist/plugins/store-backend.js +40 -14
  320. package/dist/plugins/store-contracts.d.ts +42 -0
  321. package/dist/plugins/store-contracts.js +1 -0
  322. package/dist/plugins/tidb-pool.d.ts +6 -1
  323. package/dist/plugins/tidb-pool.js +44 -10
  324. package/dist/plugins/tidb-session-storage.d.ts +3 -2
  325. package/dist/plugins/tidb-session-storage.js +2 -2
  326. package/dist/plugins/tidb-session-store.d.ts +24 -4
  327. package/dist/plugins/tidb-session-store.js +28 -4
  328. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  329. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  330. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  331. package/dist/plugins/workflow-run-store-sql.js +50 -9
  332. package/dist/posture-source.d.ts +18 -10
  333. package/dist/posture-source.js +4 -1
  334. package/dist/project-identity.d.ts +45 -6
  335. package/dist/project-identity.js +162 -8
  336. package/dist/project-layer-key.d.ts +28 -0
  337. package/dist/project-layer-key.js +29 -0
  338. package/dist/question.js +3 -2
  339. package/dist/read-deny-entry.d.ts +25 -0
  340. package/dist/read-deny-entry.js +12 -0
  341. package/dist/read-face-posture.d.ts +37 -11
  342. package/dist/read-face-posture.js +32 -3
  343. package/dist/request-key-closure.d.ts +7 -0
  344. package/dist/request-key-closure.js +9 -1
  345. package/dist/request-value-closure.d.ts +5 -0
  346. package/dist/request-value-closure.js +11 -3
  347. package/dist/rule-entry-list.d.ts +26 -2
  348. package/dist/rule-entry-list.js +72 -12
  349. package/dist/rules-consent.js +3 -4
  350. package/dist/run-acceptance.d.ts +19 -3
  351. package/dist/run-acceptance.js +13 -1
  352. package/dist/run-local.js +36 -6
  353. package/dist/runs.d.ts +10 -9
  354. package/dist/runs.js +21 -3
  355. package/dist/runtime-caps-resolver.d.ts +16 -6
  356. package/dist/runtime-caps-resolver.js +18 -5
  357. package/dist/sandbox-pkg-source.d.ts +19 -1
  358. package/dist/sandbox-pkg-source.js +29 -7
  359. package/dist/security.d.ts +87 -9
  360. package/dist/security.js +52 -9
  361. package/dist/session-error-wire.d.ts +19 -2
  362. package/dist/session-error-wire.js +5 -1
  363. package/dist/session-titled-frame.d.ts +33 -0
  364. package/dist/session-titled-frame.js +4 -0
  365. package/dist/session-titler.d.ts +9 -1
  366. package/dist/session-titler.js +15 -4
  367. package/dist/spec-fields.js +21 -2
  368. package/dist/sql-engine-posture.d.ts +3 -1
  369. package/dist/task-cwd.d.ts +1 -1
  370. package/dist/task-mcp.d.ts +3 -3
  371. package/dist/task-mcp.js +7 -66
  372. package/dist/task-settings.d.ts +89 -88
  373. package/dist/task-settings.js +71 -63
  374. package/dist/text-bidi.d.ts +0 -4
  375. package/dist/text-bidi.js +1 -3
  376. package/dist/tighten-only-seats.d.ts +150 -0
  377. package/dist/tighten-only-seats.js +196 -0
  378. package/dist/tool-approval.d.ts +303 -87
  379. package/dist/tool-approval.js +623 -239
  380. package/dist/trace/core-keyset-guard.d.ts +104 -22
  381. package/dist/trace/exit-seat.d.ts +28 -0
  382. package/dist/trace/exit-seat.js +76 -0
  383. package/dist/trace/ledger-events.d.ts +3 -2
  384. package/dist/trace/project.d.ts +80 -12
  385. package/dist/trace/project.js +41 -28
  386. package/dist/trace/projection-table.d.ts +100 -0
  387. package/dist/trace/projection-table.js +130 -0
  388. package/dist/trace/redact.d.ts +54 -0
  389. package/dist/trace/redact.js +778 -152
  390. package/dist/trace/self-minted-wire.d.ts +345 -1
  391. package/dist/trace/self-minted-wire.js +117 -1
  392. package/dist/trace/wire-projection-faces.d.ts +298 -2
  393. package/dist/trace/wire-projection-faces.js +154 -13
  394. package/dist/url-refusal.js +2 -0
  395. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  396. package/dist/web-admin-client/apply-effective.js +56 -5
  397. package/dist/web-admin-client/facade.d.ts +1 -1
  398. package/dist/web-admin-client/facade.js +1 -1
  399. package/dist/web-admin-client/read-face.js +5 -9
  400. package/dist/web-admin-client/skills-mcp.js +4 -5
  401. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +57 -9
  402. package/package.json +7 -3
@@ -0,0 +1,102 @@
1
+ import { RUN_STATUS_CLASS } from "./plugins/store-contracts.js";
2
+ export const APPROVAL_ASK_RETENTION_DEFAULT_MS = 30 * 86_400_000;
3
+ export const APPROVAL_ASK_RETENTION_FLOOR_MS = 86_400_000;
4
+ export const APPROVAL_ASK_RETENTION_PASS_MS = 3_600_000;
5
+ export const APPROVAL_ASK_REAP_BATCH = 500;
6
+ export const MOVABLE_RUN_STATUSES = [
7
+ ...Object.entries(RUN_STATUS_CLASS).filter(([, cls]) => cls === "parked"),
8
+ ...Object.entries(RUN_STATUS_CLASS).filter(([, cls]) => cls === "live"),
9
+ ...Object.entries(RUN_STATUS_CLASS).filter(([, cls]) => cls === "parked"),
10
+ ].map(([status]) => status);
11
+ const BACKGROUND_AGENT_MOVABLE = {
12
+ running: true,
13
+ parked: true,
14
+ completed: false,
15
+ failed: false,
16
+ killed: false,
17
+ };
18
+ export async function collectMovableAnchors(input) {
19
+ const anchors = new Set();
20
+ for (const status of MOVABLE_RUN_STATUSES) {
21
+ let cursor;
22
+ for (;;) {
23
+ const page = await input.runs.listRuns({ status, limit: APPROVAL_ASK_REAP_BATCH, ...(cursor !== undefined ? { cursor } : {}) });
24
+ for (const r of page) {
25
+ anchors.add(r.taskId);
26
+ anchors.add(r.sessionId);
27
+ }
28
+ const last = page[page.length - 1];
29
+ if (page.length < APPROVAL_ASK_REAP_BATCH || last === undefined)
30
+ break;
31
+ cursor = { createdAt: last.createdAt, taskId: last.taskId };
32
+ }
33
+ }
34
+ const agents = input.backgroundAgents;
35
+ if (agents !== undefined) {
36
+ if (agents.listScopes === undefined) {
37
+ throw new Error("approval ledger retention: the background-agent store cannot enumerate its scopes (no listScopes) — cannot prove which delegated children can no longer move, so nothing is aged out this pass");
38
+ }
39
+ for (const scope of await agents.listScopes()) {
40
+ for (const row of await agents.listByScope(scope)) {
41
+ if (!BACKGROUND_AGENT_MOVABLE[row.status])
42
+ continue;
43
+ for (const anchor of [row.owner, row.sessionId, row.parentSessionId, row.rootSessionId])
44
+ if (anchor !== undefined)
45
+ anchors.add(anchor);
46
+ }
47
+ }
48
+ }
49
+ if (input.checkpoints !== undefined)
50
+ for (const sessionId of await input.checkpoints.listPendingSessionIds())
51
+ anchors.add(sessionId);
52
+ return anchors;
53
+ }
54
+ export async function runApprovalAskRetentionPass(input) {
55
+ const { askStore, audit, runs, backgroundAgents, checkpoints, cutoffMs, logger, metrics } = input;
56
+ const reading = { cutoffMs, asks: 0, batches: 0, auditAsks: 0, auditRecords: 0 };
57
+ const count = (ledger, n) => {
58
+ if (n > 0)
59
+ metrics.inc("approval_ask_retention_rows_deleted_total", { ledger }, n);
60
+ };
61
+ const report = (incomplete) => {
62
+ if (reading.asks === 0 && reading.batches === 0 && reading.auditRecords === 0)
63
+ return;
64
+ logger.info("approval_ask_retention_swept", {
65
+ ...reading,
66
+ ...(incomplete ? { incomplete: true } : {}),
67
+ note: "settled approval asks quiet for longer than APPROVAL_ASK_RETENTION_MS, with nothing they hang off (their run, host session or asking leg's session) still able to move, were deleted whole from the approval ledgers (ask rows, emptied batches, and their audit-ledger records); records that remain are byte-for-byte unchanged. Set APPROVAL_ASK_RETENTION_MS=0 to keep everything.",
68
+ });
69
+ };
70
+ try {
71
+ const movable = await collectMovableAnchors({ runs, backgroundAgents, checkpoints });
72
+ if (askStore !== undefined) {
73
+ for (;;) {
74
+ const n = await askStore.reapSettledAsks(cutoffMs, APPROVAL_ASK_REAP_BATCH, movable);
75
+ reading.asks += n;
76
+ count("asks", n);
77
+ if (n < APPROVAL_ASK_REAP_BATCH)
78
+ break;
79
+ }
80
+ for (;;) {
81
+ const n = await askStore.reapEmptyBatches(cutoffMs, APPROVAL_ASK_REAP_BATCH);
82
+ reading.batches += n;
83
+ count("batches", n);
84
+ if (n < APPROVAL_ASK_REAP_BATCH)
85
+ break;
86
+ }
87
+ }
88
+ if (audit !== undefined) {
89
+ const rotated = audit.rotateOlderThan(cutoffMs, movable);
90
+ reading.auditAsks += rotated.droppedAsks;
91
+ reading.auditRecords += rotated.droppedRecords;
92
+ count("audit", rotated.droppedRecords);
93
+ }
94
+ }
95
+ catch (err) {
96
+ report(true);
97
+ throw err;
98
+ }
99
+ report(false);
100
+ return reading;
101
+ }
102
+ //# sourceMappingURL=approval-ask-retention.js.map
@@ -23,6 +23,8 @@
23
23
  import { z } from "zod";
24
24
  import { ALLOW_RULE_MEMBERS, READ_ROOT_CANDIDATE_DIR_MAX, type AskClass, type AskEvidenceAbsence, type PendingAction as CorePendingAction, type ReadRootGrantCandidate, type ResumeStartupCause, type RuleOffer, type RuleOffersAbsence as CoreRuleOffersAbsence, type SteerReplayFacet } from "@sema-agent/core";
25
25
  import type { AskRow } from "./plugins/approval-ask-store-sql.js";
26
+ import type { SettleCause, SettleOutcome } from "./approval-deny-reasons.js";
27
+ import type { ToolApprovalFrame } from "./tool-approval.js";
26
28
  /** 模型自由文本(`sourceAgentName` / `delegation.agentName`)的限长(设计稿 §6.2)。设计 §3.1 把
27
29
  * 「限长 + 脱敏」写成 **server 新增责任**(引擎无此层):spawning model 挑的名字是自由文本,
28
30
  * 不能指望壳去截——一条 100KB 的 agentName 在 server 侧就该被拒,而不是变成一张撑爆呈卡面的卡。 */
@@ -82,8 +84,8 @@ export declare const RuleOfferSchema: z.ZodUnion<readonly [z.ZodObject<{
82
84
  rule: z.ZodString;
83
85
  match: z.ZodEnum<{
84
86
  name: "name";
85
- path: "path";
86
87
  host: "host";
88
+ path: "path";
87
89
  exact: "exact";
88
90
  prefix: "prefix";
89
91
  wildcard: "wildcard";
@@ -99,8 +101,8 @@ export declare const RuleOfferSchema: z.ZodUnion<readonly [z.ZodObject<{
99
101
  rule: z.ZodString;
100
102
  match: z.ZodEnum<{
101
103
  name: "name";
102
- path: "path";
103
104
  host: "host";
105
+ path: "path";
104
106
  exact: "exact";
105
107
  prefix: "prefix";
106
108
  wildcard: "wildcard";
@@ -167,8 +169,8 @@ export declare const RuleOfferRawSchema: z.ZodUnion<readonly [z.ZodObject<{
167
169
  rule: z.ZodString;
168
170
  match: z.ZodEnum<{
169
171
  name: "name";
170
- path: "path";
171
172
  host: "host";
173
+ path: "path";
172
174
  exact: "exact";
173
175
  prefix: "prefix";
174
176
  wildcard: "wildcard";
@@ -184,8 +186,8 @@ export declare const RuleOfferRawSchema: z.ZodUnion<readonly [z.ZodObject<{
184
186
  rule: z.ZodString;
185
187
  match: z.ZodEnum<{
186
188
  name: "name";
187
- path: "path";
188
189
  host: "host";
190
+ path: "path";
189
191
  exact: "exact";
190
192
  prefix: "prefix";
191
193
  wildcard: "wildcard";
@@ -631,8 +633,8 @@ export declare const ApprovalCardSchema: z.ZodObject<{
631
633
  rule: z.ZodString;
632
634
  match: z.ZodEnum<{
633
635
  name: "name";
634
- path: "path";
635
636
  host: "host";
637
+ path: "path";
636
638
  exact: "exact";
637
639
  prefix: "prefix";
638
640
  wildcard: "wildcard";
@@ -648,8 +650,8 @@ export declare const ApprovalCardSchema: z.ZodObject<{
648
650
  rule: z.ZodString;
649
651
  match: z.ZodEnum<{
650
652
  name: "name";
651
- path: "path";
652
653
  host: "host";
654
+ path: "path";
653
655
  exact: "exact";
654
656
  prefix: "prefix";
655
657
  wildcard: "wildcard";
@@ -728,10 +730,13 @@ export declare const ApprovalCardSchema: z.ZodObject<{
728
730
  }, z.core.$strict>;
729
731
  export type ApprovalCard = z.infer<typeof ApprovalCardSchema>;
730
732
  /**
731
- * `approval_ask.card_json` 里真正存的东西(设计稿 §6.2)。存**信封**而不是裸卡的理由:重放帧要回填
732
- * 车2 铸的 `approvalId`(wire 面的回决通道桥 + 消费端与并行 `tool_approval` 帧的去重键),而它不属于
733
- * 「卡的内容」——放进卡里会让 schema 的语义边界糊掉。`schemaVersion` 是形的版本闩(与行上的
733
+ * `approval_ask.card_json` 里真正存的东西(设计稿 §6.2)。`schemaVersion` 是形的版本闩(与行上的
734
734
  * `schema_version` 列同值,列供 SQL 侧过滤,信封里这份供读面在解出内容**之前**判形)。
735
+ *
736
+ * `approvalId` = 这张卡**呈出时**的 wire 身份。7.133.0 起它恒等于行的键 `askId`(一只 ask 一只 wire 身份),本服务的活读者(重放帧 /
737
+ * 应答口 / 读口)一律读行的键、不读这一格;写它是给滚动升级窗里上一版的副本(它们的 strict 信封 schema 要求这一格并照它重放)。
738
+ * 唯一读这一格的是 local 车道的启动收敛 —— 拿它去审计账里查前世这只 ask 的成因:审计行记的就是当时呈出的那个 id
739
+ * (更早写下的行上是当年的登记本地 id)。
735
740
  */
736
741
  export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
737
742
  schemaVersion: z.ZodLiteral<1>;
@@ -766,8 +771,8 @@ export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
766
771
  rule: z.ZodString;
767
772
  match: z.ZodEnum<{
768
773
  name: "name";
769
- path: "path";
770
774
  host: "host";
775
+ path: "path";
771
776
  exact: "exact";
772
777
  prefix: "prefix";
773
778
  wildcard: "wildcard";
@@ -783,8 +788,8 @@ export declare const ApprovalCardEnvelopeSchema: z.ZodObject<{
783
788
  rule: z.ZodString;
784
789
  match: z.ZodEnum<{
785
790
  name: "name";
786
- path: "path";
787
791
  host: "host";
792
+ path: "path";
788
793
  exact: "exact";
789
794
  prefix: "prefix";
790
795
  wildcard: "wildcard";
@@ -958,16 +963,33 @@ export declare function buildApprovalRequestFrame(input: {
958
963
  card: ApprovalCard;
959
964
  expiresAtMs: number;
960
965
  nowMs: number;
966
+ live: ApprovalRequestLiveFacts;
961
967
  }): ApprovalRequestFrame;
962
968
  /**
963
- * [ref] §3.1 的呈卡帧(设计稿 §4.1 逐字)。
969
+ * 🔴 **呈卡帧的活面事实座**(呈卡腿上旧族退役之后,开卡帧的全部事实都由本族承载)。
970
+ *
971
+ * 这十个座是活卡帧 `tool_approval` 上有、而卡(`ApprovalCardSchema`,`card_json` 的耐久信封)上**没有**的那几位:
972
+ * 卡外的事实此前只骑活卡帧,呈卡腿的消费方靠「两帧按 approvalId 合读」拿到它们。呈卡腿自此只发本族帧 ⇒ 它们挪到**活铸**的
973
+ * 呈卡帧顶层,同名同型同值 —— 值取自同一只帧对象(活卡帧的那一次铸定,`tool-approval.ts` 的 `askBroadcast`),本仓不另算一遍。
964
974
  *
965
- * 与既有 `tool_approval` 帧是**并行加帧、不替换**(§4.2):存量壳只认旧帧,新帧是闭集加员;两帧同带
966
- * `approvalId`,消费端据它去重。
975
+ * 在场面与它们在活卡帧上的在场面**逐字相同**:只在活铸的帧上,断连重放帧({@link buildReplayFrame},从 `card_json` 回读)上恒缺席 ——
976
+ * 活卡帧从来不重放,卡外事实也从来不在重放面上;是否把其中某几位收进卡(耐久、随重放)是另一件事,各自要过 `.strict()` 信封的回滚窗判断
977
+ * (`readRootCandidate` 有不进卡的硬理由:耐久面兑现不了它,见活卡帧该座顶注)。
967
978
  *
968
- * 🔴 铸造/发射**不在刀 3c**(那是 3b 的域)。本文件只出「持久行 → 帧」的重放投影 `buildReplayFrame`。
979
+ * `requiresRealApproval` 不在表里:卡上 `risk.requiresRealApproval` 是同一个事实(铸卡第三参就是它),一个事实一个读法。
969
980
  */
970
- export interface ApprovalRequestFrame {
981
+ export declare const APPROVAL_REQUEST_LIVE_FACT_KEYS: readonly ["mandated", "mandate", "origin", "boundGrantDigest", "boundGrants", "classifierNoRuling", "boundGrantAbsence", "approvalCard", "readRootCandidate", "probeReason"];
982
+ /** 呈卡帧活面事实座的类型面 = 活卡帧同名座的 `Pick`(同型由构造保证,不手抄)。 */
983
+ export type ApprovalRequestLiveFacts = Pick<ToolApprovalFrame, (typeof APPROVAL_REQUEST_LIVE_FACT_KEYS)[number]>;
984
+ /**
985
+ * [ref] §3.1 的呈卡帧(设计稿 §4.1 逐字)。
986
+ *
987
+ * 🔴 **一条腿一个帧族**:呈卡协议在一条腿上场(腿的审批上下文接了 `emitCard`)⇒ 这条腿上一只 ask 的开卡 / 消卡 / 撤卡只走本族
988
+ * (`approval_request` / {@link ApprovalCompleteFrame} / {@link ApprovalRevokeFrame}),旧族 `tool_approval` / `tool_approval_complete`
989
+ * 一帧都不发;协议未上场的腿只发旧族。同一只 ask 在同一条腿上不再有两种开卡帧,消费方不再按 `approvalId` 去重。
990
+ * 开卡的全部事实因此在本帧上:卡(`card`,耐久信封)+ 活面事实座({@link ApprovalRequestLiveFacts},只在活铸的帧上)。
991
+ */
992
+ export interface ApprovalRequestFrame extends ApprovalRequestLiveFacts {
971
993
  /** = SSE 具名事件名(与 `tool_approval` 同约定)。 */
972
994
  type: "approval_request";
973
995
  schemaVersion: 1;
@@ -984,12 +1006,50 @@ export interface ApprovalRequestFrame {
984
1006
  expiresAtMs: number;
985
1007
  serverNowMs: number;
986
1008
  /**
987
- * server 扩(不在设计字面):车4 落地前的**回决通道桥**——现行
988
- * `POST /v1/tool-approvals/:id/respond` 的 id。也是消费端把本帧与并行的 `tool_approval` 帧去重的键。
989
- * 车4 上线后仍保留(旧壳过渡窗)。
1009
+ * server 扩(不在设计字面):`POST /v1/tool-approvals/:id/respond` / `GET /v1/tool-approvals/:id` 的 id —— **恒等于 `askId`**(行的键就是这只 ask
1010
+ * 唯一的 wire 身份;本族的消卡帧({@link ApprovalCompleteFrame})同带它)。
990
1011
  */
991
1012
  approvalId: string;
992
1013
  }
1014
+ /**
1015
+ * 呈卡族的**单卡消卡帧**(`approval_complete`)—— 一只 ask 落定时发给每一条**收到过它的呈卡帧**的呈卡腿连接。
1016
+ *
1017
+ * 语义与旧族 `tool_approval_complete` 逐字同一件事(同一次 settle 的同一份判决:`outcome` 三词、非人结局的 `cause`、park 路由的
1018
+ * `parked`),只是它属于本族:键与开卡帧对位(`askId` / `taskId` / `approvalId`,开卡帧上有的身份这里都有),消卡按开卡那一帧的键。
1019
+ * 与 {@link ApprovalRevokeFrame} 的分工:撤卡帧是**批级**的(兄弟被赢家连坐成 `VOID` 的那一批,名单 = 那一次原子事务的行集,
1020
+ * 不带逐卡终局);本帧是**单卡**的终局(人答 / 窗到期 / park 路由 / 取消 …)。同一只 ask 两帧都可能收到(被撤的兄弟自己的
1021
+ * 登记也按 settle 收场)—— 按 `askId` 清卡即可,两帧不冲突。
1022
+ *
1023
+ * 投递口 = 开卡帧的同一只口(`ToolApprovalRunContext.emitCard`):卡帧在哪,消卡帧就在哪(sync 腿 live + detach 账本,bg / resume 腿账本)。
1024
+ * 门 = 这条连接的**开卡帧真的送达过**(没见过开卡帧的连接收到消卡帧就是孤儿 close,与旧族同一条门)。
1025
+ */
1026
+ export interface ApprovalCompleteFrame {
1027
+ /** = SSE 具名事件名(同 `approval_request` 约定)。 */
1028
+ type: "approval_complete";
1029
+ schemaVersion: 1;
1030
+ askId: string;
1031
+ taskId: string;
1032
+ approvalId: string;
1033
+ /** 这只 ask 怎么落定 —— 与审计 settle 行 `outcome` 同三词(`allowed` / `denied` = 一次决议;`expired` = 非人结局)。 */
1034
+ outcome: SettleOutcome;
1035
+ /** 非人结局的成因(与审计 settle 行 `cause` 同一个词);人答缺席。缺席不是证据。 */
1036
+ cause?: SettleCause;
1037
+ /** 这只 ask 按 park 路由收尾(行已转 PARKING / PARKED、迟到回决可达)。缺席 = 无证据,禁读作真拒。 */
1038
+ parked?: true;
1039
+ serverNowMs: number;
1040
+ }
1041
+ /** 单卡消卡帧的纯构造(`build*`:纯数据)。可选座只在有值时写键。 */
1042
+ export declare function buildApprovalCompleteFrame(input: {
1043
+ askId: string;
1044
+ taskId: string;
1045
+ approvalId: string;
1046
+ outcome: SettleOutcome;
1047
+ cause?: SettleCause;
1048
+ parked: boolean;
1049
+ nowMs: number;
1050
+ }): ApprovalCompleteFrame;
1051
+ /** 呈卡腿的单卡帧(开卡 / 消卡)—— `ToolApprovalRunContext.emitCard` 的入参形。 */
1052
+ export type ApprovalCardLegFrame = ApprovalRequestFrame | ApprovalCompleteFrame;
993
1053
  /**
994
1054
  * [ref] §3.3 的**批级撤卡帧**(车6;设计稿 §3 逐字)。
995
1055
  *
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { ALLOW_RULE_MEMBERS, ASK_EVIDENCE_ABSENCE_VALUES, BOUND_GRANT_ABSENCES, MAX_RULE_TEXT_CHARS, READ_ROOT_CANDIDATE_DIR_MAX, RESUME_STARTUP_CAUSES, RULE_OFFERS_ABSENCES, STEER_REPLAY_FACETS, isAskClass, isAskOrigin, isAutoModeFallbackCause, isMintableProbeReason, isPersistedRuleMandate, screenAskClassMembers } from "@sema-agent/core";
3
3
  import { redactSecrets } from "./trace/redact.js";
4
4
  import { recordFailOpen } from "./observability/fail-open.js";
5
+ import { capText } from "./caller-text-echo.js";
5
6
  import { retireParkArmWords, retireStoredCardWords } from "./retired-card-words.js";
6
7
  import { PERSISTED_RULE_MATCHES, UNCOVERED_SEGMENT_REASONS } from "./permission-rule-vocab.js";
7
8
  export const MAX_AGENT_NAME = 200;
@@ -450,11 +451,6 @@ const RiskAxesEnvelopeSchema = z.object({
450
451
  })
451
452
  .optional(),
452
453
  });
453
- function clip(s, max) {
454
- if (s === undefined)
455
- return undefined;
456
- return s.length > max ? s.slice(0, max) : s;
457
- }
458
454
  export function buildApprovalCard(source, req, requiresRealApproval) {
459
455
  const axes = RiskAxesEnvelopeSchema.safeParse(req);
460
456
  const riskAxes = axes.success ? axes.data.riskAxes : undefined;
@@ -463,13 +459,13 @@ export function buildApprovalCard(source, req, requiresRealApproval) {
463
459
  const ruleOffersAbsence = readRuleOffersAbsence(req);
464
460
  const denialLimitFallback = readDenialLimitFallback(req);
465
461
  const askClassPair = readAskClassPair(source);
466
- const toolCallId = clip(source.toolCallId, MAX_IDENT);
467
- const sourceTaskId = clip(source.sourceTaskId, MAX_IDENT);
468
- const sourceAgentName = clip(source.sourceAgentName, MAX_AGENT_NAME);
462
+ const toolCallId = capText(source.toolCallId, MAX_IDENT);
463
+ const sourceTaskId = capText(source.sourceTaskId, MAX_IDENT);
464
+ const sourceAgentName = capText(source.sourceAgentName, MAX_AGENT_NAME);
469
465
  const allowRuleShadowed = readAllowRuleShadowed(req);
470
466
  return {
471
- toolName: clip(source.toolName, MAX_IDENT) ?? "",
472
- message: clip(source.message, MAX_MESSAGE) ?? "",
467
+ toolName: capText(source.toolName, MAX_IDENT) ?? "",
468
+ message: capText(source.message, MAX_MESSAGE) ?? "",
473
469
  ...(source.argsOmitted === true ? { argsOmitted: true } : source.args !== undefined ? { args: source.args } : {}),
474
470
  ...(toolCallId !== undefined ? { toolCallId } : {}),
475
471
  risk: {
@@ -493,9 +489,9 @@ export function buildApprovalCard(source, req, requiresRealApproval) {
493
489
  ...(source.delegation
494
490
  ? {
495
491
  delegation: {
496
- parentToolCallId: clip(source.delegation.parentToolCallId, MAX_IDENT) ?? "",
492
+ parentToolCallId: capText(source.delegation.parentToolCallId, MAX_IDENT) ?? "",
497
493
  depth: source.delegation.depth,
498
- ...(source.delegation.agentName !== undefined ? { agentName: clip(source.delegation.agentName, MAX_AGENT_NAME) ?? "" } : {}),
494
+ ...(source.delegation.agentName !== undefined ? { agentName: capText(source.delegation.agentName, MAX_AGENT_NAME) ?? "" } : {}),
499
495
  },
500
496
  }
501
497
  : {}),
@@ -532,6 +528,41 @@ export function buildApprovalRequestFrame(input) {
532
528
  expiresInMs: Math.max(0, input.expiresAtMs - input.nowMs),
533
529
  serverNowMs: input.nowMs,
534
530
  approvalId: input.approvalId,
531
+ ...pickApprovalRequestLiveFacts(input.live),
532
+ };
533
+ }
534
+ export const APPROVAL_REQUEST_LIVE_FACT_KEYS = [
535
+ "mandated",
536
+ "mandate",
537
+ "origin",
538
+ "boundGrantDigest",
539
+ "boundGrants",
540
+ "classifierNoRuling",
541
+ "boundGrantAbsence",
542
+ "approvalCard",
543
+ "readRootCandidate",
544
+ "probeReason",
545
+ ];
546
+ function pickApprovalRequestLiveFacts(src) {
547
+ const out = {};
548
+ for (const key of APPROVAL_REQUEST_LIVE_FACT_KEYS) {
549
+ const v = src[key];
550
+ if (v !== undefined)
551
+ out[key] = v;
552
+ }
553
+ return out;
554
+ }
555
+ export function buildApprovalCompleteFrame(input) {
556
+ return {
557
+ type: "approval_complete",
558
+ schemaVersion: 1,
559
+ askId: input.askId,
560
+ taskId: input.taskId,
561
+ approvalId: input.approvalId,
562
+ outcome: input.outcome,
563
+ ...(input.cause !== undefined ? { cause: input.cause } : {}),
564
+ ...(input.parked ? { parked: true } : {}),
565
+ serverNowMs: input.nowMs,
535
566
  };
536
567
  }
537
568
  export function buildRevokeFrame(batchId, askIds, reason, serverNowMs, originTaskId) {
@@ -551,7 +582,7 @@ export function buildReplayFrame(row, nowMs) {
551
582
  expiresAtMs: row.expiresAtMs,
552
583
  expiresInMs: Math.max(0, row.expiresAtMs - nowMs),
553
584
  serverNowMs: nowMs,
554
- approvalId: parsed.approvalId,
585
+ approvalId: row.askId,
555
586
  };
556
587
  }
557
588
  export function storedCardDemandsAPerson(cardJson) {
@@ -46,7 +46,7 @@ export declare const APPROVAL_ENDING_CAUSES: {
46
46
  /** 承载这张卡的流没了:断连强转 park(`parkOpenAsksForTask`,断连臂的事实 = 这个 wire run 的承载流断了;卡曾送达过,只是不会再有人从那条流上答它)。 */
47
47
  readonly STREAM_DISCONNECTED: "stream_disconnected";
48
48
  /**
49
- * 这张卡呈不出去:兜底臂(行不可用 / 身份不定 / 悬挂无行,`unattendedOutcome` 的 `persisted_row_unusable` / `ensure_indeterminate` / `unreached_no_row`)—— 持久行证不出属主或读不成,
49
+ * 这张卡呈不出去:兜底臂(行不可用 / 身份不定 / 无行且无旧族腿可呈,`unattendedOutcome` 的 `persisted_row_unusable` / `ensure_indeterminate` / `no_row_no_presenter`)—— 持久行证不出属主或读不成,
50
50
  * 本次登记根本没把卡呈到任何投递面;同 askId 的其余本地登记按这个词随行收场。与 `broadcast_lost`(emit 零接收)是两个事实。
51
51
  */
52
52
  readonly UNDELIVERABLE: "undeliverable";
@@ -184,5 +184,14 @@ export declare function createDeploymentListExemption(store: Pick<ApprovalExempt
184
184
  info(event: string, fields?: Record<string, unknown>): void;
185
185
  warn(event: string, fields?: Record<string, unknown>): void;
186
186
  }, leg?: "parked_revive"): DeploymentListExemption;
187
+ /**
188
+ * **请求叶策略:`settings.permissions.neverAuto`**(S-1351)—— 命中名单的工具恒问真人;名单外「本层没有意见」(裸 allow)。叶只管请求自己写的那张表,部署的 `APPROVAL_NEVER_AUTO`
189
+ * 在基线里({@link createDurableAskPolicy}),两者经 `tightenGoverned` 的 deny-wins 折叠取并:请求叶只会**多**问,删不掉基线里的任何一行。
190
+ *
191
+ * 名字读法与部署名单是**同一只**({@link createApprovalListVerdict} → 精确 ∪ covering,收紧臂读调用答得上的全部名字):一条规则只有一种读法。问的铸点是
192
+ * {@link requestAlwaysHumanAsk}(要真人位 + 请求出处),不是部署的 {@link operatorAlwaysHumanAsk}(那一个盖部署出身,请求里的声明冒不得)。
193
+ * `source` = 这张表在请求体里的坐标(出处进 `matchedAskRule`,审计 / 卡面据它说清是哪张表问的)。
194
+ */
195
+ export declare function createRequestNeverAutoPolicy(names: readonly string[], source: string): ToolPolicy;
187
196
  export declare function createDurableAskPolicy(opts: DurableAskOptions): ToolPolicy;
188
197
  //# sourceMappingURL=approval.d.ts.map
package/dist/approval.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { isNamespacedCoveringRuleName, namespacedRuleNameCovers } from "@sema-agent/core";
2
- import { operatorAlwaysHumanAsk, operatorAsk } from "./operator-ask.js";
2
+ import { operatorAlwaysHumanAsk, operatorAsk, requestAlwaysHumanAsk } from "./operator-ask.js";
3
3
  import { ASK_USER_QUESTION_TOOL_NAME } from "./approval-content-kind.js";
4
4
  import { isExplicitPosture } from "./posture-source.js";
5
5
  import { handsOnWorkerFilePlane } from "./execution-lane-caps.js";
@@ -37,7 +37,7 @@ export function buildNoResponderBootWarns(input) {
37
37
  out.push({
38
38
  event: "fs_write_gate_no_responder",
39
39
  fields: {
40
- hint: "host-semantics lane with no approval face: permissionMode default/auto Write/Edit asks will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
40
+ hint: "host-semantics lane with no approval face: the engine's write-gate asks (permissionMode default/auto, absent reads as default; acceptEdits outside the write roots) will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
41
41
  },
42
42
  });
43
43
  }
@@ -45,7 +45,7 @@ export function buildNoResponderBootWarns(input) {
45
45
  out.push({
46
46
  event: "workflow_gate_no_responder",
47
47
  fields: {
48
- hint: "self-orchestration with no approval face: permissionMode default/auto/acceptEdits run_workflow asks will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
48
+ hint: "self-orchestration with no approval face: run_workflow asks (every permission mode but bypassPermissions, which releases them, and dontAsk, which refuses them; absent reads as default) will auto-deny (fail-closed); wire TOOL_APPROVAL_ENABLED=true or DURABLE_APPROVAL=true to answer them",
49
49
  },
50
50
  });
51
51
  }
@@ -122,6 +122,27 @@ function createNameSetMatcher(names) {
122
122
  function grantedByRule() {
123
123
  return { action: "allow", decisionReason: "rule" };
124
124
  }
125
+ export function createRequestNeverAutoPolicy(names, source) {
126
+ const verdictOf = createApprovalListVerdict({ requireApproval: [], neverAuto: names });
127
+ return {
128
+ check: (req) => {
129
+ const verdict = verdictOf(req);
130
+ switch (verdict.list) {
131
+ case "never_auto":
132
+ return requestAlwaysHumanAsk(`${source}(${verdict.hit})`, `human approval required to run "${req.toolName}"`);
133
+ case "none":
134
+ return { action: "allow" };
135
+ case "deny":
136
+ case "require":
137
+ throw new Error(`request never-auto leaf reached a "${verdict.list}" verdict with empty deny / require lists`);
138
+ default: {
139
+ const unreachable = verdict;
140
+ throw new Error(`unhandled approval-list verdict: ${JSON.stringify(unreachable)}`);
141
+ }
142
+ }
143
+ },
144
+ };
145
+ }
125
146
  export function createDurableAskPolicy(opts) {
126
147
  const verdictOf = createApprovalListVerdict(opts);
127
148
  const budget = Math.max(0, Math.floor(opts.autoBudget ?? 0));
package/dist/audit.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type StoredPromptEpoch } from "@sema-agent/core";
1
+ import { type SessionPlacementRecord, type StoredPromptEpoch } from "@sema-agent/core";
2
2
  import type { Pool } from "mysql2/promise";
3
3
  import type { Pool as PgPool } from "pg";
4
4
  /**
@@ -29,12 +29,32 @@ export interface SessionAudit {
29
29
  * the key entirely (undefined). */
30
30
  promptEpoch?: StoredPromptEpoch;
31
31
  }
32
+ /**
33
+ * 会话视图体顶层 additive 键 `agent` —— **这只会话是哪只委派子代的转录**(`GET /v1/sessions/:id`;读法:终端侧链投影方按 fleet 帧的 `transcriptId`
34
+ * 读同一只会话读面,从体上拿到子代身份,不必再回头翻 fleet 行 —— 行一离场就没有了)。
35
+ *
36
+ * 只投影**存下来的 placement 元组**(`session_meta` 的 `placement_*` 列,首写不可变;店的 `placementOf` 一行 PK 探针),**不另铸**:
37
+ * · `id` = 元组里的 `handle` —— 耐久 agent 行的 `a…` 键,与 fleet 行的 `id`、`GET /v1/agents/roster` 的 `handle` 是同一个串(core 铸元组时 `handle: taskId`);
38
+ * · `parentSessionId` / `rootSessionId` = 元组里的同名格(派它的会话 / 委派树的根会话);
39
+ * · 元组缺哪一格这里就缺哪一格(present-iff;不铸空串);元组的 `scope`(租户键)/ `placedAt` / `kind` 不上 wire。
40
+ * 键在场 = 这是一只委派子代的转录(哪怕元组只存了 `kind`,那时 `agent` 是 `{}`);键缺席 = 普通会话,**或这台部署的店不存 placement 元组**
41
+ * (local 后端:子代转录停驻前住私有短 TTL 店、停驻时拷进来的那一份是普通会话行 —— 事实没存就不报,消费方在 fleet 行 / `GET /v1/agents/roster` 上本就有 `id`)。
42
+ * 元组由引擎在**后台**委派子代(带耐久 agent 行、店声明了 placements)建会话时铸;同步委派的子代转录不落宿主店,没有元组。
43
+ */
44
+ export interface SessionAgent {
45
+ id?: string;
46
+ parentSessionId?: string;
47
+ rootSessionId?: string;
48
+ }
49
+ /** {@link SessionAgent} 的唯一投影:店答出的 placement 元组 → 体上的 `agent` 值;`undefined`(普通会话 / 店没有这一面)⇒ 调用方不铸键。 */
50
+ export declare function sessionAgentOf(placement: SessionPlacementRecord | undefined): SessionAgent | undefined;
32
51
  /**
33
52
  * 用户消息行的**回退手柄**表:用户条目 id → 回退时交给 `resumeAt` 的那个 `event_id`(R8 用户消息锚按 run 的 taskId 键入)。
34
53
  * 真源 = `resume_anchor`(锚店 `listBySession` 的读数),本表只是它对**一位读者**的一次投影。
35
54
  */
36
55
  export type RewindHandles = ReadonlyMap<string, string>;
37
- /** 会话视图读口(`ServiceDeps.sessionAudit`)的读者参数:`reader` = 读这张视图的**已验身份**(无身份 = `null`)。给了 ⇒ 用户消息行投回退手柄。 */
56
+ /** 会话视图读口(`ServiceDeps.sessionAudit`)的读者参数:`reader` = 读这张视图的**已验身份**(无身份 = `null`)。给了 ⇒ 这是一次**视图读**:用户消息行投回退手柄、体顶层投 `agent`({@link sessionAgentOf});
57
+ * 不给(只要归属的调用方:memory-status / 自助抹除)⇒ 两样投影的读都不付。 */
38
58
  export interface SessionAuditReadOpts {
39
59
  readonly reader: string | null;
40
60
  }
@@ -53,15 +73,12 @@ export declare function buildRewindHandles(anchors: ReadonlyArray<{
53
73
  * rewind-handle projection ({@link buildRewindHandles}); absent ⇒ no `taskId` keys. */
54
74
  export declare function buildSessionAudit(pool: Pool, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
55
75
  /** The PG twin — same view over PgSessionStorage.wake. Until this, the
56
- * audit face was TiDB-only and a PG/local deployment 404'd the whole web session area. local = follow-on
57
- * (its storage seam has no wake-equivalent yet — may turn out to be a core gap). */
76
+ * audit face was TiDB-only and a PG/local deployment 404'd the whole web session area. */
58
77
  export declare function buildSessionAuditPg(pool: PgPool, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
59
- /** The LOCAL (File) leg — web session area on DB_BACKEND=local.
60
- * repo 取自 `createLocalSessionRepo`(与 `LocalSessionStore` 同一只工厂):坏记录的披露座(F 类 `server.session-repo.corrupt-record-skipped`)
61
- * 因此在视图口同样在场 —— 视图照常返回、跳过的记录有计数 + 探针行(修前自建一只不带座的 repo,零披露)。
62
- * 实现姿势:`FileSessionRepo.exportEntries`(纯读、torn-tail 恢复、missing→not_found)→
63
- * `boundedTail`(纯函数切 floor)→ InMemorySessionStorage → 同一 auditFromStorage 内核。零写面、
64
- * 零新 seam;createdAt 从 repo.list() 的 metadata 取(File 形态 meta 与 entries 分储)。 */
78
+ /** The LOCAL (File) leg — web session area on DB_BACKEND=local: the same view over `LocalSessionWindow.wake`
79
+ * (`plugins/local-session-window.ts`). All three legs read one way — a bounded window that carries the epoch anchor below its
80
+ * floor — and on every backend that is what the run reads: the SQL twins' run wakes the same window; the local run wakes the whole
81
+ * tree, and the local window is cut from that tree's branch, with the anchor walking the branch below the floor. */
65
82
  export declare function buildSessionAuditLocal(root: string, sessionId: string, handles?: RewindHandles): Promise<SessionAudit | undefined>;
66
83
  /**
67
84
  * 🔴 **会话视图的读面口 —— `GET /v1/sessions/:id` 的全部取法(整读 / `?tail` / `?before` / `?blobCap` / `?message=N`)共用这一只**。
package/dist/audit.js CHANGED
@@ -1,11 +1,20 @@
1
- import { StoredSession, InMemorySessionStorage, boundedTail } from "@sema-agent/core";
1
+ import { StoredSession } from "@sema-agent/core";
2
2
  import { TiDBSessionStorage } from "./plugins/tidb-session-storage.js";
3
3
  import { PgSessionStorage } from "./plugins/pg-session-storage.js";
4
- import { createLocalSessionRepo } from "./plugins/local-session-store.js";
4
+ import { LocalSessionWindow } from "./plugins/local-session-window.js";
5
5
  import { redactModelText } from "./observability/run-terminal.js";
6
6
  import { redactDeepWith } from "./trace/redact.js";
7
7
  import { projectToolStructured } from "./trace/tool-output-media.js";
8
8
  import { INJECTED_BLOCK_RE, isAttachmentFrame } from "./user-authored-text.js";
9
+ export function sessionAgentOf(placement) {
10
+ if (placement === undefined)
11
+ return undefined;
12
+ return {
13
+ ...(placement.handle !== undefined ? { id: placement.handle } : {}),
14
+ ...(placement.parentSessionId !== undefined ? { parentSessionId: placement.parentSessionId } : {}),
15
+ ...(placement.rootSessionId !== undefined ? { rootSessionId: placement.rootSessionId } : {}),
16
+ };
17
+ }
9
18
  export function buildRewindHandles(anchors, reader) {
10
19
  const byEntry = new Map();
11
20
  for (const a of anchors) {
@@ -26,20 +35,7 @@ export async function buildSessionAuditPg(pool, sessionId, handles) {
26
35
  return auditFromStorage(await PgSessionStorage.wake(pool, sessionId), sessionId, handles);
27
36
  }
28
37
  export async function buildSessionAuditLocal(root, sessionId, handles) {
29
- const repo = createLocalSessionRepo(root);
30
- let entries;
31
- try {
32
- entries = await repo.exportEntries(sessionId);
33
- }
34
- catch (e) {
35
- if (e.code === "not_found")
36
- return undefined;
37
- throw e;
38
- }
39
- const meta = (await repo.list()).find((m) => m.id === sessionId);
40
- const { tail, floorEntryId } = boundedTail(entries);
41
- const storage = new InMemorySessionStorage({ entries: tail, floorEntryId, ...(meta ? { metadata: meta } : {}) });
42
- return auditFromStorage(storage, sessionId, handles);
38
+ return auditFromStorage(await LocalSessionWindow.wake(root, sessionId), sessionId, handles);
43
39
  }
44
40
  async function auditFromStorage(storage, sessionId, handles) {
45
41
  if (!storage)
@@ -5,6 +5,7 @@ import { logConfigDiagnostics, parseEnvNameAllowlist, parseNumOrFailNonNegative
5
5
  import { installSecretEnvScrubRecorder } from "../observability/secret-env-scrub.js";
6
6
  import { declareServerWithheldEnv, hostSubprocessEnv } from "../server-secret-env.js";
7
7
  import { shellQuote as shellSafe } from "../plugins/remote-shell.js";
8
+ import { echoCallerText } from "../caller-text-echo.js";
8
9
  import { BakeRunner, } from "./runner.js";
9
10
  const BAKE_CLAIM_INGEST_FETCH_TIMEOUT_MS = 30_000;
10
11
  const BAKE_HEARTBEAT_FETCH_TIMEOUT_MS = 10_000;
@@ -181,9 +182,9 @@ export async function execGroup(cmd, timeoutMs, envAllow) {
181
182
  try {
182
183
  const { code, signal } = await child.exited;
183
184
  if (timedOut)
184
- throw new Error(`host exec timed out after ${timeoutMs}ms (group killed): ${cmd.slice(0, 120)}`);
185
+ throw new Error(`host exec timed out after ${timeoutMs}ms (group killed): ${echoCallerText(cmd, { maxChars: 120 })}`);
185
186
  if (code !== 0)
186
- throw new Error(`host exec exited ${code ?? signal}: ${cmd.slice(0, 120)}${stderr.trim() ? ` — ${stderr.trim().slice(-400)}` : ""}`);
187
+ throw new Error(`host exec exited ${code ?? signal}: ${echoCallerText(cmd, { maxChars: 120 })}${stderr.trim() ? ` — ${stderr.trim().slice(-400)}` : ""}`);
187
188
  return { stdout };
188
189
  }
189
190
  finally {
@@ -118,7 +118,7 @@ export class DeferredSandboxPathEnv extends StubExecutionEnv {
118
118
  reason: found.reason,
119
119
  face,
120
120
  sessionId: this.sessionId ?? null,
121
- note: "the sandbox fs-write gate has no task environment to adjudicate against — every write target fails closed (ask, and deny under the sensitive-path set) until one is bound",
121
+ note: "the sandbox path adjudication has no task environment to read — the sensitive-path guard fails closed (deny) on every write target until one is bound",
122
122
  });
123
123
  }
124
124
  return {