@sema-agent/server 7.131.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 (509) hide show
  1. package/MIGRATION.md +575 -0
  2. package/README.md +12 -9
  3. package/README.zh-CN.md +9 -6
  4. package/USAGE.md +326 -98
  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 +82 -20
  24. package/dist/approval-card.js +46 -16
  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 +33 -19
  29. package/dist/audit.js +12 -16
  30. package/dist/auth-bridge.d.ts +4 -0
  31. package/dist/auth-bridge.js +10 -11
  32. package/dist/bake-runner/main.js +3 -2
  33. package/dist/boot/deferred-sandbox-path-env.js +1 -1
  34. package/dist/boot/deployment-mods.d.ts +31 -0
  35. package/dist/boot/deployment-mods.js +26 -0
  36. package/dist/boot/execution-env.d.ts +1 -1
  37. package/dist/boot/execution-env.js +27 -12
  38. package/dist/boot/execution-lane.js +11 -0
  39. package/dist/boot/leader.js +2 -0
  40. package/dist/boot/memory-boundary.d.ts +2 -2
  41. package/dist/boot/memory-boundary.js +2 -2
  42. package/dist/boot/memory-consolidation.d.ts +5 -4
  43. package/dist/boot/memory-consolidation.js +7 -6
  44. package/dist/boot/org-delivery.d.ts +28 -0
  45. package/dist/boot/org-delivery.js +20 -0
  46. package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
  47. package/dist/boot/read-deny-anchor-audit.js +36 -0
  48. package/dist/boot/reapers.d.ts +3 -0
  49. package/dist/boot/reapers.js +21 -1
  50. package/dist/boot/resolve-spec.d.ts +4 -5
  51. package/dist/boot/resolve-spec.js +74 -123
  52. package/dist/boot/runner-deps.d.ts +19 -8
  53. package/dist/boot/runner-deps.js +15 -2
  54. package/dist/boot/session-faces.d.ts +2 -7
  55. package/dist/boot/session-faces.js +4 -2
  56. package/dist/boot/stage-02-web-admin-pull.js +4 -1
  57. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  58. package/dist/boot/stage-03-store-backend.js +2 -2
  59. package/dist/boot/stage-04-stores.d.ts +1 -1
  60. package/dist/boot/stage-05-execution-env.d.ts +4 -4
  61. package/dist/boot/stage-05-execution-env.js +7 -10
  62. package/dist/boot/stage-06-runners.d.ts +4 -2
  63. package/dist/boot/stage-06-runners.js +11 -7
  64. package/dist/boot/stage-07-capability-layer.d.ts +4 -2
  65. package/dist/boot/stage-07-capability-layer.js +27 -6
  66. package/dist/boot/stage-08-reapers.d.ts +4 -2
  67. package/dist/boot/stage-08-reapers.js +2 -2
  68. package/dist/boot/stage-09-leader.d.ts +6 -9
  69. package/dist/boot/stage-10-http-server.d.ts +6 -9
  70. package/dist/boot/stage-10-http-server.js +7 -9
  71. package/dist/boot/stores.d.ts +1 -1
  72. package/dist/boot/stores.js +7 -8
  73. package/dist/boot/web-admin.d.ts +4 -3
  74. package/dist/boot/web-admin.js +186 -98
  75. package/dist/boot/workflow-orchestration.d.ts +2 -0
  76. package/dist/boot/workflow-orchestration.js +2 -1
  77. package/dist/brain.js +25 -25
  78. package/dist/breaker-key.d.ts +6 -0
  79. package/dist/breaker-key.js +29 -0
  80. package/dist/budget.js +5 -4
  81. package/dist/caller-text-echo.d.ts +23 -0
  82. package/dist/caller-text-echo.js +21 -0
  83. package/dist/capabilities/brand-identity.d.ts +26 -0
  84. package/dist/capabilities/brand-identity.js +27 -0
  85. package/dist/capabilities/center-plugins.d.ts +7 -0
  86. package/dist/capabilities/center-plugins.js +1 -1
  87. package/dist/capabilities/center-prompts.d.ts +32 -59
  88. package/dist/capabilities/center-prompts.js +18 -32
  89. package/dist/capabilities/composite-members.d.ts +1 -1
  90. package/dist/capabilities/composite-members.js +1 -1
  91. package/dist/capabilities/engine-capabilities.js +2 -1
  92. package/dist/capabilities/execution-lane.js +2 -2
  93. package/dist/capabilities/hands-lane.d.ts +30 -6
  94. package/dist/capabilities/hands-lane.js +11 -1
  95. package/dist/capabilities/mcp-probe.d.ts +48 -3
  96. package/dist/capabilities/mcp-probe.js +47 -135
  97. package/dist/capabilities/scenarios.d.ts +95 -45
  98. package/dist/capabilities/scenarios.js +53 -38
  99. package/dist/capabilities/skills.d.ts +19 -4
  100. package/dist/capabilities/skills.js +30 -10
  101. package/dist/capability-facts.d.ts +34 -4
  102. package/dist/capability-facts.js +28 -2
  103. package/dist/center-config-tier.d.ts +69 -0
  104. package/dist/center-config-tier.js +42 -0
  105. package/dist/checkpoint-identity.d.ts +16 -0
  106. package/dist/checkpoint-identity.js +19 -0
  107. package/dist/config-catalog.d.ts +17 -10
  108. package/dist/config-catalog.js +47 -32
  109. package/dist/config-d-migration.d.ts +3 -1
  110. package/dist/config-d-migration.js +2 -2
  111. package/dist/config-dir-trust.d.ts +114 -0
  112. package/dist/config-dir-trust.js +388 -0
  113. package/dist/config-invariants.d.ts +18 -5
  114. package/dist/config-invariants.js +35 -3
  115. package/dist/config-lkg.d.ts +9 -9
  116. package/dist/config-lkg.js +20 -4
  117. package/dist/config-provider.d.ts +9 -2
  118. package/dist/config-provider.js +18 -6
  119. package/dist/config-types.d.ts +75 -20
  120. package/dist/config-types.js +8 -0
  121. package/dist/config.d.ts +13 -0
  122. package/dist/config.js +137 -62
  123. package/dist/delegated-session-owner.d.ts +185 -0
  124. package/dist/delegated-session-owner.js +119 -0
  125. package/dist/device-protocol.d.ts +5 -3
  126. package/dist/device-protocol.js +1 -1
  127. package/dist/device-ws-hub.js +21 -2
  128. package/dist/device-ws-protocol.d.ts +70 -6
  129. package/dist/device-ws-protocol.js +50 -22
  130. package/dist/elicitation.js +3 -2
  131. package/dist/entry-problems.d.ts +34 -0
  132. package/dist/entry-problems.js +14 -0
  133. package/dist/env-name-allowlist-knobs.d.ts +12 -2
  134. package/dist/env-name-allowlist-knobs.js +5 -4
  135. package/dist/exec-bounds.d.ts +15 -3
  136. package/dist/exec-bounds.js +4 -0
  137. package/dist/execution-lane-caps.d.ts +56 -10
  138. package/dist/execution-lane-caps.js +50 -0
  139. package/dist/field-conflict.d.ts +43 -0
  140. package/dist/field-conflict.js +20 -0
  141. package/dist/fleet/fleet-bus.d.ts +80 -6
  142. package/dist/fleet/fleet-bus.js +41 -9
  143. package/dist/hooks/classic-stations.d.ts +91 -0
  144. package/dist/hooks/classic-stations.js +27 -0
  145. package/dist/hooks/command-spawn.d.ts +57 -0
  146. package/dist/hooks/command-spawn.js +139 -0
  147. package/dist/hooks/hook-llm.d.ts +8 -5
  148. package/dist/hooks/hook-llm.js +79 -36
  149. package/dist/hooks/hook-runner.d.ts +349 -95
  150. package/dist/hooks/hook-runner.js +855 -568
  151. package/dist/hooks/hook-source.d.ts +44 -0
  152. package/dist/hooks/hook-source.js +40 -0
  153. package/dist/http/active-run-conflict.d.ts +5 -13
  154. package/dist/http/active-run-conflict.js +17 -27
  155. package/dist/http/admission.d.ts +8 -2
  156. package/dist/http/admission.js +188 -101
  157. package/dist/http/approval-sweeps.js +99 -21
  158. package/dist/http/caller-trust.d.ts +77 -0
  159. package/dist/http/caller-trust.js +143 -0
  160. package/dist/http/checkpoint-ctx.d.ts +41 -24
  161. package/dist/http/checkpoint-ctx.js +23 -16
  162. package/dist/http/claimed-run.d.ts +14 -0
  163. package/dist/http/claimed-run.js +15 -0
  164. package/dist/http/device-placement.d.ts +2 -4
  165. package/dist/http/device-placement.js +7 -11
  166. package/dist/http/dispatch.d.ts +0 -4
  167. package/dist/http/dispatch.js +15 -13
  168. package/dist/http/durable-run-leg.d.ts +6 -33
  169. package/dist/http/durable-run-leg.js +36 -10
  170. package/dist/http/health-self-report.d.ts +7 -5
  171. package/dist/http/health-self-report.js +4 -18
  172. package/dist/http/owner-access.d.ts +56 -0
  173. package/dist/http/owner-access.js +42 -0
  174. package/dist/http/principal-gate.d.ts +70 -28
  175. package/dist/http/principal-gate.js +61 -15
  176. package/dist/http/readiness.d.ts +11 -5
  177. package/dist/http/readiness.js +10 -3
  178. package/dist/http/refusal-body.d.ts +21 -0
  179. package/dist/http/refusal-body.js +4 -0
  180. package/dist/http/request-guards.d.ts +43 -23
  181. package/dist/http/request-guards.js +53 -17
  182. package/dist/http/resume-ctx-read.d.ts +2 -5
  183. package/dist/http/resume-ctx-read.js +7 -4
  184. package/dist/http/resume-legs.d.ts +28 -4
  185. package/dist/http/resume-legs.js +169 -91
  186. package/dist/http/retired-service-deps.d.ts +43 -0
  187. package/dist/http/retired-service-deps.js +18 -0
  188. package/dist/http/route-ctx.d.ts +44 -28
  189. package/dist/http/route-ctx.js +4 -0
  190. package/dist/http/route-table.js +2 -0
  191. package/dist/http/routes/a2a-serve.js +3 -4
  192. package/dist/http/routes/admin-config-refresh.js +1 -1
  193. package/dist/http/routes/admin-drain.js +1 -1
  194. package/dist/http/routes/admin-memory-optout.js +5 -1
  195. package/dist/http/routes/adoption.js +2 -9
  196. package/dist/http/routes/approvals-assistant.js +49 -48
  197. package/dist/http/routes/background.js +3 -2
  198. package/dist/http/routes/capabilities.js +21 -5
  199. package/dist/http/routes/config-catalog.d.ts +3 -3
  200. package/dist/http/routes/config-catalog.js +1 -1
  201. package/dist/http/routes/devices.js +3 -17
  202. package/dist/http/routes/diagnostics.js +6 -2
  203. package/dist/http/routes/images.js +6 -7
  204. package/dist/http/routes/leader.js +1 -8
  205. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  206. package/dist/http/routes/mcp-reconnect.js +3 -2
  207. package/dist/http/routes/memory-bundle.js +1 -1
  208. package/dist/http/routes/memory-compliance.js +1 -1
  209. package/dist/http/routes/memory-consolidation.js +1 -1
  210. package/dist/http/routes/memory-origin.js +1 -1
  211. package/dist/http/routes/memory-policy.d.ts +1 -1
  212. package/dist/http/routes/memory-policy.js +3 -2
  213. package/dist/http/routes/notify-wake.js +8 -21
  214. package/dist/http/routes/observability.js +2 -2
  215. package/dist/http/routes/principal-inbox.d.ts +39 -0
  216. package/dist/http/routes/principal-inbox.js +76 -0
  217. package/dist/http/routes/retention-ops.js +2 -9
  218. package/dist/http/routes/rules.js +5 -18
  219. package/dist/http/routes/runs.d.ts +5 -0
  220. package/dist/http/routes/runs.js +34 -107
  221. package/dist/http/routes/session-sync.js +15 -26
  222. package/dist/http/routes/sessions.js +30 -40
  223. package/dist/http/routes/shared-memory.js +2 -13
  224. package/dist/http/routes/side-query.js +8 -7
  225. package/dist/http/routes/tasks.js +67 -21
  226. package/dist/http/routes/workflows.d.ts +351 -0
  227. package/dist/http/routes/workflows.js +153 -119
  228. package/dist/http/send.d.ts +33 -10
  229. package/dist/http/send.js +21 -4
  230. package/dist/http/server.d.ts +27 -18
  231. package/dist/http/server.js +34 -6
  232. package/dist/http/stored-body-replay.js +17 -4
  233. package/dist/http/submit-ctx.d.ts +25 -0
  234. package/dist/http/submit-ctx.js +40 -0
  235. package/dist/http/submit-replay.d.ts +4 -3
  236. package/dist/http/submit-replay.js +5 -4
  237. package/dist/http/wire-types.d.ts +11 -8
  238. package/dist/index.d.ts +2 -2
  239. package/dist/index.js +1 -2
  240. package/dist/lane-home-probe.d.ts +112 -0
  241. package/dist/lane-home-probe.js +101 -0
  242. package/dist/leader/endpoint.d.ts +4 -1
  243. package/dist/leader/endpoint.js +11 -10
  244. package/dist/limit-refusal.d.ts +59 -0
  245. package/dist/limit-refusal.js +15 -0
  246. package/dist/main.js +1 -1
  247. package/dist/mcp-assertion-header.d.ts +32 -19
  248. package/dist/mcp-assertion-header.js +10 -9
  249. package/dist/mcp-tool-faces.d.ts +5 -0
  250. package/dist/mcp-tool-faces.js +6 -4
  251. package/dist/memory-project-layer.d.ts +37 -0
  252. package/dist/memory-project-layer.js +46 -0
  253. package/dist/memory-scope.d.ts +24 -17
  254. package/dist/memory-scope.js +24 -8
  255. package/dist/memory-sync-client.d.ts +27 -13
  256. package/dist/memory-sync-client.js +107 -18
  257. package/dist/model-entry-refusal.d.ts +9 -1
  258. package/dist/model-entry-refusal.js +6 -1
  259. package/dist/model-plane-face.d.ts +51 -0
  260. package/dist/model-plane-face.js +24 -0
  261. package/dist/model-provider.d.ts +44 -12
  262. package/dist/model-provider.js +21 -2
  263. package/dist/model-route-endpoint.d.ts +9 -12
  264. package/dist/model-route-endpoint.js +8 -11
  265. package/dist/model-route-env.d.ts +22 -0
  266. package/dist/model-route-env.js +2 -0
  267. package/dist/model-route-gap.d.ts +60 -30
  268. package/dist/model-route-gap.js +21 -15
  269. package/dist/observability/corrupt-read-seat.d.ts +7 -0
  270. package/dist/observability/corrupt-read-seat.js +9 -0
  271. package/dist/observability/cost-taxonomy.d.ts +7 -7
  272. package/dist/observability/err-text.d.ts +6 -0
  273. package/dist/observability/err-text.js +18 -4
  274. package/dist/observability/fail-open.d.ts +76 -14
  275. package/dist/observability/fail-open.js +76 -14
  276. package/dist/observability/metrics.js +4 -1
  277. package/dist/observability/prompt-manifest.d.ts +33 -82
  278. package/dist/observability/prompt-manifest.js +122 -17
  279. package/dist/observability/run-terminal.js +14 -6
  280. package/dist/observability/secret-env-scrub.d.ts +13 -1
  281. package/dist/observability/secret-env-scrub.js +13 -1
  282. package/dist/observability/tool-trace.d.ts +16 -21
  283. package/dist/observability/tool-trace.js +58 -49
  284. package/dist/operator-ask.d.ts +10 -0
  285. package/dist/operator-ask.js +3 -0
  286. package/dist/orchestration/workflow-agent-session-index.d.ts +12 -12
  287. package/dist/orchestration/workflow-agent-session-index.js +9 -13
  288. package/dist/orchestration/workflow-completion-inbox.d.ts +42 -15
  289. package/dist/orchestration/workflow-completion-inbox.js +13 -0
  290. package/dist/orchestration/workflow-notify-journal.d.ts +13 -32
  291. package/dist/orchestration/workflow-notify-journal.js +27 -34
  292. package/dist/orchestration/workflow-park-decision.d.ts +89 -0
  293. package/dist/orchestration/workflow-park-decision.js +118 -0
  294. package/dist/org-delivery-gate.d.ts +81 -0
  295. package/dist/org-delivery-gate.js +59 -0
  296. package/dist/panel-tool-names.d.ts +23 -0
  297. package/dist/panel-tool-names.js +8 -0
  298. package/dist/parked-decide.d.ts +39 -6
  299. package/dist/parked-decide.js +98 -51
  300. package/dist/parked-revive-surface.d.ts +9 -2
  301. package/dist/parked-revive-surface.js +11 -8
  302. package/dist/per-task-image.d.ts +7 -1
  303. package/dist/per-task-image.js +3 -3
  304. package/dist/permission-rule-list.d.ts +1 -1
  305. package/dist/permission-rule-list.js +2 -2
  306. package/dist/plain-string-record.d.ts +25 -0
  307. package/dist/plain-string-record.js +32 -0
  308. package/dist/plugins/approval-ask-store-file.d.ts +16 -1
  309. package/dist/plugins/approval-ask-store-file.js +21 -0
  310. package/dist/plugins/approval-ask-store-memory.d.ts +18 -1
  311. package/dist/plugins/approval-ask-store-memory.js +34 -2
  312. package/dist/plugins/approval-ask-store-sql.d.ts +25 -0
  313. package/dist/plugins/approval-ask-store-sql.js +37 -1
  314. package/dist/plugins/blob-backend.d.ts +83 -15
  315. package/dist/plugins/blob-backend.js +68 -15
  316. package/dist/plugins/breaker-state-sql.d.ts +2 -2
  317. package/dist/plugins/breaker-state-sql.js +4 -4
  318. package/dist/plugins/caching-session-store.d.ts +3 -0
  319. package/dist/plugins/caching-session-store.js +3 -0
  320. package/dist/plugins/checkpoint-store-sql.d.ts +28 -4
  321. package/dist/plugins/checkpoint-store-sql.js +59 -28
  322. package/dist/plugins/file-history-store-sql.d.ts +5 -2
  323. package/dist/plugins/file-history-store-sql.js +3 -1
  324. package/dist/plugins/file-run-store.d.ts +5 -13
  325. package/dist/plugins/file-run-store.js +9 -0
  326. package/dist/plugins/fork-routing-session-store.d.ts +9 -1
  327. package/dist/plugins/fork-routing-session-store.js +12 -1
  328. package/dist/plugins/host-platform.d.ts +2 -0
  329. package/dist/plugins/host-platform.js +2 -1
  330. package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
  331. package/dist/plugins/k8s-bg-scripts.js +22 -0
  332. package/dist/plugins/local-checkpoint-store.d.ts +2 -0
  333. package/dist/plugins/local-checkpoint-store.js +11 -3
  334. package/dist/plugins/local-session-store.d.ts +1 -1
  335. package/dist/plugins/local-session-store.js +1 -1
  336. package/dist/plugins/local-session-window.d.ts +39 -0
  337. package/dist/plugins/local-session-window.js +54 -0
  338. package/dist/plugins/mailbox-recipient-lifecycle.d.ts +3 -2
  339. package/dist/plugins/mailbox-store-sql.d.ts +30 -48
  340. package/dist/plugins/mailbox-store-sql.js +77 -52
  341. package/dist/plugins/memory-embedder-fingerprint.js +2 -1
  342. package/dist/plugins/memory-run-store.d.ts +5 -13
  343. package/dist/plugins/memory-run-store.js +8 -0
  344. package/dist/plugins/one-time-migrations.d.ts +245 -93
  345. package/dist/plugins/one-time-migrations.js +668 -207
  346. package/dist/plugins/org-delivery-quota-store.d.ts +123 -0
  347. package/dist/plugins/org-delivery-quota-store.js +228 -0
  348. package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
  349. package/dist/plugins/permission-rule-store-sql.js +4 -18
  350. package/dist/plugins/pg-pool.js +39 -7
  351. package/dist/plugins/pg-session-storage.d.ts +20 -8
  352. package/dist/plugins/pg-session-storage.js +34 -21
  353. package/dist/plugins/remote-env-adb.d.ts +12 -12
  354. package/dist/plugins/remote-env-adb.js +21 -6
  355. package/dist/plugins/remote-env-device.js +3 -0
  356. package/dist/plugins/remote-env-e2b.d.ts +1 -1
  357. package/dist/plugins/remote-env-e2b.js +21 -9
  358. package/dist/plugins/remote-env-host.d.ts +9 -9
  359. package/dist/plugins/remote-env-host.js +10 -32
  360. package/dist/plugins/remote-env-k8s.d.ts +103 -38
  361. package/dist/plugins/remote-env-k8s.js +288 -95
  362. package/dist/plugins/remote-env-local-docker.d.ts +27 -13
  363. package/dist/plugins/remote-env-local-docker.js +82 -11
  364. package/dist/plugins/remote-env-ssh.d.ts +21 -12
  365. package/dist/plugins/remote-env-ssh.js +117 -5
  366. package/dist/plugins/remote-shell.d.ts +0 -1
  367. package/dist/plugins/remote-shell.js +1 -2
  368. package/dist/plugins/retention-store-sql.js +6 -2
  369. package/dist/plugins/run-store-sql.d.ts +16 -14
  370. package/dist/plugins/run-store-sql.js +22 -2
  371. package/dist/plugins/schema-consistency.d.ts +54 -0
  372. package/dist/plugins/schema-consistency.js +52 -0
  373. package/dist/plugins/schema-indexes.js +2 -0
  374. package/dist/plugins/send-user-file.js +2 -2
  375. package/dist/plugins/session-epoch-anchor.d.ts +39 -0
  376. package/dist/plugins/session-epoch-anchor.js +22 -0
  377. package/dist/plugins/session-store.d.ts +18 -8
  378. package/dist/plugins/session-store.js +15 -4
  379. package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
  380. package/dist/plugins/shared-memory-store-sql.js +5 -16
  381. package/dist/plugins/sql-driver.d.ts +205 -1
  382. package/dist/plugins/sql-driver.js +325 -13
  383. package/dist/plugins/sql-errors.d.ts +64 -0
  384. package/dist/plugins/sql-errors.js +57 -0
  385. package/dist/plugins/store-backend.d.ts +36 -1
  386. package/dist/plugins/store-backend.js +42 -15
  387. package/dist/plugins/store-contracts.d.ts +42 -0
  388. package/dist/plugins/store-contracts.js +1 -0
  389. package/dist/plugins/tidb-pool.d.ts +6 -1
  390. package/dist/plugins/tidb-pool.js +44 -10
  391. package/dist/plugins/tidb-session-storage.d.ts +8 -11
  392. package/dist/plugins/tidb-session-storage.js +6 -16
  393. package/dist/plugins/tidb-session-store.d.ts +24 -4
  394. package/dist/plugins/tidb-session-store.js +29 -5
  395. package/dist/plugins/workflow-journal-store-sql.d.ts +73 -19
  396. package/dist/plugins/workflow-journal-store-sql.js +19 -6
  397. package/dist/plugins/workflow-run-store-sql.d.ts +30 -8
  398. package/dist/plugins/workflow-run-store-sql.js +50 -9
  399. package/dist/posture-source.d.ts +18 -10
  400. package/dist/posture-source.js +4 -1
  401. package/dist/project-identity.d.ts +45 -6
  402. package/dist/project-identity.js +162 -8
  403. package/dist/project-layer-key.d.ts +28 -0
  404. package/dist/project-layer-key.js +29 -0
  405. package/dist/prompts-domain-validate.d.ts +17 -61
  406. package/dist/prompts-domain-validate.js +9 -119
  407. package/dist/question.js +3 -2
  408. package/dist/read-deny-entry.d.ts +25 -0
  409. package/dist/read-deny-entry.js +12 -0
  410. package/dist/read-face-posture.d.ts +37 -11
  411. package/dist/read-face-posture.js +32 -3
  412. package/dist/request-key-closure.d.ts +9 -2
  413. package/dist/request-key-closure.js +11 -5
  414. package/dist/request-value-closure.d.ts +5 -0
  415. package/dist/request-value-closure.js +11 -3
  416. package/dist/rule-entry-list.d.ts +38 -11
  417. package/dist/rule-entry-list.js +106 -30
  418. package/dist/rules-consent.js +3 -4
  419. package/dist/run-acceptance.d.ts +19 -3
  420. package/dist/run-acceptance.js +13 -1
  421. package/dist/run-local.js +54 -24
  422. package/dist/runs.d.ts +15 -8
  423. package/dist/runs.js +35 -1
  424. package/dist/runtime-caps-resolver.d.ts +16 -6
  425. package/dist/runtime-caps-resolver.js +18 -5
  426. package/dist/sandbox-pkg-source.d.ts +19 -1
  427. package/dist/sandbox-pkg-source.js +29 -7
  428. package/dist/security.d.ts +87 -9
  429. package/dist/security.js +52 -9
  430. package/dist/server-secret-env.d.ts +44 -18
  431. package/dist/server-secret-env.js +49 -8
  432. package/dist/session-error-wire.d.ts +19 -2
  433. package/dist/session-error-wire.js +5 -1
  434. package/dist/session-incarnation.d.ts +15 -5
  435. package/dist/session-incarnation.js +16 -9
  436. package/dist/session-titled-frame.d.ts +33 -0
  437. package/dist/session-titled-frame.js +4 -0
  438. package/dist/session-titler.d.ts +9 -1
  439. package/dist/session-titler.js +27 -6
  440. package/dist/spec-fields.d.ts +28 -16
  441. package/dist/spec-fields.js +66 -54
  442. package/dist/sql-engine-posture.d.ts +31 -4
  443. package/dist/sql-engine-posture.js +36 -1
  444. package/dist/stored-request-tool-axes-m19.d.ts +19 -4
  445. package/dist/stored-request-tool-axes-m19.js +30 -2
  446. package/dist/task-a2a.d.ts +9 -1
  447. package/dist/task-a2a.js +73 -47
  448. package/dist/task-cwd.d.ts +1 -1
  449. package/dist/task-mcp.d.ts +46 -58
  450. package/dist/task-mcp.js +82 -107
  451. package/dist/task-settings.d.ts +95 -108
  452. package/dist/task-settings.js +77 -98
  453. package/dist/text-bidi.d.ts +1 -48
  454. package/dist/text-bidi.js +3 -5
  455. package/dist/tighten-only-seats.d.ts +150 -0
  456. package/dist/tighten-only-seats.js +196 -0
  457. package/dist/tool-approval.d.ts +304 -88
  458. package/dist/tool-approval.js +623 -239
  459. package/dist/trace/core-keyset-guard.d.ts +122 -20
  460. package/dist/trace/engine-notice-wire.d.ts +11 -3
  461. package/dist/trace/engine-notice-wire.js +8 -1
  462. package/dist/trace/exit-seat.d.ts +28 -0
  463. package/dist/trace/exit-seat.js +76 -0
  464. package/dist/trace/ledger-events.d.ts +6 -3
  465. package/dist/trace/ledger-sink.js +4 -1
  466. package/dist/trace/model-segment.js +1 -1
  467. package/dist/trace/project.d.ts +98 -17
  468. package/dist/trace/project.js +98 -50
  469. package/dist/trace/projection-table.d.ts +100 -0
  470. package/dist/trace/projection-table.js +130 -0
  471. package/dist/trace/redact.d.ts +54 -0
  472. package/dist/trace/redact.js +778 -152
  473. package/dist/trace/self-minted-wire.d.ts +345 -1
  474. package/dist/trace/self-minted-wire.js +117 -1
  475. package/dist/trace/wire-projection-faces.d.ts +377 -3
  476. package/dist/trace/wire-projection-faces.js +164 -1
  477. package/dist/url-refusal.js +2 -0
  478. package/dist/web-admin-client/apply-effective.d.ts +12 -0
  479. package/dist/web-admin-client/apply-effective.js +56 -5
  480. package/dist/web-admin-client/candidate-gate.d.ts +6 -6
  481. package/dist/web-admin-client/candidate-gate.js +3 -3
  482. package/dist/web-admin-client/facade.d.ts +1 -1
  483. package/dist/web-admin-client/facade.js +1 -1
  484. package/dist/web-admin-client/http-client.js +0 -6
  485. package/dist/web-admin-client/read-face.js +5 -9
  486. package/dist/web-admin-client/read-warnings.d.ts +13 -0
  487. package/dist/web-admin-client/read-warnings.js +10 -0
  488. package/dist/web-admin-client/skills-mcp.d.ts +3 -0
  489. package/dist/web-admin-client/skills-mcp.js +11 -9
  490. package/dist/web-admin-client/types.d.ts +2 -3
  491. package/dist/workspace-cache.d.ts +35 -0
  492. package/dist/workspace-cache.js +36 -0
  493. package/dist/workspace-space.d.ts +3 -2
  494. package/dist/workspace-space.js +2 -0
  495. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +65 -10
  496. package/package.json +8 -4
  497. package/scripts/drain-check-local.mjs +34 -1
  498. package/scripts/drain-check.mysql.sql +30 -2
  499. package/scripts/drain-check.pg.sql +29 -2
  500. package/dist/capabilities/memory-notice.d.ts +0 -138
  501. package/dist/capabilities/memory-notice.js +0 -64
  502. package/dist/capabilities/prompt.d.ts +0 -17
  503. package/dist/capabilities/prompt.js +0 -6
  504. package/dist/mcp-content-origin.d.ts +0 -34
  505. package/dist/mcp-content-origin.js +0 -10
  506. package/dist/tool-axis-words.d.ts +0 -27
  507. package/dist/tool-axis-words.js +0 -9
  508. package/dist/wire-name-bound.d.ts +0 -14
  509. package/dist/wire-name-bound.js +0 -13
@@ -1,13 +1,16 @@
1
1
  import { emitLeafAdvance } from "../session-leaf-bus.js";
2
- import { BaseSessionStorage, StoredSession, SessionError, uuidv7, validateEntriesForImport, leafIdAfterEntry, normalizePromptEpoch, } from "@sema-agent/core";
2
+ import { BaseSessionStorage, StoredSession, SessionError, uuidv7, validateEntriesForImport, leafIdAfterEntry, } from "@sema-agent/core";
3
3
  import { SESSION_TITLE_MAX_CHARS } from "../session-row.js";
4
4
  import { escapeLike } from "./sql-escape.js";
5
5
  import { decodeSessionEventPayload } from "./session-event-payload.js";
6
+ import { scanEpochAnchor } from "./session-epoch-anchor.js";
6
7
  import { jsonColumnText } from "./sql-json-column.js";
7
8
  import { pgSafeJsonStringify } from "./pg-safe-json.js";
8
9
  import { toIso } from "./sql-row-helpers.js";
9
10
  import { assertPlacementAdmission, LIST_PLACED_BATCH, PLACEMENT_SELECT_COLUMNS, placedRowFromRow, placementFromRow, placementInsertValues, SQL_SESSION_PLACEMENTS, } from "./session-placement.js";
10
11
  import { contentForkRelation, fastForwardSharedContentDiverged } from "../session-sync-content.js";
12
+ import { CLAIM_OWNERLESS_PLACED_SQL, claimOwnerlessParams, createPlacedSessionRow } from "../delegated-session-owner.js";
13
+ import { createLogger } from "../observability/logger.js";
11
14
  import { classifySyncRelationshipByIds, SyncConflictError, stagingIdFor, STAGING_ID_MARKER, STAGING_GC_GRACE_MS, } from "../session-sync-kernel.js";
12
15
  import { isPgUniqueViolation } from "./sql-errors.js";
13
16
  import { BASELINE_IO_DEADLINE_MS, decodeInstructionSource, encodeInstructionSource } from "../instruction-source-notice.js";
@@ -82,21 +85,10 @@ export class PgSessionStorage extends BaseSessionStorage {
82
85
  this.floorSeq = floorSeq;
83
86
  }
84
87
  async getEpochAnchor() {
85
- if (this.floorSeq <= 0)
86
- return undefined;
87
- let cursor = this.floorSeq;
88
- for (;;) {
89
- const res = await this.pool.query(`SELECT seq, ${jsonColumnText("pg", "payload")} FROM session_event WHERE session_id = $1 AND seq < $2 AND type IN ('prompt_epoch','compaction') ORDER BY seq DESC LIMIT 100`, [this.sessionId, cursor]);
90
- if (res.rows.length === 0)
91
- return undefined;
92
- for (const r of res.rows) {
93
- const e = decodeSessionEventPayload(r.payload, this.sessionId, r.seq);
94
- const d = e.type === "prompt_epoch" ? normalizePromptEpoch(e) : normalizePromptEpoch(e.details?.promptEpoch);
95
- if (d)
96
- return d;
97
- }
98
- cursor = Number(res.rows[res.rows.length - 1].seq);
99
- }
88
+ return scanEpochAnchor(this.floorSeq, async (beforeSeq) => {
89
+ const res = await this.pool.query(`SELECT seq, ${jsonColumnText("pg", "payload")} FROM session_event WHERE session_id = $1 AND seq < $2 AND type IN ('prompt_epoch','compaction') ORDER BY seq DESC LIMIT 100`, [this.sessionId, beforeSeq]);
90
+ return res.rows;
91
+ }, (row) => decodeSessionEventPayload(row.payload, this.sessionId, row.seq));
100
92
  }
101
93
  static async wake(pool, sessionId) {
102
94
  const metaRes = await pool.query(`SELECT created_at, leaf_id, leaf_seq, incarnation, ${PLACEMENT_SELECT_COLUMNS} FROM session_meta WHERE session_id = $1`, [sessionId]);
@@ -185,13 +177,15 @@ export class PgSessionStore {
185
177
  retention = MANAGED_RETENTION;
186
178
  placements = SQL_SESSION_PLACEMENTS;
187
179
  pending = new Map();
188
- constructor(pool) {
180
+ log;
181
+ constructor(pool, opts = {}) {
189
182
  this.pool = pool;
183
+ this.log = opts.log ?? createLogger();
190
184
  }
191
185
  async acquire(sessionId, opts) {
192
186
  if (!sessionId) {
193
187
  const id = uuidv7();
194
- await this.register(id, null, opts?.placement);
188
+ await this.createOnAcquire(id, opts?.placement);
195
189
  return this.load(id, false, opts);
196
190
  }
197
191
  if (opts?.requireExisting)
@@ -214,7 +208,7 @@ export class PgSessionStore {
214
208
  }
215
209
  if (requireExisting)
216
210
  throw new SessionError("not_found", `session ${sessionId} not found`);
217
- await this.register(sessionId, null, opts?.placement);
211
+ await this.createOnAcquire(sessionId, opts?.placement);
218
212
  storage = await PgSessionStorage.wake(this.pool, sessionId);
219
213
  if (!storage) {
220
214
  throw new SessionError("storage", `session ${sessionId} vanished between register and wake (a concurrent purge won the race) — retry`);
@@ -222,7 +216,26 @@ export class PgSessionStore {
222
216
  assertPlacementAdmission(sessionId, (await storage.getMetadata()).placement, opts);
223
217
  return { session: new StoredSession(storage), sessionId };
224
218
  }
225
- async register(sessionId, owner, placement) {
219
+ async register(sessionId, owner) {
220
+ await this.insertMeta(sessionId, owner, undefined);
221
+ }
222
+ async createOnAcquire(sessionId, placement) {
223
+ if (placement === undefined)
224
+ return this.insertMeta(sessionId, null, undefined);
225
+ await createPlacedSessionRow(sessionId, placement, {
226
+ readFaces: (ids) => this.sourceFaces(ids),
227
+ insert: (owner) => this.insertMeta(sessionId, owner, placement),
228
+ readOwner: () => this.ownerOf(sessionId),
229
+ }, this.log);
230
+ }
231
+ async claimOwnerless(sessionId, incarnation, owner) {
232
+ return ((await this.pool.query(CLAIM_OWNERLESS_PLACED_SQL.pg, [...claimOwnerlessParams(sessionId, incarnation, owner)])).rowCount ?? 0) > 0;
233
+ }
234
+ async sourceFaces(ids) {
235
+ const res = await this.pool.query(`SELECT session_id, owner, incarnation FROM session_meta WHERE session_id IN (${ids.map((_, i) => `$${i + 1}`).join(", ")})`, [...ids]);
236
+ return new Map(res.rows.map((r) => [String(r.session_id), sessionFaceFromRow(String(r.session_id), r.owner ?? null, r.incarnation)]));
237
+ }
238
+ async insertMeta(sessionId, owner, placement) {
226
239
  const now = new Date();
227
240
  await this.pool.query("INSERT INTO session_meta (session_id, owner, created_at, updated_at, leaf_id, leaf_seq, incarnation, " +
228
241
  "placement_kind, placement_scope, placement_parent_session_id, placement_root_session_id, placement_handle, placed_at) " +
@@ -516,7 +529,7 @@ export class PgSessionStore {
516
529
  }
517
530
  await conn.query("DELETE FROM session_event WHERE session_id = $1", [sessionId]);
518
531
  await conn.query("DELETE FROM session_meta WHERE session_id = $1 AND owner IS NOT DISTINCT FROM $2 AND placement_kind IS NULL", [sessionId, owner]);
519
- await this.insertValidatedLog(conn, sessionId, owner, validated, carriedIncarnation(placedRes.rows[0], owner));
532
+ await this.insertValidatedLog(conn, sessionId, owner, validated, carriedIncarnation(sessionId, placedRes.rows[0], owner));
520
533
  await conn.query("COMMIT");
521
534
  }
522
535
  catch (err) {
@@ -1,20 +1,12 @@
1
1
  import { spawn } from "node:child_process";
2
+ import { type LaneHomeConfig } from "../lane-home-probe.js";
2
3
  import { FileError, ExecutionError, RemoteExecutionError, type ExecutionEnv, type RemoteExecutionEnv, type WorkspaceHandle, type FileInfo, type Result, type SymlinkChain, type OutputChunk, type ExecStreamOptions, type RemoteConnectConfig, type SnapshotId, type SessionToken, type VmLifecycleOptions, type ExecutionEnvFactory } from "@sema-agent/core";
3
4
  type ExecOpts = Parameters<ExecutionEnv["exec"]>[1];
4
- export interface AdbEnvConfig {
5
+ export interface AdbEnvConfig extends LaneHomeConfig {
5
6
  /** Device serial or `host:port` (TCP). `host:port` triggers `adb connect` on connect()/reconnect(). */
6
7
  serial: string;
7
8
  /** Path to the adb binary. Default "adb" (must be on PATH in the runner image). */
8
9
  adbPath?: string;
9
- /**
10
- * S-213④ / core [ref] —— 本执行环境的 **home 目录**(`ExecutionEnv.homeDir` 座,绝对路径,本环境自己的
11
- * 命名空间里)。`~/…` 形权限规则(`Edit(~/.ssh/**)`)对**跑在本 env 里的调用**就以它为基。
12
- * 缺席 ⇒ 本 env 声明「我没有 home」,core 对 `~/` 规则判 `unreadable`(fail-closed 的 ask),
13
- * 绝不回落引擎进程自己的 home(那在远端腿上是另一个用户的另一个目录 —— 静默守错目录正是 [ref] 的病)。
14
- * 值由 `boot/execution-env.ts` 从**唯一属主** `execution-lane-caps.ts` 的 `executionLaneHomeDir` 递进来;
15
- * adapter 不自算(两处各算一份 = 422 门与引擎对同一条规则给相反答案)。
16
- */
17
- homeDir?: string;
18
10
  /** On-device workspace root; relative paths resolve against it. Default "/data/local/tmp". */
19
11
  mountPath?: string;
20
12
  commandTimeoutMs?: number;
@@ -86,8 +78,10 @@ export declare class RemoteAdbExecutionEnv implements RemoteExecutionEnv {
86
78
  private destroyed;
87
79
  /** 在飞的那一次懒连接(单飞记忆)——见 {@link ensureConnected}。settle 即清,**不缓存败诺**。 */
88
80
  private connectPromise?;
89
- /** core `ExecutionEnv.homeDir`([ref]):本沙箱/目标机上执行用户的 home。见配置同名字段。 */
90
- readonly homeDir?: string | undefined;
81
+ /** core `ExecutionEnv.homeDir`([ref]):设备 shell 里执行用户的 home —— 声明胜,否则首连时 `adb shell` 实测的 `$HOME`(Android 常为 `/` 或 `/data/local/tmp` 一类,读到什么填什么,绝对即可),见 {@link LaneHomeSeat}。读时才取(没声明时连上之前缺席)。 */
82
+ get homeDir(): string | undefined;
83
+ /** 家目录的座(声明胜 · 否则首连时实测 · 实测缺席 ⇒ 缺席 + 一行 warn)。本车道**不对证**声明:Android 没有 POSIX 登录家目录,声明是运维的断言,照单全收。 */
84
+ private readonly homeSeat;
91
85
  /** core 7.49.0 #1554:shell 子进程真拿到的 `CDPATH` 条目 —— 本车道的命令跑在 Android 设备的 shell 里(设备自己的 env),本类不读那份 env ⇒ `"unknown"`(core 契约:说不出就说 unknown,
92
86
  * 不许报一张没读过的空表;删除守卫因此对裸 `cd <相对名>` 之后的删除问人,而不是按「没有 CDPATH」放行)。 */
93
87
  readonly cdPath: "unknown";
@@ -204,6 +198,12 @@ export declare class RemoteAdbExecutionEnv implements RemoteExecutionEnv {
204
198
  suffix?: string;
205
199
  abortSignal?: AbortSignal;
206
200
  }): Promise<Result<string, FileError>>;
201
+ /**
202
+ * 交给宿主 `adb` CLI 的 env —— 宿主子进程 env 的唯一组合(`server-secret-env.ts` `hostSubprocessEnv`),继承词 `"all"`:本服务自有凭据(起服声明的名与值)
203
+ * 任何词都不交,adb 自己要读的变量(`ADB_VENDOR_KEYS` / `ANDROID_*` …)照交 —— 形状剥会剥 `ADB_VENDOR_KEYS`(名形),设备鉴权因此断。首次调用拉起的常驻 adb server
204
+ * 继承的就是这一份。命令本身跑在设备的 shell 里,本 env 到不了设备。每次起进程现算一次(与 host shell 同)。
205
+ */
206
+ private cliEnv;
207
207
  /** Spawn the adb binary with the given args; collect stdout/stderr (+ raw bytes when binary), bound by timeout/abort. */
208
208
  private adb;
209
209
  /**
@@ -2,9 +2,11 @@ import path from "node:path";
2
2
  import os from "node:os";
3
3
  import fs from "node:fs/promises";
4
4
  import { spawn } from "node:child_process";
5
+ import { hostSubprocessEnv } from "../server-secret-env.js";
6
+ import { LANE_HOME_PROBE_COMMAND, LaneHomeSeat } from "../lane-home-probe.js";
5
7
  import { buildCwdEnvCommand, createCwdGuardedCall, shellQuote, armPipeDestroyGrace } from "./remote-shell.js";
6
8
  import { signalNumber } from "./host-platform.js";
7
- import { commandBoundsOf, livenessCutMessage } from "../exec-bounds.js";
9
+ import { buildLivenessCut, commandBoundsOf } from "../exec-bounds.js";
8
10
  import { FileError, ExecutionError, RemoteExecutionError, withRetry, RollingTailBuffer, markTruncated, } from "@sema-agent/core";
9
11
  import { classifyFsStderr, fileErrorFromExec } from "./remote-env-file-error.js";
10
12
  import { createPosixShellFs } from "./posix-shell-fs.js";
@@ -30,7 +32,10 @@ export class RemoteAdbExecutionEnv {
30
32
  connected = false;
31
33
  destroyed = false;
32
34
  connectPromise;
33
- homeDir;
35
+ get homeDir() {
36
+ return this.homeSeat.home;
37
+ }
38
+ homeSeat;
34
39
  cdPath = "unknown";
35
40
  cfg;
36
41
  spawnFn;
@@ -45,7 +50,7 @@ export class RemoteAdbExecutionEnv {
45
50
  retry: { maxAttempts: config.retry?.maxAttempts ?? 3, backoffMs: config.retry?.backoffMs ?? 800 },
46
51
  };
47
52
  this.cwd = this.cfg.mountPath;
48
- this.homeDir = config.homeDir;
53
+ this.homeSeat = new LaneHomeSeat({ lane: PROVIDER, declared: config.homeDir, verifiesDeclared: false, onAbsent: config.onHomeAbsent });
49
54
  this.spawnFn = deps?.spawn ?? spawn;
50
55
  this.injectedConnectOnce = deps?.connectOnce;
51
56
  }
@@ -116,6 +121,12 @@ export class RemoteAdbExecutionEnv {
116
121
  error: new RemoteExecutionError("unsupported", `device ${this.cfg.serial} does not advertise the 'shell_v2' feature, so this adapter cannot establish that its command round-trip carries a real exit code with stderr kept separate — the two properties every filesystem judgment on this lane depends on to tell failure from success. Refusing to connect rather than run on an unverifiable transport: attach a device that supports adb shell protocol v2.`),
117
122
  };
118
123
  }
124
+ if (this.homeSeat.asks) {
125
+ const home = await this.adb(this.deviceShellArgs(LANE_HOME_PROBE_COMMAND), { signal, timeoutMs: this.cfg.commandTimeoutMs });
126
+ if (!home.ok && home.error.code === "aborted")
127
+ return { ok: false, error: new RemoteExecutionError("aborted", "connect aborted while reading the device's home") };
128
+ this.homeSeat.settle(home.ok && home.value.exitCode === 0 ? { ok: true, stdout: home.value.stdout } : { ok: false, reason: home.ok ? `exit ${home.value.exitCode}` : home.error.message });
129
+ }
119
130
  this.connected = true;
120
131
  return ok(this.workspaceHandle());
121
132
  }
@@ -180,7 +191,7 @@ export class RemoteAdbExecutionEnv {
180
191
  if (this.destroyed)
181
192
  throw new RemoteExecutionError("connect_failed", "execution env already destroyed");
182
193
  const wrapped = buildCwdEnvCommand(command, this.workingDirOf(options?.cwd), options?.env, "raw").command;
183
- const child = this.spawnFn(this.cfg.adbPath, this.deviceShellArgs(wrapped), { stdio: ["ignore", "pipe", "pipe"] });
194
+ const child = this.spawnFn(this.cfg.adbPath, this.deviceShellArgs(wrapped), { stdio: ["ignore", "pipe", "pipe"], env: this.cliEnv() });
184
195
  const queue = [];
185
196
  let finished = false;
186
197
  let failure;
@@ -276,7 +287,8 @@ export class RemoteAdbExecutionEnv {
276
287
  clearTimeout(waitTimer);
277
288
  }
278
289
  if (liveness !== undefined && !finished && Date.now() - lastChunk >= liveness.ms) {
279
- throw new RemoteExecutionError("timeout", livenessCutMessage(liveness));
290
+ const cut = buildLivenessCut(liveness);
291
+ throw new RemoteExecutionError(cut.code, cut.message);
280
292
  }
281
293
  }
282
294
  while (queue.length)
@@ -417,13 +429,16 @@ export class RemoteAdbExecutionEnv {
417
429
  async createTempFile(options) {
418
430
  return this.posixFs.createTempFile(options);
419
431
  }
432
+ cliEnv() {
433
+ return hostSubprocessEnv({ site: "server.remote-env-adb.spawn-env", policy: "all", allow: [] });
434
+ }
420
435
  adb(args, opts) {
421
436
  if (this.destroyed)
422
437
  return Promise.resolve({ ok: false, error: new ExecutionError("shell_unavailable", "execution env already destroyed") });
423
438
  return new Promise((resolve) => {
424
439
  let settled = false;
425
440
  let forceSettleTimer;
426
- const child = this.spawnFn(this.cfg.adbPath, args, { stdio: ["ignore", "pipe", "pipe"] });
441
+ const child = this.spawnFn(this.cfg.adbPath, args, { stdio: ["ignore", "pipe", "pipe"], env: this.cliEnv() });
427
442
  const killGrace = () => {
428
443
  try {
429
444
  child.kill("SIGKILL");
@@ -12,6 +12,7 @@ export const DEVICE_OUTCOME_TO_FILE_ERROR = {
12
12
  callback_error: "unknown",
13
13
  invalid: "invalid",
14
14
  is_directory: "is_directory",
15
+ liveness_no_output: "unknown",
15
16
  not_directory: "not_directory",
16
17
  not_found: "not_found",
17
18
  not_supported: "not_supported",
@@ -33,6 +34,7 @@ export const DEVICE_OUTCOME_TO_EXEC_ERROR = {
33
34
  callback_error: "callback_error",
34
35
  invalid: "unknown",
35
36
  is_directory: "unknown",
37
+ liveness_no_output: "liveness_no_output",
36
38
  not_directory: "unknown",
37
39
  not_found: "unknown",
38
40
  not_supported: "shell_unavailable",
@@ -763,6 +765,7 @@ const OUTCOME_TO_REMOTE_ERROR = {
763
765
  callback_error: "unknown",
764
766
  invalid: "unknown",
765
767
  is_directory: "unknown",
768
+ liveness_no_output: "liveness_no_output",
766
769
  not_directory: "unknown",
767
770
  not_found: "unknown",
768
771
  not_supported: "unsupported",
@@ -321,7 +321,7 @@ export declare class RemoteContainerExecutionEnv implements RemoteExecutionEnv,
321
321
  * a command that hangs DURING execution (not creation) would otherwise wait the E2B command timeout (= the
322
322
  * lifetime when none is set, the original hang bug). With a `liveness` bound (the caller stated no `timeout` —
323
323
  * `exec-bounds.ts`) it races wait() against an idle check: no stdout/stderr for `liveness.ms` ⇒ hung → kill + typed
324
- * retryable "timeout" with the shared cut sentence. `lastProgress()` is bumped by the stdout/stderr callbacks, so a
324
+ * retryable `liveness_no_output` (the shared cut: code, sentence and the window in whole seconds — `buildLivenessCut`). `lastProgress()` is bumped by the stdout/stderr callbacks, so a
325
325
  * slow-but-PROGRESSING command (long `npm ci`) is never killed. Both cuts reject with an `ExecutionError` carrying
326
326
  * its real code (exec returns it as-is) — a `RemoteExecutionError` here would reach {@link execError}'s text match
327
327
  * and land as `unknown`. The rejection is armed BEFORE the kill: the kill rejects `wait()` too, and the race must
@@ -3,7 +3,7 @@ import { Sandbox, CommandExitError, FileType } from "e2b";
3
3
  import { FileError, ExecutionError, RemoteExecutionError, RollingTailBuffer, markTruncated, } from "@sema-agent/core";
4
4
  import { fileErrorFromExec } from "./remote-env-file-error.js";
5
5
  import { numEnvOr, runSymlinkChain, shellQuote } from "./remote-shell.js";
6
- import { commandBoundsOf, firstBoundOf, laneLivenessOf, livenessCutMessage, LIVENESS_MS_DEFAULT } from "../exec-bounds.js";
6
+ import { buildLivenessCut, commandBoundsOf, firstBoundOf, laneLivenessOf, LIVENESS_MS_DEFAULT } from "../exec-bounds.js";
7
7
  import { BackgroundShellManager } from "./background-shell-support.js";
8
8
  const PROVIDER = "e2b";
9
9
  const DEFAULT_MOUNT_PATH = "/home/user";
@@ -297,7 +297,10 @@ export class RemoteContainerExecutionEnv {
297
297
  startCut = true;
298
298
  this.settleAbandonedStart(starting);
299
299
  const cut = e instanceof RemoteExecutionError && e.code === "timeout" && !options?.abortSignal?.aborted;
300
- return { ok: false, error: cut ? new ExecutionError("timeout", boundCutMessage(first)) : this.execError(e, options?.abortSignal) };
300
+ if (!cut)
301
+ return { ok: false, error: this.execError(e, options?.abortSignal) };
302
+ const bc = boundCut(first);
303
+ return { ok: false, error: new ExecutionError(bc.code, bc.message, undefined, undefined, bc.noOutputSec) };
301
304
  }
302
305
  const onAbort = () => { if (!detached)
303
306
  void handle.kill().catch(() => { }); };
@@ -425,8 +428,10 @@ export class RemoteContainerExecutionEnv {
425
428
  catch (e) {
426
429
  finished = true;
427
430
  this.settleAbandonedStart(starting);
428
- if (e instanceof RemoteExecutionError && e.code === "timeout" && !options?.signal?.aborted)
429
- throw new RemoteExecutionError("timeout", boundCutMessage(first), e);
431
+ if (e instanceof RemoteExecutionError && e.code === "timeout" && !options?.signal?.aborted) {
432
+ const bc = boundCut(first);
433
+ throw new RemoteExecutionError(bc.code, bc.message, e);
434
+ }
430
435
  throw this.remoteError(e, "connect_failed");
431
436
  }
432
437
  handle
@@ -490,7 +495,10 @@ export class RemoteContainerExecutionEnv {
490
495
  const idle = liveness === undefined
491
496
  ? undefined
492
497
  : new Promise((_, reject) => {
493
- timer = setTimeout(() => reject(new RemoteExecutionError("timeout", livenessCutMessage(liveness))), liveness.ms);
498
+ timer = setTimeout(() => {
499
+ const cut = buildLivenessCut(liveness);
500
+ reject(new RemoteExecutionError(cut.code, cut.message));
501
+ }, liveness.ms);
494
502
  });
495
503
  try {
496
504
  await (idle === undefined ? next : Promise.race([next, idle]));
@@ -850,7 +858,8 @@ export class RemoteContainerExecutionEnv {
850
858
  return;
851
859
  const idleFor = Date.now() - lastProgress();
852
860
  if (idleFor >= bound.ms) {
853
- reject(new ExecutionError("timeout", livenessCutMessage(bound)));
861
+ const cut = buildLivenessCut(bound);
862
+ reject(new ExecutionError(cut.code, cut.message, undefined, undefined, cut.noOutputSec));
854
863
  void handle.kill().catch(() => { });
855
864
  this.cfg.metrics?.inc("remote_env_exec_idle_timeout_total", { provider: PROVIDER });
856
865
  }
@@ -866,7 +875,7 @@ export class RemoteContainerExecutionEnv {
866
875
  wallTimer = setTimeout(() => {
867
876
  if (opts.disarmed?.())
868
877
  return;
869
- reject(new ExecutionError("timeout", boundCutMessage({ ms: wall.totalMs, cut: "wall" })));
878
+ reject(new ExecutionError("timeout", wallCutMessage(wall.totalMs)));
870
879
  void handle.kill().catch(() => { });
871
880
  }, wall.leftMs);
872
881
  }
@@ -969,8 +978,11 @@ export function e2bExecutionEnvFactory(config, deps) {
969
978
  function errMsg(e) {
970
979
  return e instanceof Error ? e.message : String(e);
971
980
  }
972
- function boundCutMessage(first) {
973
- return first.cut === "wall" ? `exec exceeded ${first.ms}ms` : livenessCutMessage(first.cut);
981
+ function wallCutMessage(ms) {
982
+ return `exec exceeded ${ms}ms`;
983
+ }
984
+ function boundCut(first) {
985
+ return first.cut === "wall" ? { code: "timeout", message: wallCutMessage(first.ms) } : buildLivenessCut(first.cut);
974
986
  }
975
987
  function providerTimedOut(e) {
976
988
  return e?.name === "TimeoutError" || /timeout|timed out/i.test(errMsg(e));
@@ -314,17 +314,17 @@ export declare class RemoteHostExecutionEnv implements RemoteExecutionEnv, Sched
314
314
  canonicalPath(p: string, abortSignal?: AbortSignal): Promise<Result<string, FileError>>;
315
315
  readLink(p: string, abortSignal?: AbortSignal): Promise<Result<string, FileError>>;
316
316
  /**
317
- * S-362 / core 7.21.0 [ref] —— **实现**(表态:本腿实现 `canonicalChain`)。host 腿是 node:fs 腿,所以按
318
- * 提货单 [ref] @server 五适配器段的第一行,与 core 的 `NodeExecutionEnv.canonicalChain` **同形**:对整条
319
- * 拼法 `readlink`,再对每一跳 `readlink`,**上限 64**、**只锚不折**、**遇环即止**;win32 宿主上跳到共享
320
- * (UNC)时**记下该跳并停止探测**(不碰网络,CC `vr` 对网络拼法只给拼法)。
317
+ * S-362 / core 7.21.0 [ref] —— **实现**(表态:本腿实现 `canonicalChain`)。host 腿是 node:fs 腿:走法(对整条拼法 `readlink`、再对每一跳
318
+ * `readlink`,**上限**、**只锚不折**、**遇环即止**、win32 宿主上跳到共享(UNC)时**记下该跳并停止探测** —— 不碰网络)是 core 导出的
319
+ * `walkSymlinkChain`,本腿只供它**逐跳的读口**;上限、播种、锚法、UNC 判都在那一只里,本仓不再重写第二遍。
321
320
  *
322
- * 🔴 **不复用 core 的实现而是同形重写**:`NodeExecutionEnv` 是 core 的内部类,包根不导出它的这只方法;
323
- * 而本腿的每一次读都必须先过 {@link fsReady}(2026-07-25 全族统一:拆除之后只读面不得与写面自相矛盾),
324
- * 那道门在 core 的实现里不存在。同形的判据钉在 `test/remote-env-canonical-chain.test.ts`。
321
+ * 🔴 为什么本腿仍自备读口而不是整体复用 core 的 `NodeExecutionEnv.canonicalChain`:本腿的每一次读都必须先过 {@link fsReady}
322
+ * (2026-07-25 全族统一:拆除之后只读面不得与写面自相矛盾),那道门在 core 的实现里不存在 —— 门在**起点**过一次,读口不再逐跳过
323
+ * (中途 destroy 不改变「这一次链读」的读数:每跳是同一次往返里对本机盘的读,与旧循环逐字同姿势)。
325
324
  *
326
- * 链尽的三种 errno(`EINVAL` 不是软链 / `ENOENT` 不存在 / `ENOTDIR`)⇒ `ok` + 到此为止的跳;其余 errno
327
- * (`EACCES` …)⇒ `ok:false`(core 读作「这一次没有跳」,**永不是拒绝**)。非链接的叶答 `[]`。
325
+ * 链尽的三种 errno(`EINVAL` 不是软链 / `ENOENT` 不存在 / `ENOTDIR`)由本腿的 `fileError` 归成 `invalid` / `not_found` / `not_directory`,
326
+ * core 的走法读作「到此为止」⇒ `ok` + 到此为止的跳;其余 errno(`EACCES` …)⇒ `ok:false`(core 读作「这一次没有跳」,**永不是拒绝**)。
327
+ * 非链接的叶答 `[]`。同形的判据钉在 `test/remote-env-canonical-chain.test.ts`,「读 core 导出」的钉在 `test/core-export-single-source-*.test.ts`。
328
328
  */
329
329
  canonicalChain(p: string, abortSignal?: AbortSignal): Promise<Result<SymlinkChain, FileError>>;
330
330
  exists(p: string, abortSignal?: AbortSignal): Promise<Result<boolean, FileError>>;
@@ -5,12 +5,12 @@ import fs from "node:fs/promises";
5
5
  import { randomBytes } from "node:crypto";
6
6
  import { openSync, closeSync, readSync, statSync, truncateSync, unlinkSync, mkdirSync, rmdirSync, mkdtempSync, existsSync, realpathSync, accessSync, constants as FS_CONST } from "node:fs";
7
7
  import { StringDecoder } from "node:string_decoder";
8
- import { armPipeDestroyGrace, numEnvOr, SYMLINK_CHAIN_MAX_HOPS } from "./remote-shell.js";
9
- import { commandBoundsOf, livenessCutMessage } from "../exec-bounds.js";
8
+ import { armPipeDestroyGrace, numEnvOr } from "./remote-shell.js";
9
+ import { buildLivenessCut, commandBoundsOf } from "../exec-bounds.js";
10
10
  import { hostBackgroundShellEnabled, hostExecSpoolEnabled } from "../config.js";
11
11
  import { IS_WIN32, resolveHostShell, hostShell, pinHostShell, spawnGroupOptions, killTreeHard, killTreeSoft, hardKillGroupNow, collapseWin32EnvKeys, adoptHostForegroundChild } from "./host-platform.js";
12
12
  import { BackgroundShellManager, seedMemStream, feedMemStream, drainMemStream } from "./background-shell-support.js";
13
- import { FileError, NodeExecutionEnv, inheritEnvPolicyProblem, ExecutionError, RemoteExecutionError, RollingTailBuffer, markTruncated, SchedulerError, BackgroundShellError, } from "@sema-agent/core";
13
+ import { FileError, NodeExecutionEnv, inheritEnvPolicyProblem, ExecutionError, RemoteExecutionError, RollingTailBuffer, walkSymlinkChain, markTruncated, SchedulerError, BackgroundShellError, } from "@sema-agent/core";
14
14
  import { composeHostSubprocessEnv, hostSubprocessEnv } from "../server-secret-env.js";
15
15
  import { trackEphemeralHostWorkspace, untrackEphemeralHostWorkspace } from "./host-workspace-registry.js";
16
16
  const PROVIDER = "host";
@@ -24,7 +24,6 @@ const HOST_BG_FILE_CAP = numEnvOr("HOST_BG_FILE_CAP", 64 * 1024 * 1024, HOST_BG_
24
24
  export const HOST_BG_KILL_GRACE_MS = numEnvOr("HOST_BG_KILL_GRACE_MS", 1000, 0);
25
25
  const HOST_BG_MEM_CAP = numEnvOr("HOST_BG_MEM_CAP", 8 * 1024 * 1024, 64 * 1024);
26
26
  const ok = (value) => ({ ok: true, value });
27
- const UNC_SPELLING = /^[\\/]{2}[^\\/]+[\\/]+[^\\/]/;
28
27
  const unsupported = (op) => ({
29
28
  ok: false,
30
29
  error: new RemoteExecutionError("unsupported", `${op} is not supported on a host target (the operator's own machine — no container boundary, not snapshotable; capabilities.suspendable=false)`),
@@ -919,7 +918,8 @@ export class RemoteHostExecutionEnv {
919
918
  if (liveness !== undefined && !finished && Date.now() - lastChunk >= liveness.ms) {
920
919
  finished = true;
921
920
  kill();
922
- throw new RemoteExecutionError("timeout", livenessCutMessage(liveness));
921
+ const cut = buildLivenessCut(liveness);
922
+ throw new RemoteExecutionError(cut.code, cut.message);
923
923
  }
924
924
  }
925
925
  while (queue.length)
@@ -1099,36 +1099,14 @@ export class RemoteHostExecutionEnv {
1099
1099
  const ready = await this.fsReady(p);
1100
1100
  if (!ready.ok)
1101
1101
  return ready;
1102
- const hops = [];
1103
- let cur = this.resolve(p);
1104
- const seen = new Set([cur]);
1105
- for (let i = 0; i < SYMLINK_CHAIN_MAX_HOPS; i += 1) {
1106
- let target;
1102
+ return walkSymlinkChain(this.resolve(p), async (hop) => {
1107
1103
  try {
1108
- target = await fs.readlink(cur);
1104
+ return ok(await fs.readlink(hop));
1109
1105
  }
1110
1106
  catch (e) {
1111
- const fe = this.fileError(e, cur, abortSignal);
1112
- if (fe.code === "invalid" || fe.code === "not_found" || fe.code === "not_directory")
1113
- break;
1114
- return { ok: false, error: fe };
1107
+ return { ok: false, error: this.fileError(e, hop, abortSignal) };
1115
1108
  }
1116
- let next;
1117
- if (path.isAbsolute(target))
1118
- next = target;
1119
- else {
1120
- const dir = path.dirname(cur);
1121
- next = dir.endsWith(path.sep) ? `${dir}${target}` : `${dir}${path.sep}${target}`;
1122
- }
1123
- if (seen.has(next))
1124
- break;
1125
- seen.add(next);
1126
- hops.push(next);
1127
- if (IS_WIN32 && UNC_SPELLING.test(next))
1128
- break;
1129
- cur = next;
1130
- }
1131
- return ok({ hops });
1109
+ });
1132
1110
  }
1133
1111
  async exists(p, abortSignal) {
1134
1112
  const ready = await this.fsReady(p);
@@ -1325,7 +1303,7 @@ export class RemoteHostExecutionEnv {
1325
1303
  }
1326
1304
  childEnv(perCommand, spawnShell) {
1327
1305
  const base = spawnShell !== undefined
1328
- ? hostSubprocessEnv({ site: "server.remote-env-host.inherit-scrub", policy: this.cfg.inheritEnv, allow: [] })
1306
+ ? hostSubprocessEnv({ site: "server.remote-env-host.spawn-env", policy: this.cfg.inheritEnv, allow: [] })
1329
1307
  : composeHostSubprocessEnv({ policy: this.cfg.inheritEnv, allow: [] });
1330
1308
  if (this.cfg.env)
1331
1309
  Object.assign(base, this.cfg.env);