@sema-agent/server 7.148.0 → 7.149.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 (247) hide show
  1. package/MIGRATION.md +429 -0
  2. package/README.md +16 -1
  3. package/README.zh-CN.md +4 -0
  4. package/USAGE.md +89 -55
  5. package/dist/adoption/wire.d.ts +3 -3
  6. package/dist/approval-card.d.ts +32 -32
  7. package/dist/approval-leg-origin.d.ts +33 -0
  8. package/dist/approval-leg-origin.js +4 -0
  9. package/dist/auth-bridge.d.ts +9 -1
  10. package/dist/auth-bridge.js +4 -4
  11. package/dist/auth-keys.d.ts +10 -1
  12. package/dist/auth-keys.js +8 -0
  13. package/dist/boot/execution-env.js +10 -11
  14. package/dist/boot/execution-lane.d.ts +6 -4
  15. package/dist/boot/execution-lane.js +3 -1
  16. package/dist/boot/org-delivery.d.ts +3 -2
  17. package/dist/boot/resolve-spec.js +6 -4
  18. package/dist/boot/runner-deps.js +3 -1
  19. package/dist/boot/stage-01-config.d.ts +1 -0
  20. package/dist/boot/stage-01-config.js +4 -3
  21. package/dist/boot/stage-02-web-admin-pull.d.ts +1 -0
  22. package/dist/boot/stage-02-web-admin-pull.js +10 -2
  23. package/dist/boot/stage-03-store-backend.d.ts +1 -0
  24. package/dist/boot/stage-03-store-backend.js +2 -2
  25. package/dist/boot/stage-04-stores.d.ts +1 -0
  26. package/dist/boot/stage-05-execution-env.d.ts +1 -0
  27. package/dist/boot/stage-06-runners.d.ts +2 -1
  28. package/dist/boot/stage-07-capability-layer.d.ts +2 -1
  29. package/dist/boot/stage-08-reapers.d.ts +2 -1
  30. package/dist/boot/stage-09-leader.d.ts +2 -1
  31. package/dist/boot/stage-10-http-server.d.ts +2 -1
  32. package/dist/boot/stores.d.ts +3 -0
  33. package/dist/boot/stores.js +22 -19
  34. package/dist/capabilities/tool-defer.d.ts +1 -1
  35. package/dist/capability-facts.d.ts +5 -4
  36. package/dist/capability-facts.js +3 -14
  37. package/dist/card-settle-stored-scope.d.ts +56 -0
  38. package/dist/card-settle-stored-scope.js +27 -0
  39. package/dist/card-void.d.ts +7 -12
  40. package/dist/card-void.js +2 -7
  41. package/dist/config-catalog.d.ts +12 -0
  42. package/dist/config-catalog.js +36 -32
  43. package/dist/config-invariants.d.ts +5 -4
  44. package/dist/config-invariants.js +4 -4
  45. package/dist/config-types.d.ts +37 -5
  46. package/dist/config.d.ts +6 -5
  47. package/dist/config.js +35 -24
  48. package/dist/context-window-notice.d.ts +31 -0
  49. package/dist/context-window-notice.js +28 -0
  50. package/dist/deployment-shape.d.ts +20 -11
  51. package/dist/deployment-shape.js +1 -0
  52. package/dist/env-name-allowlist-knobs.d.ts +6 -5
  53. package/dist/env-name-allowlist-knobs.js +5 -0
  54. package/dist/execution-lane-caps.d.ts +20 -5
  55. package/dist/execution-lane-caps.js +18 -4
  56. package/dist/hooks/command-spawn.d.ts +7 -2
  57. package/dist/hooks/command-spawn.js +13 -6
  58. package/dist/hooks/hook-runner.d.ts +5 -0
  59. package/dist/hooks/hook-runner.js +11 -7
  60. package/dist/http/admission.js +3 -3
  61. package/dist/http/approval-sweeps.js +3 -2
  62. package/dist/http/claim-heartbeat.d.ts +3 -3
  63. package/dist/http/claim-heartbeat.js +3 -3
  64. package/dist/http/claimed-run.d.ts +16 -9
  65. package/dist/http/claimed-run.js +8 -0
  66. package/dist/http/dispatch.js +5 -3
  67. package/dist/http/durable-run-leg.d.ts +8 -1
  68. package/dist/http/durable-run-leg.js +30 -11
  69. package/dist/http/execution-context.d.ts +115 -14
  70. package/dist/http/execution-context.js +130 -40
  71. package/dist/http/owner-access.d.ts +3 -2
  72. package/dist/http/owner-access.js +2 -3
  73. package/dist/http/principal-gate.d.ts +18 -11
  74. package/dist/http/principal-gate.js +3 -1
  75. package/dist/http/resume-ctx-read.d.ts +14 -3
  76. package/dist/http/resume-ctx-read.js +8 -2
  77. package/dist/http/resume-legs.d.ts +35 -3
  78. package/dist/http/resume-legs.js +244 -92
  79. package/dist/http/route-ctx.d.ts +6 -0
  80. package/dist/http/routes/a2a-serve.js +2 -0
  81. package/dist/http/routes/approvals-assistant.js +3 -2
  82. package/dist/http/routes/capabilities.js +1 -1
  83. package/dist/http/routes/diagnostics.d.ts +3 -1
  84. package/dist/http/routes/diagnostics.js +30 -5
  85. package/dist/http/routes/principal-inbox.d.ts +3 -1
  86. package/dist/http/routes/principal-inbox.js +3 -2
  87. package/dist/http/routes/runs.js +10 -7
  88. package/dist/http/routes/session-sync.d.ts +24 -5
  89. package/dist/http/routes/session-sync.js +46 -34
  90. package/dist/http/routes/sessions-list.d.ts +1 -1
  91. package/dist/http/routes/tasks.js +127 -93
  92. package/dist/http/server.d.ts +4 -5
  93. package/dist/http/server.js +30 -5
  94. package/dist/http/submit-ctx.d.ts +1 -0
  95. package/dist/http/submit-ctx.js +2 -3
  96. package/dist/index.d.ts +3 -1
  97. package/dist/index.js +1 -0
  98. package/dist/leg-facts.d.ts +7 -2
  99. package/dist/leg-facts.js +1 -0
  100. package/dist/local-store-declaration.d.ts +54 -0
  101. package/dist/local-store-declaration.js +59 -0
  102. package/dist/mcp-assertion-header.d.ts +1 -1
  103. package/dist/mcp-assertion-header.js +1 -1
  104. package/dist/memory-project-layer.js +1 -1
  105. package/dist/memory-scope.d.ts +4 -4
  106. package/dist/memory-scope.js +4 -4
  107. package/dist/memory-sync-client.js +2 -2
  108. package/dist/model-context-window.d.ts +50 -11
  109. package/dist/model-context-window.js +20 -1
  110. package/dist/model-entry-refusal.d.ts +5 -4
  111. package/dist/model-entry-refusal.js +17 -3
  112. package/dist/model-reach-scope.d.ts +2 -1
  113. package/dist/observability/fail-open.d.ts +14 -2
  114. package/dist/observability/fail-open.js +14 -2
  115. package/dist/observability/metrics.js +1 -1
  116. package/dist/observability/run-terminal.js +1 -0
  117. package/dist/observability/secret-env-scrub.d.ts +1 -1
  118. package/dist/observability/secret-env-scrub.js +1 -1
  119. package/dist/org-delivery-gate.d.ts +31 -6
  120. package/dist/org-delivery-gate.js +7 -4
  121. package/dist/owner-faces.d.ts +3 -2
  122. package/dist/park-row-commit.d.ts +67 -0
  123. package/dist/park-row-commit.js +76 -0
  124. package/dist/parked-decide.d.ts +9 -7
  125. package/dist/parked-decide.js +25 -6
  126. package/dist/peer-directory.d.ts +1 -1
  127. package/dist/plugins/adoption-log-sql.d.ts +3 -3
  128. package/dist/plugins/adoption-log-sql.js +19 -19
  129. package/dist/plugins/approval-ask-store-sql.d.ts +1 -1
  130. package/dist/plugins/approval-ask-store-sql.js +3 -5
  131. package/dist/plugins/approval-exemption-skill-cutoff.d.ts +64 -0
  132. package/dist/plugins/approval-exemption-skill-cutoff.js +122 -0
  133. package/dist/plugins/approval-exemption-skill-m46.d.ts +0 -6
  134. package/dist/plugins/approval-exemption-skill-m46.js +6 -10
  135. package/dist/plugins/approval-exemption-store.d.ts +26 -1
  136. package/dist/plugins/approval-exemption-store.js +28 -19
  137. package/dist/plugins/ensure-schema-lock-policy.d.ts +36 -3
  138. package/dist/plugins/ensure-schema-lock-policy.js +75 -9
  139. package/dist/plugins/file-run-store.d.ts +22 -9
  140. package/dist/plugins/file-run-store.js +50 -22
  141. package/dist/plugins/local-checkpoint-store.d.ts +4 -0
  142. package/dist/plugins/local-checkpoint-store.js +2 -1
  143. package/dist/plugins/local-data-root-admission.d.ts +52 -0
  144. package/dist/plugins/local-data-root-admission.js +100 -0
  145. package/dist/plugins/local-engine-high-water.d.ts +28 -7
  146. package/dist/plugins/local-engine-high-water.js +27 -22
  147. package/dist/plugins/local-session-store.d.ts +134 -49
  148. package/dist/plugins/local-session-store.js +149 -108
  149. package/dist/plugins/memory-run-store.d.ts +14 -9
  150. package/dist/plugins/memory-run-store.js +47 -21
  151. package/dist/plugins/one-time-migration-marker.d.ts +19 -3
  152. package/dist/plugins/one-time-migration-marker.js +7 -1
  153. package/dist/plugins/one-time-migrations.d.ts +46 -20
  154. package/dist/plugins/one-time-migrations.js +102 -79
  155. package/dist/plugins/org-delivery-quota-store.d.ts +34 -11
  156. package/dist/plugins/org-delivery-quota-store.js +29 -14
  157. package/dist/plugins/permission-rule-store-sql.d.ts +1 -1
  158. package/dist/plugins/permission-rule-store-sql.js +5 -9
  159. package/dist/plugins/pg-pool.d.ts +1 -1
  160. package/dist/plugins/pg-pool.js +10 -12
  161. package/dist/plugins/remote-env-device.d.ts +3 -2
  162. package/dist/plugins/remote-env-e2b.d.ts +1 -7
  163. package/dist/plugins/remote-env-e2b.js +10 -7
  164. package/dist/plugins/remote-env-host.d.ts +50 -9
  165. package/dist/plugins/remote-env-host.js +77 -20
  166. package/dist/plugins/remote-env-k8s.js +4 -2
  167. package/dist/plugins/remote-env-local-docker.d.ts +6 -3
  168. package/dist/plugins/remote-env-local-docker.js +8 -23
  169. package/dist/plugins/run-store-sql.d.ts +26 -7
  170. package/dist/plugins/run-store-sql.js +44 -16
  171. package/dist/plugins/scenario-prefix-switch-m42.d.ts +3 -1
  172. package/dist/plugins/scenario-prefix-switch-m42.js +4 -3
  173. package/dist/plugins/schema-consistency.d.ts +89 -5
  174. package/dist/plugins/schema-consistency.js +176 -7
  175. package/dist/plugins/schema-drift-sentence.d.ts +6 -5
  176. package/dist/plugins/schema-drift-sentence.js +13 -5
  177. package/dist/plugins/session-placement.d.ts +5 -4
  178. package/dist/plugins/shell-sentinel-owner-m48.d.ts +22 -0
  179. package/dist/plugins/shell-sentinel-owner-m48.js +6 -0
  180. package/dist/plugins/stop-then-start-sentence.d.ts +16 -0
  181. package/dist/plugins/stop-then-start-sentence.js +7 -0
  182. package/dist/plugins/store-backend.d.ts +22 -8
  183. package/dist/plugins/store-backend.js +58 -24
  184. package/dist/plugins/store-contracts.d.ts +33 -3
  185. package/dist/plugins/store-contracts.js +16 -0
  186. package/dist/plugins/tidb-pool.d.ts +11 -6
  187. package/dist/plugins/tidb-pool.js +18 -12
  188. package/dist/plugins/workspace-custody.d.ts +44 -0
  189. package/dist/plugins/workspace-custody.js +47 -0
  190. package/dist/project-identity.d.ts +8 -7
  191. package/dist/project-identity.js +40 -17
  192. package/dist/project-layer-key.d.ts +13 -2
  193. package/dist/project-layer-key.js +9 -1
  194. package/dist/read-deny-floor-notice.d.ts +36 -0
  195. package/dist/read-deny-floor-notice.js +40 -0
  196. package/dist/{plain-string-record.d.ts → request-declaration-disposition.d.ts} +9 -23
  197. package/dist/request-declaration-disposition.js +39 -0
  198. package/dist/run-cancel-card.d.ts +28 -0
  199. package/dist/run-cancel-card.js +19 -0
  200. package/dist/run-cancel-context.d.ts +10 -0
  201. package/dist/run-cancel-context.js +1 -0
  202. package/dist/run-local.js +28 -13
  203. package/dist/runs.d.ts +31 -7
  204. package/dist/runs.js +34 -16
  205. package/dist/security.d.ts +2 -2
  206. package/dist/server-secret-env.d.ts +34 -20
  207. package/dist/server-secret-env.js +61 -18
  208. package/dist/session-agent.d.ts +3 -2
  209. package/dist/session-children-retire.d.ts +6 -3
  210. package/dist/session-children-retire.js +2 -5
  211. package/dist/session-workspace.d.ts +3 -3
  212. package/dist/store-admission.d.ts +33 -0
  213. package/dist/store-admission.js +49 -0
  214. package/dist/store-posture.d.ts +5 -0
  215. package/dist/store-posture.js +18 -1
  216. package/dist/stores-sql/checkpoint-store-sql.d.ts +1 -1
  217. package/dist/stores-sql/checkpoint-store-sql.js +3 -5
  218. package/dist/stores-sql/file-history-store-sql.d.ts +1 -1
  219. package/dist/stores-sql/file-history-store-sql.js +3 -5
  220. package/dist/stores-sql/tool-result-store-sql.d.ts +1 -1
  221. package/dist/stores-sql/tool-result-store-sql.js +4 -6
  222. package/dist/task-a2a.d.ts +3 -8
  223. package/dist/task-a2a.js +25 -27
  224. package/dist/task-cwd.d.ts +23 -7
  225. package/dist/task-cwd.js +3 -0
  226. package/dist/task-mcp.d.ts +3 -3
  227. package/dist/task-mcp.js +1 -1
  228. package/dist/task-settings.js +1 -0
  229. package/dist/terminal.d.ts +2 -0
  230. package/dist/terminal.js +21 -6
  231. package/dist/tool-approval.d.ts +44 -36
  232. package/dist/tool-approval.js +66 -47
  233. package/dist/trace/engine-notice-wire.d.ts +24 -21
  234. package/dist/trace/engine-notice-wire.js +7 -3
  235. package/dist/trace/ledger-sink.d.ts +3 -1
  236. package/dist/trace/project.d.ts +4 -2
  237. package/dist/trace/project.js +8 -7
  238. package/dist/trace/redact.d.ts +12 -0
  239. package/dist/trace/redact.js +5 -1
  240. package/dist/trace/self-minted-wire.d.ts +131 -52
  241. package/dist/trace/self-minted-wire.js +71 -39
  242. package/dist/web-admin-client/apply-effective.js +22 -9
  243. package/docs/error-text-lexicon.json +317 -0
  244. package/package.json +3 -1
  245. package/scripts/embed-minimal.mjs +183 -0
  246. package/wire-changes/server@7.149.0.json +372 -0
  247. package/dist/plain-string-record.js +0 -70
@@ -0,0 +1,317 @@
1
+ {
2
+ "description": [
3
+ "错误响应体 `{ error, errorCode, … }` 里 `error` 文案的用词约束。`error` 是给人读的一句话,`errorCode` 才是机器面(程序按码分支,不按文案);这份词表约束的是文案怎么写,不是协议。本服务自己的错误文案词域检查读的就是这一份文件,没有第二份。",
4
+ "射程:约束的是本服务自己写的那部分句子。句中插进来的值 —— 调用方送来的名字 / 路径 / id、上游或引擎的原话 —— 原样带出,不在这份词表的约束里;按词表判一句 `error` 时先把这些插入值剔掉(例:请求点名了一个叫 `council` 的模型而目录里没有,拒句里引着的这个名字不算命中)。",
5
+ "`words`:内部词闭集 —— 引擎 / 本服务内部机件的名字,判据是「调用方在 wire 上拿不到这个名字」。`error` 文案里不出现其中任何一个词:把 `words.match.pattern` 里的 `{word}` 换成词、按 `words.match.flags` 编译成正则来匹配。式子两头的 `\\b` 是承重的:wire 字段名的拼法(如 `checkpointToken`)不是整词,不命中;连字符是词边界(`workflow-agent` 里的 `workflow` 命中)。屈折形逐个列成成员,不做词干化(`park` 与 `parked` 是两件事)。",
6
+ "`idShapes`:内部编号形。`error` 文案里不出现任何一形:`shapes[].pattern` 按 `idShapes.flags` 编译成正则来匹配。",
7
+ "`pardons`:逐族放行 —— 唯一的例外来源。一条放行按族 `family` 生效(`<HTTP 状态码>:<errorCode>`);带 `where` 时只放行该族里含这个子串的那一句,不带时该族只有一句文案;`words` 是那一句上放行的词(都是 `words` 闭集的成员);`why` 说这个词在这一族上是调用方自己看得见、拿得到、写得出的哪一样东西(路径段 / wire 字段 / 错误码的拼写 / 旋钮名 / 状态词)。不在放行里的命中都不该出现在 `error` 文案里。"
8
+ ],
9
+ "words": {
10
+ "match": {
11
+ "pattern": "\\b{word}\\b",
12
+ "flags": "i"
13
+ },
14
+ "groups": [
15
+ {
16
+ "forms": [
17
+ "workflow",
18
+ "workflows"
19
+ ],
20
+ "why": "引擎内部的 workflow 执行通道;产品义(`/v1/workflows` 资源、`Workflow` 工具)按族放行,见 `pardons`。"
21
+ },
22
+ {
23
+ "forms": [
24
+ "child",
25
+ "children"
26
+ ],
27
+ "why": "引擎的父子代角色名;产品义(调用方自己在一条 run 下起的后台 agent)按族放行,见 `pardons`。"
28
+ },
29
+ {
30
+ "forms": [
31
+ "host",
32
+ "hosts"
33
+ ],
34
+ "why": "引擎的宿主会话角色(「宿主会话 / 宿主的下一跑」);产品义(worker 所在机器的文件系统路径)按族放行,见 `pardons`。"
35
+ },
36
+ {
37
+ "forms": [
38
+ "park",
39
+ "parks",
40
+ "parking"
41
+ ],
42
+ "why": "挂起对象的名词 / 动词形 —— wire 上只有形容词 `parked`,没有这三个形;错误码自己拼着它的族按族放行,见 `pardons`。"
43
+ },
44
+ {
45
+ "forms": [
46
+ "parked"
47
+ ],
48
+ "why": "wire 状态词(`GET /v1/agents/roster` 的 `?status=` 闭集成员);在待决 / decide 面上是产品词,但仍逐族放行、不整词豁免,见 `pardons`。"
49
+ },
50
+ {
51
+ "forms": [
52
+ "lane",
53
+ "lanes"
54
+ ],
55
+ "why": "本服务对「执行通道 / 部署形」的内部自称;错误码自己拼着它的族按族放行,见 `pardons`。"
56
+ },
57
+ {
58
+ "forms": [
59
+ "leader",
60
+ "leaders"
61
+ ],
62
+ "why": "编排席的内部名;产品义(`POST /v1/leader` 端点)按族放行,见 `pardons`。"
63
+ },
64
+ {
65
+ "forms": [
66
+ "subagent",
67
+ "subagents"
68
+ ],
69
+ "why": "引擎内部的角色名;产品义(`/v1/runs/:id/subagents` 路径段)按族放行,见 `pardons`。"
70
+ },
71
+ {
72
+ "forms": [
73
+ "council",
74
+ "councils"
75
+ ],
76
+ "why": "复审席的内部名 —— wire 上没有这个拼写。"
77
+ },
78
+ {
79
+ "forms": [
80
+ "checkpoint",
81
+ "checkpoints"
82
+ ],
83
+ "why": "挂起点对象的内部名;产品义(错误码目录里在册的部署件名)按族放行,见 `pardons`。"
84
+ },
85
+ {
86
+ "forms": [
87
+ "leg",
88
+ "legs"
89
+ ],
90
+ "why": "本服务对「一段执行」的内部自称 —— wire 上没有这个拼写。"
91
+ },
92
+ {
93
+ "forms": [
94
+ "seam",
95
+ "seams"
96
+ ],
97
+ "why": "本服务对「可替换接缝」的内部自称 —— wire 上没有这个拼写。"
98
+ },
99
+ {
100
+ "forms": [
101
+ "twin",
102
+ "twins"
103
+ ],
104
+ "why": "本服务对「另一后端的孪生实现」的内部自称 —— wire 上没有这个拼写。"
105
+ }
106
+ ]
107
+ },
108
+ "idShapes": {
109
+ "flags": "",
110
+ "shapes": [
111
+ {
112
+ "pattern": "\\bS-\\d+",
113
+ "label": "内部工单号(S-nnn)"
114
+ },
115
+ {
116
+ "pattern": "\\bA-\\d+(?:\\.\\d+)*",
117
+ "label": "内部审计号(A-nnn.n)"
118
+ },
119
+ {
120
+ "pattern": "\\bB-\\d+",
121
+ "label": "内部缺陷号(B-nnn)"
122
+ },
123
+ {
124
+ "pattern": "\\bC-R\\d+",
125
+ "label": "内部裁定号(C-Rnn)"
126
+ },
127
+ {
128
+ "pattern": "\\bdesign/\\d+",
129
+ "label": "内部设计稿号(design/nnn)"
130
+ },
131
+ {
132
+ "pattern": "\\[\\d{3,4}\\]",
133
+ "label": "内部讨论帖号([nnnn])"
134
+ },
135
+ {
136
+ "pattern": "车[A-Z]{1,2}\\b",
137
+ "label": "内部作业名(车XX)"
138
+ },
139
+ {
140
+ "pattern": "\\bwf_[0-9a-f]{6,}",
141
+ "label": "内部扫描号(wf_xxxxxxxx)"
142
+ }
143
+ ]
144
+ },
145
+ "pardons": [
146
+ {
147
+ "family": "400:request.field_invalid",
148
+ "where": "host path",
149
+ "words": [
150
+ "host"
151
+ ],
152
+ "why": "「absolute host path」限定的是调用方自己在 `cwd` / `additionalDirectories` / `additionalReadDirectories` 里送的那些路径 —— `host` 在这里是「worker 跑在哪台机器上」的产品义,不是引擎里的 HOST 会话角色。"
153
+ },
154
+ {
155
+ "family": "404:not_found.workflow",
156
+ "words": [
157
+ "workflow"
158
+ ],
159
+ "why": "`/v1/workflows/:id` 面自己的 404 —— 调用方 URL 里写的就是这个资源名,错误码 `not_found.workflow` 也逐字拼着它。"
160
+ },
161
+ {
162
+ "family": "400:request.path_malformed",
163
+ "where": "malformed workflow path",
164
+ "words": [
165
+ "workflow"
166
+ ],
167
+ "why": "路径段名(`/v1/workflows/…`),调用方自己写进 URL 的那一段。"
168
+ },
169
+ {
170
+ "family": "501:capability.workflow_store_required",
171
+ "where": "workflow",
172
+ "words": [
173
+ "workflow"
174
+ ],
175
+ "why": "两句都点名调用方够得着的东西:`GET /v1/workflows/:id/journal` 这张脸,以及部署旋钮 `WORKFLOW_RUN_STORE`(它自己的拼写里就有 WORKFLOW)。"
176
+ },
177
+ {
178
+ "family": "501:capability.self_orchestration_required",
179
+ "where": "workflow",
180
+ "words": [
181
+ "workflow",
182
+ "workflows"
183
+ ],
184
+ "why": "`/v1/workflows` 提交面与 `GET /v1/capabilities` 的 `workflows` 能力位 —— 长的那句自己就把那个 JSON 键(`workflows:false`)拼了出来。"
185
+ },
186
+ {
187
+ "family": "404:not_found.task_handle",
188
+ "words": [
189
+ "workflow",
190
+ "workflows"
191
+ ],
192
+ "why": "这句自己点名 `GET /v1/workflows/:id/journal` —— 指的是调用方接下来该去读的那张脸,不是引擎车道。"
193
+ },
194
+ {
195
+ "family": "404:not_found.subagent",
196
+ "words": [
197
+ "workflow",
198
+ "child",
199
+ "children"
200
+ ],
201
+ "why": "`workflow` = 同上那张 journal 读面;`child`/`children` = 调用方自己在这条 run 下起的后台 agent —— 它们在 `/v1/runs/:id/subagents` 与 `GET /v1/agents/roster` 上都有行,亲缘关系是调用方自己造的。"
202
+ },
203
+ {
204
+ "family": "400:request.path_malformed",
205
+ "where": "malformed subagent path",
206
+ "words": [
207
+ "subagent"
208
+ ],
209
+ "why": "路径段名(`/v1/runs/:id/subagents/…`),调用方自己写进 URL 的那一段。"
210
+ },
211
+ {
212
+ "family": "501:capability.run_store_required",
213
+ "where": "subagent",
214
+ "words": [
215
+ "subagent"
216
+ ],
217
+ "why": "同一段路径名的两条能力拒(`/v1/runs/:id/subagents/…` 的读面与流面)—— 主语就是调用方刚才请求的那条路径。"
218
+ },
219
+ {
220
+ "family": "404:not_found.checkpoint",
221
+ "words": [
222
+ "checkpoint"
223
+ ],
224
+ "why": "错误码自身即 `not_found.checkpoint` —— 码与文案同词,调用方读码、读文案得到同一件事;不依赖任何它发不出去的字段。"
225
+ },
226
+ {
227
+ "family": "404:not_found.parked_checkpoint",
228
+ "words": [
229
+ "parked",
230
+ "checkpoint"
231
+ ],
232
+ "why": "两个词都在错误码自己的拼写里(`not_found.parked_checkpoint`);`parked` 另是 `GET /v1/agents/roster` 的 `?status=` 闭集成员。"
233
+ },
234
+ {
235
+ "family": "501:capability.checkpoint_store_required",
236
+ "where": "checkpoint store",
237
+ "words": [
238
+ "checkpoint"
239
+ ],
240
+ "why": "运维面 501,码自身就是 `capability.checkpoint_store_required` —— `checkpoint store` 是错误码目录里在册的那只部署件的名字。"
241
+ },
242
+ {
243
+ "family": "501:feature.preemption_disabled",
244
+ "where": "checkpoint store",
245
+ "words": [
246
+ "checkpoint"
247
+ ],
248
+ "why": "同一只部署件,名字来自同一份错误码目录(`capability.checkpoint_store_required`)—— 运维读这句时要装的就是目录里那一件;与同句的 `RESOURCE_SUSPEND` 是两样东西,理由不靠那个旋钮。"
249
+ },
250
+ {
251
+ "family": "400:decide.parked_remember_unsupported",
252
+ "words": [
253
+ "parked"
254
+ ],
255
+ "why": "错误码自身即 `decide.parked_remember_unsupported`;主语是调用方在 `GET /v1/agents/roster` 上看得到的那一行,`parked` 是那张脸 `?status=` 闭集里的词。"
256
+ },
257
+ {
258
+ "family": "409:decide.claim_lost",
259
+ "where": "parked agent is already claimed",
260
+ "words": [
261
+ "parked"
262
+ ],
263
+ "why": "同 decide 族:主语是 `GET /v1/agents/roster` 上状态值逐字为 `parked` 的那一行 —— 这句说的是「你挑的那一行被别人先认领了」。"
264
+ },
265
+ {
266
+ "family": "409:decide.gate_moved",
267
+ "words": [
268
+ "parked"
269
+ ],
270
+ "why": "同 decide 族:`re-parked` 说的是那一行又回到了 roster `?status=` 闭集里的同一个值 —— 调用方的动作(重读待决列表)正是由这个词决定的。"
271
+ },
272
+ {
273
+ "family": "409:decide.not_parked",
274
+ "where": "moved under this decide",
275
+ "words": [
276
+ "parked"
277
+ ],
278
+ "why": "错误码自身即 `decide.not_parked` —— 码与文案说的是同一个 roster 状态值离开了,两边同词。"
279
+ },
280
+ {
281
+ "family": "410:gone.ask_parked",
282
+ "words": [
283
+ "parked"
284
+ ],
285
+ "why": "错误码自身即 `gone.ask_parked`,且 `tool_approval` 帧上有一个同名 additive 键 `parked`(契约 §7b)—— 这个词调用方在两处都见得到。"
286
+ },
287
+ {
288
+ "family": "425:parking.ask_retry",
289
+ "words": [
290
+ "park"
291
+ ],
292
+ "why": "错误码自身即 `parking.ask_retry` —— 「mid-park」是这个码的自然语言拼法,重试就会告诉调用方它最终落在哪。"
293
+ },
294
+ {
295
+ "family": "500:internal.error",
296
+ "where": "the parked approval",
297
+ "words": [
298
+ "parked"
299
+ ],
300
+ "why": "这句说的是赎回一张后台审批卡失败:主语是那张卡,`parked` 是 `GET /v1/agents/roster` 的 `?status=` 闭集与 `tool_approval` 帧同名键上的同一个词。"
301
+ },
302
+ {
303
+ "family": "501:capability.device_lane_required",
304
+ "words": [
305
+ "lane"
306
+ ],
307
+ "why": "错误码自身即 `capability.device_lane_required` —— `device execution lane` 是这个码在错误码目录里的全称,旋钮 `REMOTE_EXEC=device` 在同句里给出兑现路径。"
308
+ },
309
+ {
310
+ "family": "404:not_found.leader_run",
311
+ "words": [
312
+ "leader"
313
+ ],
314
+ "why": "`POST /v1/leader` / `GET /v1/leader/:id` 端点名,也是错误码自身的拼写(`not_found.leader_run`)、能力位名(`capabilities.leader`)与旋钮名(`LEADER_ENABLED`)。"
315
+ }
316
+ ]
317
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.148.0",
3
+ "version": "7.149.0",
4
4
  "description": "Sema Server — the server/API implementation layer for Sema, wiring core, registry, model providers, and cloud agent execution. Built on @sema-agent/core.",
5
5
  "type": "module",
6
6
  "license": "BUSL-1.1",
@@ -45,9 +45,11 @@
45
45
  "scripts/drain-check-local.mjs",
46
46
  "scripts/drain-check.mysql.sql",
47
47
  "scripts/drain-check.pg.sql",
48
+ "scripts/embed-minimal.mjs",
48
49
  "deploy/sema-up",
49
50
  "deploy/facts",
50
51
  "docs/DEVICE-EXECUTOR-PROTOCOL.md",
52
+ "docs/error-text-lexicon.json",
51
53
  "wire-changes/",
52
54
  "USAGE.md",
53
55
  "MIGRATION.md"
@@ -0,0 +1,183 @@
1
+ #!/usr/bin/env node
2
+ // embed-minimal.mjs — the smallest HTTP service assembled the way a library embedder assembles it.
3
+ //
4
+ // node scripts/embed-minimal.mjs build every seat, listen on 127.0.0.1:0, print `EMBED-MINIMAL ok port=<n>`, exit 0
5
+ // node scripts/embed-minimal.mjs --omit <seat> build every seat but <seat>, then call `createHttpServer`:
6
+ // refused at construction → `EMBED-MINIMAL refused seat=<seat> message=<first line>`, exit 2
7
+ // accepted at construction → `EMBED-MINIMAL accepted seat=<seat>`, exit 3 (the seat is not judged at construction)
8
+ // any other failure `EMBED-MINIMAL failed step=<step> message=<first line>`, exit 1; a bad command line exits 64.
9
+ // `--omit` reads the omission against the complete assembly: when that does not construct either, the line is `failed step=baseline`,
10
+ // and a clean-up that did not happen is `failed step=cleanup` — neither is ever reported as a refusal of the omitted seat.
11
+ //
12
+ // The assembly order is the README "Library embedding" chain: `declareServerWithheldEnv()` → `loadConfig()` → `composeExecutionLane(config, ctx)` →
13
+ // `judgeServedModelRoute(config, { envTableIsPlaceholder })` (the route judge, once after the config-source apply; `loadConfig()` does not judge routes) →
14
+ // the nine required `createHttpServer` seats (the type `ServiceCoreDeps`) → `createHttpServer(deps)`. It imports the package root `@sema-agent/server` and the
15
+ // engine package `@sema-agent/core` (the server's pinned dependency, owner of the `Runner` class), never a path inside `dist/`.
16
+ // The service it assembles runs on the host lane against a throwaway local data root and listens on a kernel-assigned loopback port; it takes no task,
17
+ // calls no model and leaves nothing behind (the data root is removed on the way out). It sets the ten environment variables in the `env` block below
18
+ // itself; every other service knob is read from the caller's environment as usual, so run it from a shell that does not carry a production deployment's variables.
19
+
20
+ import { mkdtemp, rm } from "node:fs/promises";
21
+ import { tmpdir } from "node:os";
22
+ import { join } from "node:path";
23
+ import { Runner } from "@sema-agent/core";
24
+ import {
25
+ HTTP_SERVICE_LANE_ENTRY,
26
+ buildScenarios,
27
+ composeExecutionLane,
28
+ createAuthorizer,
29
+ createBrain,
30
+ createHttpServer,
31
+ createKeyResolver,
32
+ createLogger,
33
+ createPeerDesk,
34
+ createScenarioGate,
35
+ createSideQueryLane,
36
+ declareServerWithheldEnv,
37
+ judgeServedModelRoute,
38
+ loadConfig,
39
+ } from "@sema-agent/server";
40
+
41
+ /** The nine seats `createHttpServer` requires (the type `ServiceCoreDeps`); `--omit` takes exactly these names. */
42
+ const SEATS = ["runner", "runnerFor", "sideQuery", "scenarioGate", "peerDesk", "deploymentMods", "config", "authorize", "resolveSpec"];
43
+
44
+ const TAG = "EMBED-MINIMAL";
45
+ const oneLine = (e) => String(e instanceof Error ? e.message : e).split("\n")[0].replace(/\s+/g, " ").slice(0, 400);
46
+
47
+ // ── command line ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
48
+ const args = process.argv.slice(2);
49
+ let omit;
50
+ if (args.length === 0) {
51
+ omit = undefined;
52
+ } else if (args.length === 2 && args[0] === "--omit" && SEATS.includes(args[1])) {
53
+ omit = args[1];
54
+ } else {
55
+ console.error(`usage: embed-minimal.mjs [--omit <${SEATS.join("|")}>]`);
56
+ process.exit(64);
57
+ }
58
+
59
+ let step = "env";
60
+ let dataRoot;
61
+ let runner;
62
+ let server;
63
+ let line;
64
+ let code = 1;
65
+ try {
66
+ // ── the deployment's own env: what a deployer would put in the service's environment ─────────────────────────────────────────────────────────
67
+ dataRoot = await mkdtemp(join(tmpdir(), "embed-minimal-"));
68
+ Object.assign(process.env, {
69
+ DB_BACKEND: "local", // file-backed local mode: no database
70
+ LOCAL_DATA_ROOT: dataRoot, // the store root (highest-priority data-root knob)
71
+ AGENT_DATA_DIR: dataRoot, // the engine's own default root follows the same directory
72
+ REMOTE_EXEC: "host", // every deployment names its execution lane; `host` = tools run on this machine
73
+ BIND_HOST: "127.0.0.1",
74
+ PORT: "0", // the kernel assigns the port; the bound one is read back from the server
75
+ OPERATOR_SINGLE_USER: "true", // a single-user process says who the operator is
76
+ ALLOW_UNAUTHED_WRITES: "true", // no service token: loopback only
77
+ MODEL_ID: "embed-minimal-model", // the model table needs one entry; nothing here calls it
78
+ MODEL_GATEWAY_BASEURL: "http://127.0.0.1:9/v1",
79
+ });
80
+
81
+ // ── seat: config (package root: declareServerWithheldEnv → loadConfig → composeExecutionLane) ─────────────────────────────────────────────
82
+ step = "config";
83
+ declareServerWithheldEnv(); // first, before `loadConfig()` and before any execution environment or child process
84
+ const logger = createLogger("error");
85
+ const config = await composeExecutionLane(loadConfig(), { configSource: undefined, localRoot: dataRoot, logger, entry: HTTP_SERVICE_LANE_ENTRY });
86
+ // The route judge runs after the config-source apply, never inside `loadConfig()`: a model row with no endpoint would otherwise travel to the first model call.
87
+ // No center here ⇒ the env table is the served table, not a placeholder awaiting a catalog.
88
+ const routeGap = judgeServedModelRoute(config, { envTableIsPlaceholder: false });
89
+ if (routeGap !== undefined) throw new Error(routeGap.reason);
90
+
91
+ // ── seats: peerDesk, deploymentMods (package root: createPeerDesk; `[]` = no mods) ────────────────────────────────────────────────────────
92
+ step = "seats";
93
+ const peerDesk = createPeerDesk(); // zero IO; the same desk goes to the server and, as `peerSeat`, to every Runner
94
+ const deploymentMods = []; // the very array the Runners carry as `mods`
95
+
96
+ // ── seat: runner (engine package: `Runner`; the brain comes from the package root's createBrain) ───────────────────────────────────────────
97
+ const brain = createBrain(config);
98
+ runner = new Runner({ brain, models: config.models, roles: config.roles, mods: deploymentMods, peerSeat: peerDesk.seat });
99
+
100
+ // ── seat: sideQuery (package root: createSideQueryLane + createKeyResolver, the same brain as the Runner's) ────────────────────────────────
101
+ const keyResolver = createKeyResolver(config.modelApiKeyEnv, process.env, config.modelApiKeys);
102
+ const sideQuery = createSideQueryLane({ brain, config, getKeyResolver: () => keyResolver });
103
+
104
+ // ── seat: scenarioGate (package root: buildScenarios → createScenarioGate, the read-face leg `peek`) ───────────────────────────────────────
105
+ const scenarios = buildScenarios({ runner, subRunner: runner, model: Object.keys(config.models)[0], skills: [], logger });
106
+ const scenarioGate = createScenarioGate({ config, scenarios, principalCaps: undefined, logger }, "peek");
107
+
108
+ // ── seats: authorize, runnerFor (package root: createAuthorizer; a single-Runner embedding says so with `() => runner`) ─────────────────────
109
+ const authorize = createAuthorizer(config, runner.sessions);
110
+ const runnerFor = () => runner;
111
+
112
+ // ── seat: resolveSpec (the embedder's own: request body + identity → the task spec; it returns no `sessionId`, the server stamps the root) ──
113
+ const resolveSpec = (body) => ({ objective: String(body?.objective ?? "") });
114
+
115
+ const deps = { runner, runnerFor, sideQuery, scenarioGate, peerDesk, deploymentMods, config, authorize, resolveSpec };
116
+
117
+ if (omit !== undefined) {
118
+ // An omission can only be read against a complete assembly that constructs: build that first, so a refusal that has nothing to do with the omitted seat
119
+ // (any other construction-time check of the deployment's configuration) is reported as `failed step=baseline`, never as `refused seat=…`.
120
+ step = "baseline";
121
+ createHttpServer(deps).close();
122
+ const partial = { ...deps };
123
+ delete partial[omit];
124
+ step = "createHttpServer";
125
+ createHttpServer(partial).close();
126
+ line = `${TAG} accepted seat=${omit}`;
127
+ code = 3;
128
+ } else {
129
+ step = "createHttpServer";
130
+ server = createHttpServer(deps);
131
+ step = "listen";
132
+ await new Promise((resolve, reject) => {
133
+ server.once("error", reject);
134
+ server.listen(0, "127.0.0.1", () => resolve());
135
+ });
136
+ const port = server.address().port;
137
+ step = "health";
138
+ const res = await fetch(`http://127.0.0.1:${port}/health`);
139
+ if (res.status !== 200) throw new Error(`GET /health answered ${res.status}`);
140
+ line = `${TAG} ok port=${port}`;
141
+ code = 0;
142
+ }
143
+ } catch (e) {
144
+ if (omit !== undefined && step === "createHttpServer") {
145
+ line = `${TAG} refused seat=${omit} message=${oneLine(e)}`;
146
+ code = 2;
147
+ } else {
148
+ line = `${TAG} failed step=${step} message=${oneLine(e)}`;
149
+ code = 1;
150
+ }
151
+ }
152
+
153
+ // ── leave nothing behind, and say so before the result is printed: a clean-up that did not happen is a failure, not a footnote ───────────────────
154
+ const leftovers = [];
155
+ if (server?.listening) {
156
+ try {
157
+ await new Promise((resolve) => (server.closeAllConnections?.(), server.close(() => resolve())));
158
+ } catch (e) {
159
+ leftovers.push(e);
160
+ }
161
+ }
162
+ try {
163
+ runner?.sessions.dispose();
164
+ } catch (e) {
165
+ leftovers.push(e);
166
+ }
167
+ if (dataRoot !== undefined) {
168
+ try {
169
+ await rm(dataRoot, { recursive: true, force: true });
170
+ } catch (e) {
171
+ leftovers.push(e);
172
+ }
173
+ }
174
+ if (leftovers.length > 0) {
175
+ if (code === 1) {
176
+ console.error(`${TAG} clean-up also failed: ${oneLine(leftovers[0])}`); // the run had already failed; its own line stays the result
177
+ } else {
178
+ line = `${TAG} failed step=cleanup message=${oneLine(leftovers[0])}`;
179
+ code = 1;
180
+ }
181
+ }
182
+ console.log(line);
183
+ process.exit(code);