@sema-agent/server 7.136.0 → 7.137.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 (214) hide show
  1. package/MIGRATION.md +173 -0
  2. package/USAGE.md +84 -16
  3. package/deploy/sema-up/README.md +14 -0
  4. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
  5. package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
  6. package/dist/approval-content-kind.d.ts +6 -0
  7. package/dist/approval-content-kind.js +7 -0
  8. package/dist/approval-gate-currency.d.ts +48 -6
  9. package/dist/approval-gate-currency.js +16 -9
  10. package/dist/approval-hmac.d.ts +13 -1
  11. package/dist/approval-hmac.js +1 -1
  12. package/dist/approval.js +3 -3
  13. package/dist/auth-bridge.js +2 -2
  14. package/dist/boot/execution-env.d.ts +24 -1
  15. package/dist/boot/execution-env.js +69 -6
  16. package/dist/boot/reapers.d.ts +3 -0
  17. package/dist/boot/reapers.js +15 -1
  18. package/dist/boot/resolve-spec.d.ts +4 -0
  19. package/dist/boot/resolve-spec.js +16 -17
  20. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  21. package/dist/boot/stage-04-stores.d.ts +1 -1
  22. package/dist/boot/stage-05-execution-env.d.ts +3 -1
  23. package/dist/boot/stage-05-execution-env.js +11 -2
  24. package/dist/boot/stage-06-runners.d.ts +3 -1
  25. package/dist/boot/stage-06-runners.js +5 -1
  26. package/dist/boot/stage-07-capability-layer.d.ts +4 -1
  27. package/dist/boot/stage-07-capability-layer.js +1 -1
  28. package/dist/boot/stage-08-reapers.d.ts +4 -1
  29. package/dist/boot/stage-08-reapers.js +2 -1
  30. package/dist/boot/stage-09-leader.d.ts +4 -1
  31. package/dist/boot/stage-10-http-server.d.ts +4 -1
  32. package/dist/boot/stage-10-http-server.js +3 -2
  33. package/dist/boot/stores.d.ts +1 -1
  34. package/dist/broker/broker.d.ts +89 -0
  35. package/dist/broker/broker.js +287 -0
  36. package/dist/broker/constants.d.ts +39 -0
  37. package/dist/broker/constants.js +15 -0
  38. package/dist/broker/http1.d.ts +111 -0
  39. package/dist/broker/http1.js +256 -0
  40. package/dist/broker/lease-book.d.ts +87 -0
  41. package/dist/broker/lease-book.js +142 -0
  42. package/dist/broker/lease-file.d.ts +60 -0
  43. package/dist/broker/lease-file.js +127 -0
  44. package/dist/broker/main.d.ts +2 -0
  45. package/dist/broker/main.js +20 -0
  46. package/dist/capabilities/composite-members.d.ts +2 -1
  47. package/dist/capabilities/composite-members.js +2 -1
  48. package/dist/capabilities/engine-capabilities.js +1 -0
  49. package/dist/capabilities/scenarios.d.ts +23 -8
  50. package/dist/capabilities/scenarios.js +13 -8
  51. package/dist/capabilities/skills.d.ts +28 -5
  52. package/dist/capabilities/skills.js +8 -0
  53. package/dist/center-credential-renewer.js +5 -1
  54. package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
  55. package/dist/checkpoint-ctx-seal-m28.js +1 -1
  56. package/dist/checkpoint-identity.d.ts +3 -3
  57. package/dist/config-catalog.js +9 -6
  58. package/dist/config-types.d.ts +9 -0
  59. package/dist/config.d.ts +1 -1
  60. package/dist/config.js +34 -8
  61. package/dist/deployment-governance.d.ts +2 -2
  62. package/dist/deployment-governance.js +7 -9
  63. package/dist/device-ws-protocol.d.ts +1 -0
  64. package/dist/device-ws-protocol.js +2 -1
  65. package/dist/file-history-disclosure.d.ts +4 -2
  66. package/dist/file-history-disclosure.js +2 -0
  67. package/dist/hooks/classic-stations.d.ts +11 -54
  68. package/dist/http/admission.js +10 -7
  69. package/dist/http/approval-sweeps.js +4 -3
  70. package/dist/http/caller-trust.d.ts +2 -1
  71. package/dist/http/caller-trust.js +1 -3
  72. package/dist/http/checkpoint-ctx.d.ts +48 -7
  73. package/dist/http/checkpoint-ctx.js +40 -0
  74. package/dist/http/dispatch.js +15 -10
  75. package/dist/http/durable-run-leg.d.ts +5 -1
  76. package/dist/http/durable-run-leg.js +1 -1
  77. package/dist/http/health-self-report.d.ts +2 -2
  78. package/dist/http/mcp-remote-text.d.ts +5 -0
  79. package/dist/http/mcp-remote-text.js +7 -0
  80. package/dist/http/principal-gate.d.ts +15 -10
  81. package/dist/http/principal-gate.js +48 -9
  82. package/dist/http/resume-legs.d.ts +2 -20
  83. package/dist/http/resume-legs.js +52 -38
  84. package/dist/http/route-ctx.d.ts +8 -2
  85. package/dist/http/routes/approvals-assistant.js +18 -4
  86. package/dist/http/routes/capabilities.js +11 -1
  87. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  88. package/dist/http/routes/mcp-reconnect.js +5 -7
  89. package/dist/http/routes/runs.js +2 -1
  90. package/dist/http/routes/session-sync.js +42 -6
  91. package/dist/http/routes/sessions.js +2 -1
  92. package/dist/http/routes/tasks.js +8 -6
  93. package/dist/http/server.d.ts +4 -0
  94. package/dist/http/stored-body-replay.d.ts +3 -3
  95. package/dist/http/stored-body-replay.js +6 -1
  96. package/dist/http/wire-types.d.ts +52 -27
  97. package/dist/identity-source.d.ts +65 -0
  98. package/dist/identity-source.js +45 -0
  99. package/dist/memory-store-refusal.d.ts +3 -3
  100. package/dist/model-entry-refusal.d.ts +2 -0
  101. package/dist/model-entry-refusal.js +11 -0
  102. package/dist/model-select.d.ts +6 -17
  103. package/dist/model-select.js +0 -3
  104. package/dist/namespaced-rule-name.d.ts +1 -1
  105. package/dist/observability/fail-open.d.ts +13 -1
  106. package/dist/observability/fail-open.js +13 -1
  107. package/dist/observability/metrics.js +1 -1
  108. package/dist/observability/run-terminal.js +1 -0
  109. package/dist/operator-ask.d.ts +2 -2
  110. package/dist/org-delivery-gate.js +1 -1
  111. package/dist/org-memory-admission.d.ts +2 -2
  112. package/dist/org-memory-admission.js +39 -2
  113. package/dist/parked-decide.js +3 -2
  114. package/dist/peer-directory.js +2 -0
  115. package/dist/permission-rule-list.d.ts +2 -2
  116. package/dist/plugins/checkpoint-store-sql.d.ts +19 -9
  117. package/dist/plugins/checkpoint-store-sql.js +6 -6
  118. package/dist/plugins/file-history-store-sql.js +7 -14
  119. package/dist/plugins/file-run-store.js +8 -2
  120. package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
  121. package/dist/plugins/k8s-exec-protocol.js +116 -28
  122. package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
  123. package/dist/plugins/k8s-pod-delete-failure.js +17 -0
  124. package/dist/plugins/k8s-pod-reaper.d.ts +112 -0
  125. package/dist/plugins/k8s-pod-reaper.js +122 -0
  126. package/dist/plugins/local-checkpoint-store.d.ts +3 -6
  127. package/dist/plugins/local-checkpoint-store.js +3 -3
  128. package/dist/plugins/memory-run-store.js +2 -0
  129. package/dist/plugins/one-time-migrations.d.ts +28 -9
  130. package/dist/plugins/one-time-migrations.js +48 -5
  131. package/dist/plugins/permission-rule-store-file.js +2 -2
  132. package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
  133. package/dist/plugins/permission-rule-store-sql.js +16 -17
  134. package/dist/plugins/pg-pool.js +4 -0
  135. package/dist/plugins/pg-session-storage.js +2 -2
  136. package/dist/plugins/remote-env-adb.d.ts +3 -0
  137. package/dist/plugins/remote-env-adb.js +1 -0
  138. package/dist/plugins/remote-env-device.d.ts +3 -0
  139. package/dist/plugins/remote-env-device.js +4 -0
  140. package/dist/plugins/remote-env-e2b.d.ts +3 -0
  141. package/dist/plugins/remote-env-e2b.js +1 -0
  142. package/dist/plugins/remote-env-file-error.d.ts +8 -1
  143. package/dist/plugins/remote-env-file-error.js +7 -1
  144. package/dist/plugins/remote-env-host.d.ts +7 -1
  145. package/dist/plugins/remote-env-host.js +7 -1
  146. package/dist/plugins/remote-env-k8s.d.ts +137 -10
  147. package/dist/plugins/remote-env-k8s.js +276 -14
  148. package/dist/plugins/remote-env-local-docker.d.ts +3 -0
  149. package/dist/plugins/remote-env-local-docker.js +1 -0
  150. package/dist/plugins/remote-env-ssh.d.ts +3 -0
  151. package/dist/plugins/remote-env-ssh.js +1 -0
  152. package/dist/plugins/run-store-sql.js +10 -4
  153. package/dist/plugins/session-ownership.d.ts +17 -3
  154. package/dist/plugins/session-ownership.js +19 -5
  155. package/dist/plugins/sql-errors.d.ts +23 -2
  156. package/dist/plugins/sql-errors.js +15 -0
  157. package/dist/plugins/store-contracts.d.ts +10 -1
  158. package/dist/plugins/store-fault.d.ts +2 -2
  159. package/dist/plugins/store-fault.js +4 -2
  160. package/dist/plugins/tidb-pool.js +7 -0
  161. package/dist/plugins/tidb-session-store.js +2 -2
  162. package/dist/request-key-closure.js +1 -1
  163. package/dist/request-value-closure.d.ts +31 -2
  164. package/dist/request-value-closure.js +7 -1
  165. package/dist/rule-entry-list.d.ts +3 -2
  166. package/dist/rule-entry-list.js +2 -2
  167. package/dist/rules-consent.js +7 -4
  168. package/dist/run-local.d.ts +2 -2
  169. package/dist/runs.js +2 -1
  170. package/dist/runtime-governance.d.ts +5 -5
  171. package/dist/sandbox-git-lease.d.ts +49 -0
  172. package/dist/sandbox-git-lease.js +60 -0
  173. package/dist/sandbox-git-plane.d.ts +84 -0
  174. package/dist/sandbox-git-plane.js +105 -0
  175. package/dist/security.d.ts +16 -4
  176. package/dist/security.js +8 -3
  177. package/dist/server-secret-env.d.ts +6 -0
  178. package/dist/server-secret-env.js +14 -0
  179. package/dist/session-error-wire.d.ts +14 -6
  180. package/dist/session-error-wire.js +2 -1
  181. package/dist/session-policy-wire.d.ts +1 -1
  182. package/dist/session-policy-wire.js +2 -2
  183. package/dist/session-sync.d.ts +1 -1
  184. package/dist/spec-fields.d.ts +43 -13
  185. package/dist/spec-fields.js +33 -12
  186. package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
  187. package/dist/stored-request-prompt-profile-m30.js +25 -0
  188. package/dist/task-mcp.d.ts +1 -1
  189. package/dist/task-settings.d.ts +2 -2
  190. package/dist/tool-approval.d.ts +12 -2
  191. package/dist/tool-approval.js +8 -3
  192. package/dist/tool-rule-names.d.ts +5 -0
  193. package/dist/trace/core-keyset-guard.d.ts +4 -4
  194. package/dist/trace/engine-notice-wire.d.ts +1 -1
  195. package/dist/trace/engine-notice-wire.js +2 -0
  196. package/dist/trace/exit-seat.js +2 -2
  197. package/dist/trace/ledger-sink.d.ts +4 -5
  198. package/dist/trace/ledger-sink.js +3 -7
  199. package/dist/trace/project.d.ts +37 -3
  200. package/dist/trace/project.js +20 -6
  201. package/dist/trace/redact.d.ts +18 -6
  202. package/dist/trace/redact.js +118 -53
  203. package/dist/trace/self-minted-wire.d.ts +377 -3
  204. package/dist/trace/self-minted-wire.js +122 -0
  205. package/dist/trace/wire-projection-faces.d.ts +5 -3
  206. package/dist/trace/wire-projection-faces.js +7 -3
  207. package/dist/web-admin-client/apply-effective.js +0 -1
  208. package/dist/web-admin-client/center-request.d.ts +20 -2
  209. package/dist/web-admin-client/center-request.js +40 -5
  210. package/dist/web-admin-client/http-client.js +6 -6
  211. package/dist/web-admin-client/types.d.ts +5 -5
  212. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
  213. package/package.json +2 -2
  214. package/wire-changes/server@7.137.0.json +825 -0
@@ -148,6 +148,33 @@ export const SELF_MINTED_WIRE = {
148
148
  title: { attr: "-", since: "7.133.0" },
149
149
  },
150
150
  },
151
+ credentialPlaneSandboxGitState: {
152
+ at: "GET /v1/capabilities credentialPlane.sandboxGit.state",
153
+ members: {
154
+ on: { attr: "-", since: "7.137.0" },
155
+ off: { attr: "-", since: "7.137.0" },
156
+ },
157
+ },
158
+ credentialPlaneSandboxGitOffReason: {
159
+ at: "GET /v1/capabilities credentialPlane.sandboxGit.reason",
160
+ members: {
161
+ single_user: { attr: "-", since: "7.137.0" },
162
+ lane_without_boundary: { attr: "-", since: "7.137.0" },
163
+ no_caller_credential: { attr: "-", since: "7.137.0" },
164
+ center_not_https: { attr: "-", since: "7.137.0" },
165
+ secret_seat_unverified: { attr: "-", since: "7.137.0" },
166
+ secret_seat_denied: { attr: "-", since: "7.137.0" },
167
+ pod_patch_reaches_broker: { attr: "-", since: "7.137.0" },
168
+ broker_image_unset: { attr: "-", since: "7.137.0" },
169
+ no_origins: { attr: "-", since: "7.137.0" },
170
+ },
171
+ },
172
+ credentialPlaneSandboxGitOriginReason: {
173
+ at: "GET /v1/capabilities credentialPlane.sandboxGit.origins[].reason",
174
+ members: {
175
+ insecure_transport: { attr: "-", since: "7.137.0" },
176
+ },
177
+ },
151
178
  healthAuthKind: {
152
179
  at: "GET /health auth.kinds[]",
153
180
  members: {
@@ -235,6 +262,15 @@ export const SELF_MINTED_WIRE = {
235
262
  not_object: { attr: "-", since: "7.133.0" },
236
263
  },
237
264
  },
265
+ inheritEnvRefusalReason: {
266
+ at: "400 request.field_invalid reason(inheritEnv 的值形 / 车道 / 无会话三只拒;另带 field: \"inheritEnv\")",
267
+ members: {
268
+ unknown_word: { attr: "-", since: "7.137.0" },
269
+ not_a_string: { attr: "-", since: "7.137.0" },
270
+ lane_not_host: { attr: "-", since: "7.137.0" },
271
+ no_authorizer_session: { attr: "-", since: "7.137.0" },
272
+ },
273
+ },
238
274
  submitIdempotency: {
239
275
  at: "提交幂等(<端点>#<面> → 应答状态)",
240
276
  members: {
@@ -268,6 +304,14 @@ export const SELF_MINTED_WIRE = {
268
304
  center: { attr: "-", since: "7.135.0" },
269
305
  },
270
306
  },
307
+ wiringSkillSource: {
308
+ at: "wiring_manifest skills[].source(run 级技能名册的来处;段只投根腿 / 续跑腿帧,零技能 = [])",
309
+ members: {
310
+ factory: { attr: "-", since: "7.137.0" },
311
+ center: { attr: "-", since: "7.137.0" },
312
+ request: { attr: "-", since: "7.137.0" },
313
+ },
314
+ },
271
315
  configCatalogValueVerdict: {
272
316
  at: "GET /v1/config/catalog rows[] 的判词位(<键> → 在场律)",
273
317
  members: {
@@ -301,6 +345,12 @@ export const SELF_MINTED_WIRE = {
301
345
  classifierNoRuling: { attr: "present-iff", since: "7.136.0" },
302
346
  },
303
347
  },
348
+ constraintRejectedBodyKey: {
349
+ at: "409 resume.constraint_rejected 拒体(<键> → 在场律)",
350
+ members: {
351
+ acceptableForm: { attr: "present-iff", since: "7.137.0" },
352
+ },
353
+ },
304
354
  endpointFaceStatus: {
305
355
  at: "逐端点应答面 → 状态(<端点>#<面> → 状态;只登记本版改了状态的面)",
306
356
  members: {
@@ -308,8 +358,15 @@ export const SELF_MINTED_WIRE = {
308
358
  "GET /v1/sessions/:id/sync/manifest#store_connection_fault(体 state.file_history_unreadable + permanence: transient)": { attr: 503, since: "7.136.0" },
309
359
  "GET /v1/sessions/:id/sync/entries#store_connection_fault(应答头发出之前;体同上)": { attr: 503, since: "7.136.0" },
310
360
  "GET /v1/sessions/:id/sync/history/blobs/:hash#store_connection_fault(体同上)": { attr: 503, since: "7.136.0" },
361
+ "GET /v1/sessions/:id/sync/manifest#store_connection_fault_session_gate(会话门那一读;体同上)": { attr: 503, since: "7.137.0" },
362
+ "GET /v1/sessions/:id/sync/entries#store_connection_fault_session_gate(会话门那一读,应答头发出之前;体同上)": { attr: 503, since: "7.137.0" },
363
+ "GET /v1/sessions/:id/sync/history/blobs/:hash#store_connection_fault_session_gate(会话门那一读;体同上)": { attr: 503, since: "7.137.0" },
364
+ "GET /v1/sessions/:id/sync/manifest#store_deployment_fault(缺表 / 权限拒;门读与读腿同一形;体 state.file_history_unreadable + permanence: terminal)": { attr: 503, since: "7.137.0" },
365
+ "GET /v1/sessions/:id/sync/entries#store_deployment_fault(应答头发出之前;体同上)": { attr: 503, since: "7.137.0" },
366
+ "GET /v1/sessions/:id/sync/history/blobs/:hash#store_deployment_fault(体同上)": { attr: 503, since: "7.137.0" },
311
367
  "GET /v1/sessions/:id/events#corrupt_archive(DB_BACKEND=local;开流之前;体 corrupt_session)": { attr: 500, since: "7.136.0" },
312
368
  "PATCH /v1/sessions/:id#corrupt_archive(DB_BACKEND=local;体 corrupt_session)": { attr: 500, since: "7.136.0" },
369
+ "POST /v1/tasks#stored_log_invalid(同步腿;打开已存日志撞上结构坏:悬空父 / 自指 / 成环 / 叶子缺席;零工作的拒;体 invalid_session)": { attr: 500, since: "7.137.0" },
313
370
  "POST /v1/sessions/:id/sync/import#identical_repush_blob_missing(体 missing_blob)": { attr: 422, since: "7.136.0" },
314
371
  "PATCH /v1/sessions/:id#title_no_visible_character(体 request.field_invalid)": { attr: 400, since: "7.136.0" },
315
372
  "POST /v1/sessions/:id/sync/import#title_no_visible_character(Phase A 体的 title;体 request.field_invalid)": { attr: 400, since: "7.136.0" },
@@ -321,6 +378,16 @@ export const SELF_MINTED_WIRE = {
321
378
  "POST /v1/tool-approvals/:id/respond#edited_rule_text_refused_after_adoption(匿名活卡收编给具名主体后新属主交坏规则文本;体 request.body_shape;契约成文的判据,今天经 /v1/adoption 到不了)": { attr: 400, since: "7.136.0" },
322
379
  "POST /v1/tasks|/v1/runs#command_line_slots_without_sealed_key_store(stdio MCP 的 command / args 与 command hook 的 command / args;体 conflict.checkpoint_ctx_unsealable + field + reason no_key_store;POST /v1/tasks/stream 在终局帧上带本码;本服务自己的装配下不可达(装配期已对「店在而封签器缺席」拒启,见 submit-ctx.ts 自述))": { attr: 409, since: "7.136.0" },
323
380
  "ALL authenticated routes#bearer_token_without_scope_claim(鉴权桥验证腿;配了 service 凭据或多租 REQUIRE_PRINCIPAL 的部署;体通用 auth.unauthorized)": { attr: 401, since: "7.136.0" },
381
+ "ALL principal-reading routes#principal_not_a_name(主体头 / SSO 令牌的 sub / 直连门 JWT 的 sub 不是一位主体的名字:空 / 空白 / 带控制、行段分隔或不可见格式字符;体 principal_not_a_name)": { attr: 400, since: "7.137.0" },
382
+ "POST /v1/tasks|/v1/tasks/stream|/v1/runs#promptProfile(新提交;体 request.body_shape + unknownKeys [promptProfile])": { attr: 400, since: "7.137.0" },
383
+ "POST /v1/tasks|/v1/tasks/stream|/v1/runs#skills[i].mods|agents[i].skills[j].mods(新提交;体 request.field_invalid)": { attr: 400, since: "7.137.0" },
384
+ "PUT /v1/sessions/:id/policy|POST /v1/sessions/:id/sync/import#toolDeny 名内带 *(`*` / `mcp__git*` / `Bas*`)": { attr: 200, since: "7.137.0" },
385
+ "POST /v1/tasks|/v1/tasks/stream|/v1/runs#限制侧名内带 *(settings.permissions.deny|ask)": { attr: 200, since: "7.137.0" },
386
+ "POST /v1/tasks|/v1/tasks/stream|/v1/runs#限制侧名内带 *(excludeTools)": { attr: 200, since: "7.137.0" },
387
+ "POST /v1/tasks|/v1/tasks/stream|/v1/runs#限制侧名内带 *(skills[i].disallowedTools|agents[i].skills[j].disallowedTools)": { attr: 200, since: "7.137.0" },
388
+ "POST /v1/tasks|/v1/tasks/stream|/v1/runs#限制侧名内带 *(agents[i].denyTools)": { attr: 200, since: "7.137.0" },
389
+ "POST /v1/assistant/tasks/:id/plan_review#checkpointId_not_current(体带的门身份不是该会话此刻待决的 plan 门;体 approval_stale + currentPending { checkpointId }?;不落决断、零状态改动)": { attr: 409, since: "7.137.0" },
390
+ "POST /v1/assistant/tasks/:id/plan_review#checkpointId_current(体带当前门的身份;受理形与不带键同)": { attr: 200, since: "7.137.0" },
324
391
  },
325
392
  },
326
393
  refusalSentenceForm: {
@@ -333,6 +400,7 @@ export const SELF_MINTED_WIRE = {
333
400
  "400 request.field_invalid#a2aPeers[i].url|cardUrl.credential": { attr: "<field> (peer <name>) is not a usable declaration — <rule> …", since: "7.136.0" },
334
401
  "400 request.field_invalid#title.no_visible_character(PATCH /v1/sessions/:id · 会话同步 2c 导入的 title)": { attr: "title must contain at least one visible character", since: "7.136.0" },
335
402
  "503 state.file_history_unreadable#store_connection_fault(会话同步三条拉取读腿)": { attr: "this session's stored state could not be read right now (the store connection failed), so nothing was exported — retry later", since: "7.136.0" },
403
+ "503 state.file_history_unreadable#store_deployment_fault(会话同步三条拉取口)": { attr: "this session's stored state cannot be read: the store does not match what this deployment requires (a table is missing or the database account lacks a privilege), so nothing was exported — retrying will not help until an operator repairs the store", since: "7.137.0" },
336
404
  "connect_failed(run 失败终局)#snapshot_bucket_missing(k8s 车道读 latest 得 404 NoSuchBucket;连沙箱失败,一只 pod 都不建)": { attr: "workspace space pointer read failed (snapshot_bucket_missing): the workspace snapshot bucket <name> (WORKSPACE_SNAPSHOT_BUCKET; default workspaces) does not exist in the object store — refusing to start this run … Ways out: create the bucket, or set WORKSPACE_SNAPSHOT_BUCKET to one that exists, or set WORKSPACE_PERSIST=off …", since: "7.136.0" },
337
405
  "400 request.field_invalid#images[i].url.credential": { attr: "<field> <规则句> — the URL is kept as written (a parked task's resume context, logs), while images[i] can carry the image bytes inline: send { data, mimeType } instead of a URL that holds the credential", since: "7.136.0" },
338
406
  "400 request.field_invalid#a2aPeers.not_array": { attr: "head: a2aPeers is <shape>, not an array of A2A peer declarations", since: "7.136.0" },
@@ -341,12 +409,52 @@ export const SELF_MINTED_WIRE = {
341
409
  "400 request.body_shape#a2aPeers[i].unknown_key": { attr: "body: unrecognized key(s) on an A2A peer declaration — refused rather than dropped …; Accepted per entry: <keys>", since: "7.136.0" },
342
410
  "409 conflict.checkpoint_ctx_unsealable#submit(提交面:本服务没有保管店)": { attr: "slots: static request headers, the command lines and environment values given to MCP stdio servers and command hooks, settings.env, or settings.webSearch.apiKey", since: "7.136.0" },
343
411
  "409 conflict.checkpoint_ctx_unsealable#resume(续跑上下文读口)": { attr: "slots: static request headers, the command lines and environment values given to MCP stdio servers and command hooks, settings.env, or settings.webSearch.apiKey", since: "7.136.0" },
412
+ "400 request.field_invalid#promptLean.not_boolean": { attr: "promptLean must be a boolean", since: "7.137.0" },
413
+ "409 checkpoint.unsupported_version#retired_request_key(续跑问点:存体仍带退役请求键 promptProfile)": { attr: "this task was suspended by an earlier server version and its stored request still carries promptProfile, a request key this version no longer reads (…) … submit the work again as a new task with promptLean in place of promptProfile, …", since: "7.137.0" },
414
+ "400 request.field_invalid#skills[i].mods(顶层技能项)": { attr: "skill.mods is not a request key — skill registrations are code the deployment mounts, not request data (…)", since: "7.137.0" },
415
+ "400 request.field_invalid#attachments.not_object": { attr: "attachments must be an object { …, mcpInstructions?, mcpUnavailable? }", since: "7.137.0" },
416
+ "400 request.field_invalid#attachments.mcpUnavailable.not_boolean": { attr: "attachments.mcpUnavailable must be a boolean", since: "7.137.0" },
417
+ "读成空的规则条目拒句#wildcard_all(授予侧)": { attr: "`*` grants nothing on an allow list (the entries beside it still apply) — …; on a deny or ask list `*` is every tool", since: "7.137.0" },
418
+ "读成空的规则条目拒句#namespace_wildcard(授予侧)": { attr: "an allow list reads a `*` only in a protocol name's tool segment — …; on a deny or ask list a `*` in a name is a glob over the whole name (…)", since: "7.137.0" },
419
+ "400 request.field_invalid#plan_review.checkpointId.not_non_empty_string": { attr: "checkpointId must be a non-empty string (the identity of the plan gate you decided on: …)", since: "7.137.0" },
420
+ "400 request.field_invalid#plan_review.checkpointId.too_large": { attr: "checkpointId too large (max <n> chars)", since: "7.137.0" },
421
+ "400 request.body_shape#/decide.checkpointId(落 unsupportedKeys)": { attr: "unsupported (a body field of POST /v1/assistant/tasks/:id/plan_review — send it there, this door never reads it): checkpointId", since: "7.137.0" },
422
+ },
423
+ },
424
+ decisionBodyKey: {
425
+ at: "回决门族决断体的受理键(<端点>#<键> → 读法;只登本版新增的键)",
426
+ members: {
427
+ "POST /v1/assistant/tasks/:id/plan_review#checkpointId": { attr: "optional;non-empty-string≤128;not-current⇒409 approval_stale;direct-door:signed-envelope-ext", since: "7.137.0" },
428
+ },
429
+ },
430
+ approvalStaleBodyKey: {
431
+ at: "409 approval_stale 拒体(<端点>#<键> → 在场律)",
432
+ members: {
433
+ "POST /v1/assistant/tasks/:id/plan_review#currentPending.checkpointId": { attr: "present-iff", since: "7.137.0" },
434
+ },
435
+ },
436
+ parkLedgerRowKey: {
437
+ at: "GET /v1/runs/:id/events 的 suspended / needs_review 账本行 data(<键> → 在场律)",
438
+ members: {
439
+ checkpointId: { attr: "present-iff", since: "7.137.0" },
440
+ gate: { attr: "always", since: "1.214.2" },
441
+ reopened: { attr: "present-iff", since: "1.231.0" },
442
+ toolCallId: { attr: "present-iff", since: "7.41.0" },
443
+ },
444
+ },
445
+ approvalEnvelopeExtKey: {
446
+ at: "直连门证明 HMAC 信封第 6 位扩展对象的键(<键> → 用它的门)",
447
+ members: {
448
+ answer: { attr: "POST /v1/approvals/:sessionId/decide", since: "7.87.0" },
449
+ checkpointId: { attr: "POST /v1/assistant/tasks/:id/plan_review", since: "7.137.0" },
450
+ permissionModeAfter: { attr: "POST /v1/assistant/tasks/:id/plan_review", since: "7.87.0" },
344
451
  },
345
452
  },
346
453
  storeFaultPermanence: {
347
454
  at: "文件历史店故障答的体键 permanence(422 adopt_failed · restore_failed 等 · 503 state.file_history_unreadable)",
348
455
  members: {
349
456
  transient: { attr: "present-iff", since: "7.136.0" },
457
+ "terminal#deployment": { attr: "present-iff", since: "7.137.0" },
350
458
  },
351
459
  },
352
460
  configCatalogRow: {
@@ -355,6 +463,14 @@ export const SELF_MINTED_WIRE = {
355
463
  SEALED_KEY_DIR: { attr: "store", since: "7.136.0" },
356
464
  },
357
465
  },
466
+ deviceProtocolRevision: {
467
+ at: "GET /v1/capabilities deviceExecutor.protocolVersion 与 device WS challenge 帧的修订号(<修订号> → 它加进结局码闭集的词)",
468
+ members: {
469
+ 1: { attr: "base", since: "7.51.0" },
470
+ 2: { attr: "+liveness_no_output", since: "7.133.0" },
471
+ 3: { attr: "+name_too_long", since: "7.137.0" },
472
+ },
473
+ },
358
474
  wireValueRule: {
359
475
  at: "出口值变换(<端点>#<键> → 变换)",
360
476
  members: {
@@ -377,6 +493,12 @@ export const SELF_MINTED_WIRE = {
377
493
  "GET /v1/config/catalog#rows[WORKSPACE_SNAPSHOT_BUCKET].semantics": { attr: "boot-checks-bucket;runtime-latest-no-such-bucket-fails-run", since: "7.136.0" },
378
494
  "GET /v1/config/catalog#rows[WORKSPACE_SNAPSHOT_PREFIX].semantics": { attr: "multi-segment-prefix;bad-segment-refuses-boot", since: "7.136.0" },
379
495
  "GET /v1/config/catalog#rows[WORKSPACE_SNAPSHOT_PREFIX].derivedDefaultNote": { attr: "absent=>kata", since: "7.136.0" },
496
+ "GET /v1/config/catalog#rows[K8S_SANDBOX_ENV].semantics": { attr: "values-only-in-the-pod-own-secret;role-needs-secrets-create;denied-refuses-boot", since: "7.137.0" },
497
+ "GET /v1/sessions/:id/mcp#servers[].error": { attr: "redactSecrets-outside-engine-marks+truncate:200", since: "7.137.0" },
498
+ "POST /v1/sessions/:id/mcp/reconnect#reason|status.error|listingIncomplete.error": { attr: "redactSecrets-outside-engine-marks+truncate:200", since: "7.137.0" },
499
+ "GET /v1/config/catalog#rows[MODEL_VISION].semantics": { attr: "names-engine-notice:model.capability_downgraded", since: "7.137.0" },
500
+ "GET /v1/config/catalog#rows[MODEL_VISION].derivedDefaultNote": { attr: "names-engine-notice:model.capability_downgraded", since: "7.137.0" },
501
+ "GET /v1/config/catalog#rows[MODEL_CHEAP_VISION].semantics": { attr: "names-engine-notice:model.capability_downgraded", since: "7.137.0" },
380
502
  },
381
503
  },
382
504
  };
@@ -129,13 +129,13 @@ export declare const WIRE_PROJECTION_FACES: {
129
129
  readonly tool_start: {
130
130
  readonly projector: "toolStartEventData";
131
131
  readonly coreType: string;
132
- readonly excluded: readonly [];
132
+ readonly excluded: readonly ["requestedBy"];
133
133
  readonly minted: readonly [];
134
134
  };
135
135
  readonly tool_end: {
136
136
  readonly projector: "toolEndEventData";
137
137
  readonly coreType: string;
138
- readonly excluded: readonly [];
138
+ readonly excluded: readonly ["requestedBy", "answeredBy"];
139
139
  readonly minted: readonly [];
140
140
  };
141
141
  readonly tool_progress: {
@@ -226,9 +226,10 @@ export declare const WIRE_PROJECTION_FACES: {
226
226
  readonly wiring_manifest_tenant: {
227
227
  readonly projector: "wiringManifestEventData";
228
228
  readonly coreType: `WiringManifest & ${string}`;
229
- readonly excluded: readonly ["governance", "configFingerprint", "autoConsolidation", "readDeny", "peerPresence", "advisor"];
229
+ readonly excluded: readonly ["governance", "configFingerprint", "autoConsolidation", "readDeny", "peerPresence", "advisor", "hostFloor"];
230
230
  readonly unwrapped: readonly ["manifest"];
231
231
  readonly minted: readonly ["instructions"];
232
+ readonly mintedConditional: readonly ["skills"];
232
233
  };
233
234
  readonly wiring_manifest_operator: {
234
235
  readonly projector: "wiringManifestOperatorEventData";
@@ -236,6 +237,7 @@ export declare const WIRE_PROJECTION_FACES: {
236
237
  readonly excluded: readonly string[];
237
238
  readonly unwrapped: readonly ["manifest"];
238
239
  readonly minted: readonly string[];
240
+ readonly mintedConditional: readonly string[];
239
241
  };
240
242
  readonly engine_notice: {
241
243
  readonly projector: "engineNoticeEventData";
@@ -26,8 +26,8 @@ function withoutSections(all, drop) {
26
26
  export const WIRE_PROJECTION_FACES = {
27
27
  task_progress: { projector: "taskProgressEventData", coreType: arm("task_progress"), excluded: [], minted: [] },
28
28
  task_started: { projector: "taskStartedEventData", coreType: arm("task_started"), excluded: [], minted: [] },
29
- tool_start: { projector: "toolStartEventData", coreType: arm("tool_start"), excluded: [], minted: [] },
30
- tool_end: { projector: "toolEndEventData", coreType: arm("tool_end"), excluded: [], minted: [] },
29
+ tool_start: { projector: "toolStartEventData", coreType: arm("tool_start"), excluded: ["requestedBy"], minted: [] },
30
+ tool_end: { projector: "toolEndEventData", coreType: arm("tool_end"), excluded: ["requestedBy", "answeredBy"], minted: [] },
31
31
  tool_progress: { projector: "toolProgressEventData", coreType: arm("tool_progress"), excluded: [], minted: [] },
32
32
  tool_disclosure: { projector: "toolDisclosureEventData", coreType: arm("tool_disclosure"), excluded: [], minted: [] },
33
33
  tool_roster_delta: { projector: "toolRosterDeltaEventData", coreType: arm("tool_roster_delta"), excluded: [], minted: [] },
@@ -51,9 +51,10 @@ export const WIRE_PROJECTION_FACES = {
51
51
  wiring_manifest_tenant: {
52
52
  projector: "wiringManifestEventData",
53
53
  coreType: `WiringManifest & ${arm("wiring_manifest")}`,
54
- excluded: ["governance", "configFingerprint", "autoConsolidation", "readDeny", "peerPresence", "advisor"],
54
+ excluded: ["governance", "configFingerprint", "autoConsolidation", "readDeny", "peerPresence", "advisor", "hostFloor"],
55
55
  unwrapped: ["manifest"],
56
56
  minted: ["instructions"],
57
+ mintedConditional: ["skills"],
57
58
  },
58
59
  wiring_manifest_operator: {
59
60
  projector: "wiringManifestOperatorEventData",
@@ -65,6 +66,9 @@ export const WIRE_PROJECTION_FACES = {
65
66
  get minted() {
66
67
  return WIRE_PROJECTION_FACES.wiring_manifest_tenant.minted;
67
68
  },
69
+ get mintedConditional() {
70
+ return WIRE_PROJECTION_FACES.wiring_manifest_tenant.mintedConditional;
71
+ },
68
72
  },
69
73
  engine_notice: { projector: "engineNoticeEventData", coreType: "EngineNotice", excluded: [], minted: ["ts"] },
70
74
  memory_import_report: { projector: "buildImportReportWire", coreType: "MemoryImportReport", excluded: [], minted: [] },
@@ -52,7 +52,6 @@ function toModel(m, envDefaults = {}, logger) {
52
52
  ...(thinkingDefault ? { defaultThinking: thinkingDefault } : {}),
53
53
  ...(compat ? { compat } : {}),
54
54
  ...(m.extraBody ? { extraBody: m.extraBody } : {}),
55
- ...(Array.isArray(m.promptGuidance) && m.promptGuidance.length > 0 ? { promptGuidance: m.promptGuidance.map(String) } : {}),
56
55
  ...buildModelHeadersKey(m.name, m.headers, m.api),
57
56
  };
58
57
  const explicitAct = m.autoCompactTokens;
@@ -63,6 +63,14 @@ export declare function pullViewQuery(view: {
63
63
  readonly worker?: string | undefined;
64
64
  readonly principal?: string | undefined;
65
65
  }): string;
66
+ /**
67
+ * 中心回了重定向(`egress-redirect.ts` 的判据:`opaqueredirect` 或任何 3xx;304 除外,见 {@link NOT_MODIFIED}):不跟、不重试,类型化拒。拒句是 `egress-redirect.ts` 既有 helper 的那一句(与 hook 直连腿 /
68
+ * 记忆 embedder 同一条律),前面冠上这条请求打的那一席;不回显 `Location`。`status` 是中心回的码(续签器据此落「被拒」终态)。
69
+ */
70
+ export declare class CenterRedirectRefusedError extends Error {
71
+ readonly status: number;
72
+ constructor(status: number, message: string);
73
+ }
66
74
  export interface CenterRequestInit {
67
75
  readonly method?: "GET" | "POST" | "DELETE";
68
76
  /** JSON 请求体(在场 ⇒ `content-type: application/json`)。 */
@@ -84,13 +92,23 @@ export declare function pathBaseUrlRefusal(subject: string, raw: string): string
84
92
  * [ref] —— 凭证续签:`POST {issuer}/api/v1/auth/token/refresh`,form `refresh_token=…`(settings-schema `AUTH_V1_PATHS.tokenRefresh`)。
85
93
  * · 以 `issuer` 为根(可带路径前缀;同源与否由续签器先判,本函数只装配);query / fragment 不带过去。
86
94
  * · **不带 Authorization**:这条端点凭 refresh token 认人,手里的 access token 可能已经过期。
87
- * · `redirect: "manual"`:3xx 不跟 —— POST 307/308 会把体(= refresh token)原样带去 `Location`,同源判据在重定向面前失效。
88
- * 3xx 原样交回,续签器按「被拒」处置。
95
+ * · 经 {@link sendToCenter}(`redirect: "manual"`):POST 307/308 会把体(= refresh token)原样带去 `Location`,同源判据在重定向面前失效 ⇒
96
+ * 中心回重定向 ⇒ 抛 {@link CenterRedirectRefusedError}(不跟),续签器把它落成「被拒」终态(配置事故,重试无益)。
89
97
  */
90
98
  export declare function centerTokenRefresh(issuer: string, refreshToken: string, init: {
91
99
  readonly timeoutMs: number;
92
100
  readonly fetchImpl?: typeof fetch;
93
101
  }): Promise<Response>;
102
+ /**
103
+ * 鉴权桥的 JWKS 拉取:`GET <jwksUrl>`,不带凭证(公钥集是公开的)。地址缺省 = 签发方(`SEMA_WEB_ADMIN_URL` / `AUTH_BRIDGE_ISSUER`)+ 契约包的
104
+ * `WEB_ADMIN_JWKS_PATH`,运维可用 `AUTH_BRIDGE_JWKS_URL` 改写 —— 打的是中心的公钥面,所以同经 {@link sendToCenter}:回重定向 ⇒ 同一只类型化拒、不跟
105
+ * (此前它自带 `redirect: "error"`,是中心面上的第二种重定向读法,拒句是传输层的 `fetch failed`、不点名出路)。体量帽 / 解析 / 缓存仍是调用方
106
+ * (`auth-bridge.ts`)的事;本函数只发这一次请求。
107
+ */
108
+ export declare function centerJwksFetch(jwksUrl: string, init: {
109
+ readonly timeoutMs: number;
110
+ readonly fetchImpl?: typeof fetch | undefined;
111
+ }): Promise<Response>;
94
112
  /**
95
113
  * 对中心发一条请求。返回响应与**这次请求所用凭证的身份**(调用方据此给拿回来的候选打分箱标记,
96
114
  * 见 `boot/web-admin.ts` 的 LKG / prompt 状态分箱)。
@@ -4,6 +4,7 @@ import { FLEET_LIVE_PATHS, FLEET_PATHS } from "@sema-agent/settings-schema/fleet
4
4
  import { CenterCredentialUnavailableError } from "../center-credential.js";
5
5
  import { WEB_ADMIN_ENV, httpUrlFlaws } from "@sema-agent/settings-schema";
6
6
  import { buildHttpUrlRefusal } from "../url-refusal.js";
7
+ import { egressRedirectRefusal } from "../egress-redirect.js";
7
8
  export const SCHEMA_MAJOR_HEADER = "x-sema-schema-major";
8
9
  export const CENTER_PULL_TIMEOUT_MS = 8000;
9
10
  export const SETTINGS_SCHEMA_MAJOR = (() => {
@@ -57,6 +58,30 @@ function routePath(route, kind) {
57
58
  return "/api/config/execution-keys";
58
59
  }
59
60
  }
61
+ export class CenterRedirectRefusedError extends Error {
62
+ status;
63
+ constructor(status, message) {
64
+ super(message);
65
+ this.status = status;
66
+ this.name = "CenterRedirectRefusedError";
67
+ }
68
+ }
69
+ const NOT_MODIFIED = 304;
70
+ async function sendToCenter(fix, url, wire) {
71
+ const res = await (wire.fetchImpl ?? fetch)(url, {
72
+ method: wire.method,
73
+ headers: wire.headers,
74
+ ...(wire.body !== undefined ? { body: wire.body } : {}),
75
+ redirect: "manual",
76
+ signal: AbortSignal.timeout(wire.timeoutMs),
77
+ });
78
+ if (res.status === NOT_MODIFIED)
79
+ return res;
80
+ const refusal = egressRedirectRefusal(res, fix);
81
+ if (refusal !== undefined)
82
+ throw new CenterRedirectRefusedError(res.status, `web-admin center request: ${refusal}`);
83
+ return res;
84
+ }
60
85
  const PATH_BASE_FORBIDS = ["userinfo", "query", "fragment"];
61
86
  export function pathBaseUrlRefusal(subject, raw) {
62
87
  const flaws = httpUrlFlaws(raw, PATH_BASE_FORBIDS);
@@ -75,12 +100,20 @@ export async function centerTokenRefresh(issuer, refreshToken, init) {
75
100
  url.pathname = `${url.pathname.replace(/\/+$/, "")}${AUTH_V1_PATHS.tokenRefresh}`;
76
101
  url.search = "";
77
102
  url.hash = "";
78
- return (init.fetchImpl ?? fetch)(url, {
103
+ return sendToCenter(`the credential issuer must be the final center address — set ${WEB_ADMIN_ENV.url} to it and sign in again`, url, {
79
104
  method: "POST",
80
105
  headers: { [SCHEMA_MAJOR_HEADER]: SETTINGS_SCHEMA_MAJOR, "content-type": "application/x-www-form-urlencoded" },
81
106
  body: new URLSearchParams({ refresh_token: refreshToken }).toString(),
82
- redirect: "manual",
83
- signal: AbortSignal.timeout(init.timeoutMs),
107
+ timeoutMs: init.timeoutMs,
108
+ fetchImpl: init.fetchImpl,
109
+ });
110
+ }
111
+ export async function centerJwksFetch(jwksUrl, init) {
112
+ return sendToCenter(`declare the final JWKS address — AUTH_BRIDGE_JWKS_URL, or the issuer it derives from (${WEB_ADMIN_ENV.url} / AUTH_BRIDGE_ISSUER)`, jwksUrl, {
113
+ method: "GET",
114
+ headers: { [SCHEMA_MAJOR_HEADER]: SETTINGS_SCHEMA_MAJOR },
115
+ timeoutMs: init.timeoutMs,
116
+ fetchImpl: init.fetchImpl,
84
117
  });
85
118
  }
86
119
  export async function centerFetch(center, route, init) {
@@ -99,12 +132,14 @@ export async function centerFetch(center, route, init) {
99
132
  const liveBase = FLEET_LIVE_PATHS.includes(path) ? center.liveBaseUrl : undefined;
100
133
  if (liveBase !== undefined)
101
134
  assertPathBaseUrl(liveBase, WEB_ADMIN_ENV.liveUrl);
135
+ const seat = liveBase !== undefined ? WEB_ADMIN_ENV.liveUrl : WEB_ADMIN_ENV.url;
102
136
  const url = `${(liveBase ?? center.baseUrl).replace(/\/+$/, "")}${path}`;
103
- const res = await (init.fetchImpl ?? fetch)(url, {
137
+ const res = await sendToCenter(`declare the final address in ${seat}`, url, {
104
138
  method: init.method ?? "GET",
105
139
  headers,
106
140
  ...(init.json !== undefined ? { body: JSON.stringify(init.json) } : {}),
107
- signal: AbortSignal.timeout(init.timeoutMs),
141
+ timeoutMs: init.timeoutMs,
142
+ fetchImpl: init.fetchImpl,
108
143
  });
109
144
  return { res, identity: cred.identity };
110
145
  }
@@ -3,7 +3,7 @@ import { readEffectiveWire, PrincipalCapsWire } from "@sema-agent/settings-schem
3
3
  import { separateRetiredDomains, splitFoldedReadWarnings, withDroppedCatalogEntries } from "./read-warnings.js";
4
4
  import { CENTER_PULL_TIMEOUT_MS, centerFetch } from "./center-request.js";
5
5
  import { answerStillCurrent } from "../center-credential.js";
6
- export async function fetchEffective(center, etag, fetchImpl = fetch, worker) {
6
+ export async function fetchEffective(center, etag, fetchImpl, worker) {
7
7
  const { res, identity } = await centerFetch(center, { kind: "effective", worker }, { etag, timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
8
8
  if (res.status === 304)
9
9
  return null;
@@ -25,7 +25,7 @@ export async function fetchEffective(center, etag, fetchImpl = fetch, worker) {
25
25
  ...(retiredDomains.length > 0 ? { retiredDomains: [...retiredDomains] } : {}),
26
26
  };
27
27
  }
28
- export async function fetchPrincipalCaps(center, principal, etag, fetchImpl = fetch, worker) {
28
+ export async function fetchPrincipalCaps(center, principal, etag, fetchImpl, worker) {
29
29
  const raw = await requestPrincipalView(center, principal, etag, fetchImpl, worker);
30
30
  if (raw === null)
31
31
  return null;
@@ -99,7 +99,7 @@ async function requestPrincipalView(center, principal, etag, fetchImpl, worker)
99
99
  return { json, ...(responseEtag !== null ? { etag: responseEtag } : {}) };
100
100
  }
101
101
  const PrincipalOrgMemoryEnvelope = PrincipalCapsWire.pick({ principal: true, orgMemory: true });
102
- export async function fetchPrincipalOrgMemory(center, principal, fetchImpl = fetch, worker) {
102
+ export async function fetchPrincipalOrgMemory(center, principal, fetchImpl, worker) {
103
103
  const raw = await requestPrincipalView(center, principal, undefined, fetchImpl, worker);
104
104
  if (raw === null)
105
105
  throw new Error("web-admin returned 304 to a non-conditional org-directory fetch");
@@ -118,7 +118,7 @@ export class WebAdminHttpError extends Error {
118
118
  this.name = "WebAdminHttpError";
119
119
  }
120
120
  }
121
- export async function fetchSkillContent(center, contentHash, fetchImpl = fetch) {
121
+ export async function fetchSkillContent(center, contentHash, fetchImpl) {
122
122
  const { res } = await centerFetch(center, { kind: "skill-content", contentHash }, { timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
123
123
  if (!res.ok)
124
124
  throw new WebAdminHttpError(`skill content HTTP ${res.status} for ${contentHash}`, res.status);
@@ -129,13 +129,13 @@ export async function fetchSkillContent(center, contentHash, fetchImpl = fetch)
129
129
  throw new Error(`skill content hash mismatch for ${contentHash}: computed sha256:${got}`);
130
130
  return content;
131
131
  }
132
- export async function fetchPromptArtifact(center, artifactDigest, fetchImpl = fetch) {
132
+ export async function fetchPromptArtifact(center, artifactDigest, fetchImpl) {
133
133
  const { res } = await centerFetch(center, { kind: "prompt-artifact", digest: artifactDigest }, { timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
134
134
  if (!res.ok)
135
135
  throw new WebAdminHttpError(`prompt artifact HTTP ${res.status} for ${artifactDigest}`, res.status);
136
136
  return await res.json();
137
137
  }
138
- export async function fetchPromptBlob(center, contentDigest, fetchImpl = fetch) {
138
+ export async function fetchPromptBlob(center, contentDigest, fetchImpl) {
139
139
  const { res } = await centerFetch(center, { kind: "prompt-blob", digest: contentDigest }, { timeoutMs: CENTER_PULL_TIMEOUT_MS, fetchImpl });
140
140
  if (!res.ok)
141
141
  throw new WebAdminHttpError(`prompt blob HTTP ${res.status} for ${contentDigest}`, res.status);
@@ -75,11 +75,11 @@ export interface CenterModel {
75
75
  * the ONLY way to keep per-model tuning that lived in env (`MODEL_FREQUENCY_PENALTY` etc.) — see the
76
76
  * review-gw heterogeneous-roster migration. MUST be static per published version (prompt-cache prefix). */
77
77
  extraBody?: Record<string, unknown>;
78
- /** registry-core 0.10.13 ([ref]/[ref]⑤c): per-model behavior-slot mitigation sentences, mirrors core
79
- * `Model.promptGuidance` (core 1.303+ assembles them into the volatile tail's per-model position).
80
- * Same category as `extraBody`: logical model metadata, carried verbatim — without this projection the
81
- * configured sentences parse fine in registry-core but never reach the assembly face ([ref]① 排雷:
82
- * the missing leg made every promptGuidance pilot a false control). */
78
+ /** registry-core 0.10.13 ([ref]/[ref]⑤c): per-model behavior-slot sentences. core 7.56.0 ([ref]) retired the engine seat
79
+ * (`Model.promptGuidance`; per-model guidance is now a prompt overlay keyed on the model's declared traits), while the
80
+ * settings-schema `ModelEntry` still accepts the key. It is carried here ONLY so the [ref] judge (`judgeCatalogEntry`)
81
+ * can see it: a non-empty list refuses the entry (`config.model_entry_invalid`, field `promptGuidance`) instead of the
82
+ * sentences being silently dropped; `toModel` never mints it onto a core `Model`. */
83
83
  promptGuidance?: string[];
84
84
  /**
85
85
  * [ref](7.108.0)—— 这条条目发给供应商的**附加请求头**(部署 ↔ 供应商的契约;今天只有 `anthropic-beta`),上 core 的 per-model
@@ -18,8 +18,11 @@ dials the device, so the device needs no inbound port, no public address and no
18
18
 
19
19
  **Discovery before you connect**: `GET /v1/capabilities` carries a `deviceExecutor` key — either `false`
20
20
  (this deployment has no device lane) or an object `{ enabled: true, protocolVersion, maxInflightPerDevice,
21
- wsPath, management }`. Read `wsPath` from there rather than hardcoding it: the path is part of the wire
22
- contract and reading it means a future path change is not a cross-repo break. `protocolVersion` tells you
21
+ wsPath, management, relayUrl? }`. Read `wsPath` from there rather than hardcoding it: the path is part of the wire
22
+ contract and reading it means a future path change is not a cross-repo break. `relayUrl` (server 7.137.0+) is present
23
+ only when the operator declared one (`DEVICE_RELAY_URL`): the engine sits behind a relay or gateway and the device
24
+ must dial that absolute `ws://` / `wss://` URL verbatim instead of the engine's own address — do not rebuild it from
25
+ the engine address and `wsPath`. Absent ⇒ dial the engine's own address at `wsPath`, as before. `protocolVersion` tells you
23
26
  which protocol **revision** the server speaks before you spend a handshake finding out (§2.1: the revision decides
24
27
  which `errorCode` words the server accepts from you).
25
28
 
@@ -136,7 +139,8 @@ Ask for a new enrollment token and try again."* Do not retry the same token afte
136
139
 
137
140
  ### 1.2 Connecting
138
141
 
139
- Open a WebSocket to `wsPath` (`GET`, standard upgrade). The server refuses the upgrade with `404` for any
142
+ Open a WebSocket to `relayUrl` when the capability carries one, otherwise to `wsPath` on the engine's own
143
+ address (`GET`, standard upgrade). The server refuses the upgrade with `404` for any
140
144
  other path, and with `503` while the replica is draining or when its pre-auth connection caps are full.
141
145
  There is no authentication in the upgrade headers — the handshake happens **inside** the protocol.
142
146
 
@@ -336,7 +340,7 @@ base64 inside JSON fields.
336
340
  | Constant | Value | Meaning |
337
341
  |---|---|---|
338
342
  | `DEVICE_WS_PATH` | `/v1/device/ws` | the upgrade path (prefer the `wsPath` from `/v1/capabilities`) |
339
- | `DEVICE_PROTOCOL_VERSION` | `2` | the protocol revision this server speaks (the highest it accepts) |
343
+ | `DEVICE_PROTOCOL_VERSION` | `3` | the protocol revision this server speaks (the highest it accepts) |
340
344
  | `DEVICE_MIN_PROTOCOL_VERSION` | `1` | the lowest revision it accepts; below it (or above the highest), a loud `helloReject` — never a silent downgrade |
341
345
  | `DEVICE_HELLO_DOMAIN_TAG` | `sema.device.hello.v1` | the handshake signature domain tag (§1.3) |
342
346
 
@@ -365,6 +369,7 @@ the union of the rows up to *N*, and the full set at the current revision is the
365
369
  |---|---|
366
370
  | `1` | `aborted`, `already_exists`, `auth_failed`, `callback_error`, `invalid`, `is_directory`, `not_directory`, `not_found`, `not_supported`, `outcome_unknown`, `permission_denied`, `precondition_failed`, `shell_unavailable`, `spawn_error`, `suspended`, `target_unavailable`, `timeout`, `transport_lost`, `unknown` |
367
371
  | `2` | `liveness_no_output` |
372
+ | `3` | `name_too_long` |
368
373
 
369
374
  Rules: adding a frame or a field is additive and does not raise the revision; adding a word to a closed set the
370
375
  server *accepts from you* (today: the `errorCode` set) raises `DEVICE_PROTOCOL_VERSION` and adds a row here; a
@@ -560,7 +565,7 @@ a moment ago. If you omit `created`, the consumer reports the weaker of the two
560
565
 
561
566
  `message` is required on the failure arm and is shown to the model — make it specific.
562
567
 
563
- This is the full set at the current revision (`2`); the revision table in §2.1 says which revision each word arrived
568
+ This is the full set at the current revision (`3`); the revision table in §2.1 says which revision each word arrived
564
569
  with, and an executor sends only the words of the revision it declared (§1.2).
565
570
 
566
571
  <!-- closed-set: DEVICE_OUTCOME_ERROR_CODES -->
@@ -574,6 +579,7 @@ with, and an executor sends only the words of the revision it declared (§1.2).
574
579
  | `invalid` | the arguments do not make sense for this target (e.g. `readLink` on a non-symlink) |
575
580
  | `is_directory` | a file operation hit a directory |
576
581
  | `liveness_no_output` | **you** killed the command because it produced no output for your own silence window (a hung command); the wall-clock budget `timeoutMs` running out stays `timeout`. The frame has no field for the window length — do not invent one |
582
+ | `name_too_long` | a component of the path is longer than the filesystem's name limit (`NAME_MAX`, 255 bytes; POSIX `ENAMETOOLONG` for such a component) — no directory can hold that name, so it is read upstream as an absence, like `not_found`. A path that is only too long as a whole while every component is short stays `unknown` (such a file may exist, reached from a directory below it). On an exec instruction it is a protocol violation (use `spawn_error` when the process could not be started) and the server reads it as `unknown` |
577
583
  | `not_directory` | a directory operation hit a non-directory |
578
584
  | `not_found` | the path does not exist |
579
585
  | `not_supported` | you do not implement this face (prefer simply not declaring it) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sema-agent/server",
3
- "version": "7.136.0",
3
+ "version": "7.137.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",
@@ -69,7 +69,7 @@
69
69
  "build:binary:run-local:darwin-arm64": "bun build --compile --target=bun-darwin-arm64 src/run-local.ts --outfile dist/run-local-darwin-arm64"
70
70
  },
71
71
  "dependencies": {
72
- "@sema-agent/core": "7.55.0",
72
+ "@sema-agent/core": "7.56.0",
73
73
  "@sema-agent/settings-schema": "14.5.0",
74
74
  "e2b": "^2.28.0",
75
75
  "libsodium-wrappers": "^0.8.4",