@sema-agent/server 7.135.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 (342) hide show
  1. package/MIGRATION.md +237 -2
  2. package/USAGE.md +146 -41
  3. package/deploy/sema-up/README.md +15 -1
  4. package/deploy/sema-up/chart/templates/NOTES.txt +1 -1
  5. package/deploy/sema-up/chart/templates/sandbox-rbac.yaml +7 -1
  6. package/deploy/sema-up/chart/values.yaml +1 -1
  7. package/deploy/sema-up/stack/sema-stack-cluster.yaml +7 -1
  8. package/dist/approval-card.d.ts +60 -4
  9. package/dist/approval-card.js +18 -1
  10. package/dist/approval-content-kind.d.ts +7 -0
  11. package/dist/approval-content-kind.js +8 -1
  12. package/dist/approval-gate-currency.d.ts +48 -6
  13. package/dist/approval-gate-currency.js +16 -9
  14. package/dist/approval-hmac.d.ts +13 -1
  15. package/dist/approval-hmac.js +1 -1
  16. package/dist/approval.js +3 -3
  17. package/dist/auth-bridge.d.ts +34 -5
  18. package/dist/auth-bridge.js +22 -5
  19. package/dist/boot/budget-tracing.d.ts +1 -2
  20. package/dist/boot/budget-tracing.js +2 -2
  21. package/dist/boot/execution-env.d.ts +24 -1
  22. package/dist/boot/execution-env.js +69 -6
  23. package/dist/boot/org-memory.js +1 -1
  24. package/dist/boot/reapers.d.ts +3 -0
  25. package/dist/boot/reapers.js +15 -1
  26. package/dist/boot/resolve-spec.d.ts +4 -0
  27. package/dist/boot/resolve-spec.js +24 -22
  28. package/dist/boot/runner-deps.js +4 -2
  29. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  30. package/dist/boot/stage-04-stores.d.ts +2 -2
  31. package/dist/boot/stage-05-execution-env.d.ts +4 -2
  32. package/dist/boot/stage-05-execution-env.js +11 -2
  33. package/dist/boot/stage-06-runners.d.ts +4 -2
  34. package/dist/boot/stage-06-runners.js +5 -1
  35. package/dist/boot/stage-07-capability-layer.d.ts +5 -2
  36. package/dist/boot/stage-07-capability-layer.js +1 -1
  37. package/dist/boot/stage-08-reapers.d.ts +5 -2
  38. package/dist/boot/stage-08-reapers.js +2 -1
  39. package/dist/boot/stage-09-leader.d.ts +5 -2
  40. package/dist/boot/stage-10-http-server.d.ts +5 -2
  41. package/dist/boot/stage-10-http-server.js +3 -2
  42. package/dist/boot/stores.d.ts +1 -1
  43. package/dist/boot/stores.js +2 -3
  44. package/dist/boot/web-admin.js +10 -17
  45. package/dist/brain.js +12 -3
  46. package/dist/broker/broker.d.ts +89 -0
  47. package/dist/broker/broker.js +287 -0
  48. package/dist/broker/constants.d.ts +39 -0
  49. package/dist/broker/constants.js +15 -0
  50. package/dist/broker/http1.d.ts +111 -0
  51. package/dist/broker/http1.js +256 -0
  52. package/dist/broker/lease-book.d.ts +87 -0
  53. package/dist/broker/lease-book.js +142 -0
  54. package/dist/broker/lease-file.d.ts +60 -0
  55. package/dist/broker/lease-file.js +127 -0
  56. package/dist/broker/main.d.ts +2 -0
  57. package/dist/broker/main.js +20 -0
  58. package/dist/budget.d.ts +3 -3
  59. package/dist/budget.js +4 -0
  60. package/dist/capabilities/composite-members.d.ts +2 -1
  61. package/dist/capabilities/composite-members.js +2 -1
  62. package/dist/capabilities/engine-capabilities.js +1 -0
  63. package/dist/capabilities/mcp-probe.d.ts +5 -4
  64. package/dist/capabilities/scenarios.d.ts +23 -8
  65. package/dist/capabilities/scenarios.js +13 -8
  66. package/dist/capabilities/skills.d.ts +28 -5
  67. package/dist/capabilities/skills.js +8 -0
  68. package/dist/capability-facts.d.ts +3 -7
  69. package/dist/capability-facts.js +3 -5
  70. package/dist/center-credential-renewer.js +5 -1
  71. package/dist/center-credential.d.ts +18 -4
  72. package/dist/center-credential.js +18 -3
  73. package/dist/checkpoint-ctx-seal-m28.d.ts +3 -10
  74. package/dist/checkpoint-ctx-seal-m28.js +1 -1
  75. package/dist/checkpoint-identity.d.ts +3 -3
  76. package/dist/config-catalog.js +21 -16
  77. package/dist/config-d-migration.js +1 -1
  78. package/dist/config-invariants.d.ts +1 -1
  79. package/dist/config-invariants.js +8 -0
  80. package/dist/config-lkg.d.ts +0 -38
  81. package/dist/config-lkg.js +1 -83
  82. package/dist/config-types.d.ts +21 -4
  83. package/dist/config.d.ts +1 -1
  84. package/dist/config.js +60 -16
  85. package/dist/deployment-governance.d.ts +2 -2
  86. package/dist/deployment-governance.js +7 -9
  87. package/dist/deployment-shape.d.ts +1 -1
  88. package/dist/device-ws-protocol.d.ts +1 -0
  89. package/dist/device-ws-protocol.js +2 -1
  90. package/dist/elicitation.d.ts +8 -7
  91. package/dist/elicitation.js +9 -8
  92. package/dist/file-history-disclosure.d.ts +8 -4
  93. package/dist/file-history-disclosure.js +24 -6
  94. package/dist/fleet-client.d.ts +32 -1
  95. package/dist/fleet-client.js +24 -4
  96. package/dist/fleet-lease.d.ts +7 -3
  97. package/dist/fleet-lease.js +31 -23
  98. package/dist/hooks/classic-stations.d.ts +11 -54
  99. package/dist/hooks/hook-llm.js +14 -8
  100. package/dist/hooks/hook-runner.d.ts +4 -4
  101. package/dist/hooks/hook-runner.js +2 -2
  102. package/dist/http/admission.js +10 -7
  103. package/dist/http/approval-sweeps.js +4 -3
  104. package/dist/http/caller-trust.d.ts +2 -1
  105. package/dist/http/caller-trust.js +1 -3
  106. package/dist/http/checkpoint-ctx.d.ts +76 -16
  107. package/dist/http/checkpoint-ctx.js +45 -1
  108. package/dist/http/dispatch.js +24 -19
  109. package/dist/http/durable-run-leg.d.ts +5 -1
  110. package/dist/http/durable-run-leg.js +1 -1
  111. package/dist/http/health-self-report.d.ts +2 -2
  112. package/dist/http/mcp-remote-text.d.ts +5 -0
  113. package/dist/http/mcp-remote-text.js +7 -0
  114. package/dist/http/principal-gate.d.ts +15 -10
  115. package/dist/http/principal-gate.js +48 -9
  116. package/dist/http/resume-ctx-read.d.ts +2 -16
  117. package/dist/http/resume-ctx-read.js +2 -3
  118. package/dist/http/resume-legs.d.ts +2 -20
  119. package/dist/http/resume-legs.js +52 -38
  120. package/dist/http/route-ctx.d.ts +8 -2
  121. package/dist/http/routes/approvals-assistant.d.ts +0 -2
  122. package/dist/http/routes/approvals-assistant.js +65 -16
  123. package/dist/http/routes/capabilities.js +11 -1
  124. package/dist/http/routes/mcp-reconnect.d.ts +1 -1
  125. package/dist/http/routes/mcp-reconnect.js +5 -7
  126. package/dist/http/routes/runs.js +4 -3
  127. package/dist/http/routes/session-sync.js +70 -12
  128. package/dist/http/routes/sessions.js +20 -15
  129. package/dist/http/routes/tasks.js +8 -6
  130. package/dist/http/server.d.ts +4 -0
  131. package/dist/http/stored-body-replay.d.ts +3 -3
  132. package/dist/http/stored-body-replay.js +6 -1
  133. package/dist/http/submit-ctx.js +1 -1
  134. package/dist/http/wire-types.d.ts +57 -30
  135. package/dist/identity-source.d.ts +65 -0
  136. package/dist/identity-source.js +45 -0
  137. package/dist/index.d.ts +1 -0
  138. package/dist/index.js +1 -0
  139. package/dist/memory-store-refusal.d.ts +3 -3
  140. package/dist/model-entry-refusal.d.ts +2 -0
  141. package/dist/model-entry-refusal.js +11 -0
  142. package/dist/model-route-gap.d.ts +49 -4
  143. package/dist/model-route-gap.js +34 -1
  144. package/dist/model-select.d.ts +6 -17
  145. package/dist/model-select.js +0 -3
  146. package/dist/namespaced-rule-name.d.ts +1 -1
  147. package/dist/object-store-buckets.d.ts +13 -0
  148. package/dist/object-store-buckets.js +3 -0
  149. package/dist/observability/fail-open.d.ts +19 -7
  150. package/dist/observability/fail-open.js +19 -7
  151. package/dist/observability/metrics.js +2 -2
  152. package/dist/observability/principal-context.d.ts +4 -1
  153. package/dist/observability/principal-context.js +6 -1
  154. package/dist/observability/run-terminal.js +1 -0
  155. package/dist/operator-ask.d.ts +2 -2
  156. package/dist/org-delivery-gate.js +1 -1
  157. package/dist/org-memory-admission.d.ts +2 -2
  158. package/dist/org-memory-admission.js +39 -2
  159. package/dist/parked-decide.d.ts +4 -3
  160. package/dist/parked-decide.js +29 -9
  161. package/dist/peer-directory.d.ts +2 -1
  162. package/dist/peer-directory.js +7 -5
  163. package/dist/permission-rule-list.d.ts +2 -2
  164. package/dist/plugins/approval-ask-store-sql.d.ts +8 -0
  165. package/dist/plugins/approval-ask-store-sql.js +3 -0
  166. package/dist/plugins/blob-backend.js +2 -1
  167. package/dist/plugins/checkpoint-index-columns.d.ts +50 -1
  168. package/dist/plugins/checkpoint-index-columns.js +28 -0
  169. package/dist/plugins/checkpoint-store-sql.d.ts +46 -12
  170. package/dist/plugins/checkpoint-store-sql.js +64 -35
  171. package/dist/plugins/file-history-store-sql.d.ts +6 -0
  172. package/dist/plugins/file-history-store-sql.js +37 -37
  173. package/dist/plugins/file-run-store.js +8 -2
  174. package/dist/plugins/k8s-exec-protocol.d.ts +69 -13
  175. package/dist/plugins/k8s-exec-protocol.js +116 -28
  176. package/dist/plugins/k8s-pod-delete-failure.d.ts +25 -0
  177. package/dist/plugins/k8s-pod-delete-failure.js +17 -0
  178. package/dist/plugins/k8s-pod-reaper.d.ts +112 -0
  179. package/dist/plugins/k8s-pod-reaper.js +122 -0
  180. package/dist/plugins/local-checkpoint-store.d.ts +3 -6
  181. package/dist/plugins/local-checkpoint-store.js +7 -6
  182. package/dist/plugins/memory-run-store.js +2 -0
  183. package/dist/plugins/one-time-migrations.d.ts +49 -37
  184. package/dist/plugins/one-time-migrations.js +87 -128
  185. package/dist/plugins/permission-rule-store-file.js +2 -2
  186. package/dist/plugins/permission-rule-store-sql.d.ts +17 -17
  187. package/dist/plugins/permission-rule-store-sql.js +16 -17
  188. package/dist/plugins/pg-pool.js +4 -0
  189. package/dist/plugins/pg-session-storage.js +2 -2
  190. package/dist/plugins/remote-env-adb.d.ts +3 -0
  191. package/dist/plugins/remote-env-adb.js +1 -0
  192. package/dist/plugins/remote-env-device.d.ts +3 -0
  193. package/dist/plugins/remote-env-device.js +4 -0
  194. package/dist/plugins/remote-env-e2b.d.ts +3 -0
  195. package/dist/plugins/remote-env-e2b.js +1 -0
  196. package/dist/plugins/remote-env-file-error.d.ts +8 -1
  197. package/dist/plugins/remote-env-file-error.js +7 -1
  198. package/dist/plugins/remote-env-host.d.ts +7 -1
  199. package/dist/plugins/remote-env-host.js +7 -1
  200. package/dist/plugins/remote-env-k8s.d.ts +154 -14
  201. package/dist/plugins/remote-env-k8s.js +300 -21
  202. package/dist/plugins/remote-env-local-docker.d.ts +3 -0
  203. package/dist/plugins/remote-env-local-docker.js +1 -0
  204. package/dist/plugins/remote-env-ssh.d.ts +3 -0
  205. package/dist/plugins/remote-env-ssh.js +1 -0
  206. package/dist/plugins/run-store-sql.js +10 -4
  207. package/dist/plugins/s3-answer.d.ts +15 -0
  208. package/dist/plugins/s3-answer.js +5 -0
  209. package/dist/plugins/session-ownership.d.ts +17 -3
  210. package/dist/plugins/session-ownership.js +19 -5
  211. package/dist/plugins/snapshot-bucket-presence.d.ts +39 -4
  212. package/dist/plugins/snapshot-bucket-presence.js +35 -7
  213. package/dist/plugins/sql-errors.d.ts +60 -0
  214. package/dist/plugins/sql-errors.js +64 -1
  215. package/dist/plugins/store-contracts.d.ts +10 -1
  216. package/dist/plugins/store-fault.d.ts +4 -0
  217. package/dist/plugins/store-fault.js +10 -0
  218. package/dist/plugins/tidb-pool.js +8 -1
  219. package/dist/plugins/tidb-session-store.js +2 -2
  220. package/dist/plugins/web-search.d.ts +1 -1
  221. package/dist/plugins/web-search.js +2 -2
  222. package/dist/request-declaration-refusal.d.ts +94 -0
  223. package/dist/request-declaration-refusal.js +78 -0
  224. package/dist/request-image-urls.d.ts +6 -0
  225. package/dist/request-image-urls.js +27 -0
  226. package/dist/request-key-closure.d.ts +5 -0
  227. package/dist/request-key-closure.js +5 -2
  228. package/dist/request-value-closure.d.ts +31 -2
  229. package/dist/request-value-closure.js +7 -1
  230. package/dist/rule-entry-list.d.ts +3 -2
  231. package/dist/rule-entry-list.js +2 -2
  232. package/dist/rules-consent.js +7 -4
  233. package/dist/run-local.d.ts +2 -2
  234. package/dist/runs.js +2 -1
  235. package/dist/runtime-caps-resolver.js +1 -1
  236. package/dist/runtime-governance.d.ts +5 -5
  237. package/dist/sandbox-git-lease.d.ts +49 -0
  238. package/dist/sandbox-git-lease.js +60 -0
  239. package/dist/sandbox-git-plane.d.ts +84 -0
  240. package/dist/sandbox-git-plane.js +105 -0
  241. package/dist/sandbox-pkg-source.d.ts +28 -1
  242. package/dist/sandbox-pkg-source.js +1 -2
  243. package/dist/sealed-key.d.ts +19 -0
  244. package/dist/sealed-key.js +47 -4
  245. package/dist/security.d.ts +16 -4
  246. package/dist/security.js +8 -3
  247. package/dist/server-secret-env.d.ts +6 -0
  248. package/dist/server-secret-env.js +14 -0
  249. package/dist/session-error-wire.d.ts +14 -6
  250. package/dist/session-error-wire.js +2 -1
  251. package/dist/session-incarnation.d.ts +16 -5
  252. package/dist/session-incarnation.js +7 -4
  253. package/dist/session-policy-wire.d.ts +1 -1
  254. package/dist/session-policy-wire.js +2 -2
  255. package/dist/session-row.d.ts +3 -17
  256. package/dist/session-row.js +4 -0
  257. package/dist/session-sync.d.ts +15 -3
  258. package/dist/session-sync.js +5 -2
  259. package/dist/spec-fields.d.ts +43 -13
  260. package/dist/spec-fields.js +33 -12
  261. package/dist/stored-request-prompt-profile-m30.d.ts +49 -0
  262. package/dist/stored-request-prompt-profile-m30.js +25 -0
  263. package/dist/task-a2a.d.ts +52 -81
  264. package/dist/task-a2a.js +219 -89
  265. package/dist/task-mcp.d.ts +7 -15
  266. package/dist/task-mcp.js +16 -51
  267. package/dist/task-settings.d.ts +2 -2
  268. package/dist/tool-approval.d.ts +35 -12
  269. package/dist/tool-approval.js +59 -39
  270. package/dist/tool-rule-names.d.ts +5 -0
  271. package/dist/trace/core-keyset-guard.d.ts +5 -5
  272. package/dist/trace/engine-notice-wire.d.ts +1 -1
  273. package/dist/trace/engine-notice-wire.js +2 -0
  274. package/dist/trace/exit-seat.js +37 -13
  275. package/dist/trace/ledger-sink.d.ts +4 -5
  276. package/dist/trace/ledger-sink.js +3 -7
  277. package/dist/trace/project.d.ts +37 -3
  278. package/dist/trace/project.js +20 -6
  279. package/dist/trace/redact.d.ts +40 -12
  280. package/dist/trace/redact.js +332 -128
  281. package/dist/trace/self-minted-wire.d.ts +641 -0
  282. package/dist/trace/self-minted-wire.js +201 -0
  283. package/dist/trace/wire-projection-faces.d.ts +5 -3
  284. package/dist/trace/wire-projection-faces.js +7 -3
  285. package/dist/url-credential-refusal.d.ts +52 -0
  286. package/dist/url-credential-refusal.js +14 -0
  287. package/dist/url-refusal.d.ts +13 -4
  288. package/dist/url-refusal.js +8 -2
  289. package/dist/web-admin-client/apply-effective.js +0 -1
  290. package/dist/web-admin-client/center-request.d.ts +20 -2
  291. package/dist/web-admin-client/center-request.js +40 -5
  292. package/dist/web-admin-client/http-client.js +6 -6
  293. package/dist/web-admin-client/types.d.ts +5 -5
  294. package/dist/workspace-space.d.ts +27 -0
  295. package/dist/workspace-space.js +26 -0
  296. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +11 -5
  297. package/package.json +4 -3
  298. package/scripts/drain-check-local.mjs +2 -1
  299. package/scripts/drain-check.mysql.sql +3 -1
  300. package/scripts/drain-check.pg.sql +3 -1
  301. package/skills/schedule.md +1 -1
  302. package/wire-changes/server@7.104.0.json +134 -0
  303. package/wire-changes/server@7.105.0.json +53 -0
  304. package/wire-changes/server@7.106.0.json +475 -0
  305. package/wire-changes/server@7.107.0.json +64 -0
  306. package/wire-changes/server@7.108.0.json +153 -0
  307. package/wire-changes/server@7.109.0.json +46 -0
  308. package/wire-changes/server@7.110.0.json +90 -0
  309. package/wire-changes/server@7.111.0.json +86 -0
  310. package/wire-changes/server@7.112.0.json +60 -0
  311. package/wire-changes/server@7.113.0.json +26 -0
  312. package/wire-changes/server@7.114.0.json +26 -0
  313. package/wire-changes/server@7.115.0.json +97 -0
  314. package/wire-changes/server@7.116.0.json +218 -0
  315. package/wire-changes/server@7.116.1.json +26 -0
  316. package/wire-changes/server@7.117.0.json +65 -0
  317. package/wire-changes/server@7.118.0.json +129 -0
  318. package/wire-changes/server@7.119.0.json +65 -0
  319. package/wire-changes/server@7.120.0.json +89 -0
  320. package/wire-changes/server@7.121.0.json +219 -0
  321. package/wire-changes/server@7.122.0.json +54 -0
  322. package/wire-changes/server@7.123.0.json +26 -0
  323. package/wire-changes/server@7.124.0.json +336 -0
  324. package/wire-changes/server@7.124.1.json +26 -0
  325. package/wire-changes/server@7.125.0.json +111 -0
  326. package/wire-changes/server@7.126.0.json +285 -0
  327. package/wire-changes/server@7.127.0.json +77 -0
  328. package/wire-changes/server@7.127.1.json +26 -0
  329. package/wire-changes/server@7.127.2.json +53 -0
  330. package/wire-changes/server@7.128.0.json +26 -0
  331. package/wire-changes/server@7.129.0.json +106 -0
  332. package/wire-changes/server@7.129.1.json +26 -0
  333. package/wire-changes/server@7.130.0.json +26 -0
  334. package/wire-changes/server@7.131.0.json +118 -0
  335. package/wire-changes/server@7.132.0.json +226 -0
  336. package/wire-changes/server@7.133.0.json +1155 -0
  337. package/wire-changes/server@7.134.0.json +107 -0
  338. package/wire-changes/server@7.135.0.json +174 -0
  339. package/wire-changes/server@7.136.0.json +448 -0
  340. package/wire-changes/server@7.137.0.json +825 -0
  341. package/dist/url-credential.d.ts +0 -52
  342. package/dist/url-credential.js +0 -49
@@ -50,7 +50,7 @@ import type { ServiceFileHistoryStore, ServiceSessionPolicyStore, ResumeAnchorSt
50
50
  /**
51
51
  * core 7.55.0 [ref] T2([ref]):一只会话的文件历史**读不全**(撕裂 / 读不出的边界、读不出的跟踪集 —— 店的 `exportHistory` 答 `{ ok: false }`,`adopt_failed`
52
52
  * 带店判的 `permanence`)。它**不是**「没有历史」:读成 `null` 的同步会把这只会话的全部 rewind 历史丢在路上、还答成功。会话同步的两只拉取口
53
- * (manifest、history blob)对它答同一句 503 `state.file_history_unreadable`(路由 `sendFileHistoryUnreadable`)。
53
+ * (manifest、history blob)对它答同一句 503 `state.file_history_unreadable`(路由 `sendPullUnreadable`;连接类故障在拉取口同码同体键答 `permanence: "transient"`,部署错配类故障〔缺表 / 权限拒〕答 `permanence: "terminal"`)。
54
54
  */
55
55
  export declare class FileHistoryUnreadableError extends Error {
56
56
  readonly sessionId: string;
@@ -67,9 +67,21 @@ export declare function exportedFileHistory(store: Pick<ServiceFileHistoryStore,
67
67
  * Returned by {@link exportSessionManifest} (closes over the source store); consumed wherever a caller pulls
68
68
  * content-addressed history bytes lazily (the live PUSH route's `importHistory` replay). */
69
69
  export type BlobGetter = (hash: string) => Promise<Uint8Array | undefined>;
70
- /** 一只文件历史店自己的 blob 取值口({@link BlobGetter}):店带 `getBlob` ⇒ 绑在店上;没有这条面(core 的 local 文件店)⇒ 恒答 `undefined`(「这里取不到」)。
70
+ /** blob 两面(`putBlob` / `getBlob`)齐备的文件历史店(marker 门,不做名字探测:local 的引擎文件店带同名私有助手)。 */
71
+ export type SyncBlobHistoryStore = ServiceFileHistoryStore & {
72
+ readonly syncBlobFaces: true;
73
+ } & {
74
+ [P in "putBlob" | "getBlob"]-?: NonNullable<ServiceFileHistoryStore[P]>;
75
+ };
76
+ /**
77
+ * 「这只文件历史店有没有 blob 两面」的**唯一**读法:marker `syncBlobFaces`(只有 SQL 两只店立它)∧ 两面在场。能力事实 `sessionSyncFileHistory`(capability-facts)
78
+ * 与取值口 {@link blobGetterOf} 都读它 —— 事实说有,取值口就通到事实店的 `getBlob`;事实说没有,取值口恒空。
79
+ * 名字探测(`store.getBlob?.…`)不可靠:core 的 local 文件店带与服务面同名的**私有**助手(同形 `putBlob` 已被 marker 挡过一次),名字探会错拿到它。
80
+ */
81
+ export declare function syncBlobFacesOf(store: ServiceFileHistoryStore): SyncBlobHistoryStore | undefined;
82
+ /** 一只文件历史店自己的 blob 取值口({@link BlobGetter}):从 {@link syncBlobFacesOf} 派生 —— 有 blob 两面 ⇒ 绑在店上的 `getBlob`;没有(core 的 local 文件店)⇒ 恒答 `undefined`(「这里取不到」)。
71
83
  * 拉取面(manifest 的 `getBlob`)、identical 自愈臂、提交臂三处读同一只,不各写一份「无面则 undefined」。 */
72
- export declare function blobGetterOf(store: Pick<ServiceFileHistoryStore, "getBlob">): BlobGetter;
84
+ export declare function blobGetterOf(store: ServiceFileHistoryStore): BlobGetter;
73
85
  /** The history-import capability face of a `FileHistoryStore` (`importHistory` is OPTIONAL on the core
74
86
  * contract — a store without it cannot be a 2c history sink). */
75
87
  export interface FileHistoryImportFace {
@@ -21,9 +21,12 @@ export async function exportedFileHistory(store, sessionId) {
21
21
  throw new FileHistoryUnreadableError(sessionId, exported.error);
22
22
  return exported.history;
23
23
  }
24
+ export function syncBlobFacesOf(store) {
25
+ return store.syncBlobFaces === true && typeof store.putBlob === "function" && typeof store.getBlob === "function" ? store : undefined;
26
+ }
24
27
  export function blobGetterOf(store) {
25
- const get = store.getBlob?.bind(store);
26
- return get ? (hash) => get(hash) : async () => undefined;
28
+ const faces = syncBlobFacesOf(store);
29
+ return faces ? (hash) => faces.getBlob(hash) : async () => undefined;
27
30
  }
28
31
  export function fileHistoryImportFace(fs) {
29
32
  const candidate = fs?.importHistory;
@@ -21,6 +21,32 @@ export declare function normalizeSuggestNextPrompts(v: unknown): TaskSpec["sugge
21
21
  * undefined (never an empty object — keeps the spec byte-identical for non-users).
22
22
  */
23
23
  export declare function normalizeResilience(v: unknown, operator: boolean): TaskSpec["resilience"];
24
+ /**
25
+ * 请求体 `attachments` 的子键**只有这一张表**(键 → 受理类别)。三处读它,不再各抄一份键名:
26
+ * · 导出类型 `TaskRequestAttachments`(`http/wire-types.ts`)—— 与本表互为差集门(下面两只 `_GuardAttachmentKeys*`:类型加 / 删一个键而本表没跟 ⇒ tsc 红);
27
+ * · 受理门(`http/admission.ts`)—— 非对象那一句列的键、布尔类键的逐键 `must be a boolean` 检查都从这里取;
28
+ * · 重放翻译口 {@link normalizeAttachments} —— 入参形与逐键赋值的键集都是本表(`parts` 记录对 {@link AttachmentKey} 穷举,少一个键 ⇒ tsc 红)。
29
+ * 类别只回答受理门一个问题:`boolean` = 值必须是布尔(literal-true 键与布尔透传键的差别在翻译口,不在门);`mode` = `todoReminderMode` 的枚举;
30
+ * `changedFiles` = 布尔或 `{ maxFiles }`。后两类各有自己的门。键的**顺序**就是受理门那一句里的顺序(句子字面另由错误文案冻结钉守)。
31
+ */
32
+ export type AttachmentKeyKind = "boolean" | "mode" | "changedFiles";
33
+ export declare const ATTACHMENT_KEY_KINDS: {
34
+ readonly todoReminder: "boolean";
35
+ readonly todoReminderMode: "mode";
36
+ readonly changedFiles: "changedFiles";
37
+ readonly budgetUsd: "boolean";
38
+ readonly backgroundTasks: "boolean";
39
+ readonly toolsDelta: "boolean";
40
+ readonly agentListing: "boolean";
41
+ readonly skillsListing: "boolean";
42
+ readonly mcpInstructions: "boolean";
43
+ readonly mcpUnavailable: "boolean";
44
+ };
45
+ export type AttachmentKey = keyof typeof ATTACHMENT_KEY_KINDS;
46
+ /** 表的键,原序。 */
47
+ export declare const ATTACHMENT_KEYS: readonly AttachmentKey[];
48
+ /** 受理门要验「值必须是布尔」的键(= 类别 `boolean`),原序。 */
49
+ export declare const ATTACHMENT_BOOLEAN_KEYS: readonly AttachmentKey[];
24
50
  /**
25
51
  * [ref] (core 1.251) — normalize `body.attachments` → `TaskSpec.attachments`. Core's contract is
26
52
  * literal-true unions ("关闭=删 key,勿传 false"): only `true` (or, for changedFiles, an object with a sane
@@ -163,21 +189,25 @@ export declare function toolNameListFromBody(raw: unknown): string[] | undefined
163
189
  export declare function allowToolsSpecFragment(raw: unknown): {
164
190
  allowTools?: string[];
165
191
  };
166
- /** [ref]/[ref] — body.promptProfile → `TaskSpec.promptProfile`(core 1.328 R2 主件,CC LT(model_id)
167
- * 同构双形轴)。语义:纯呈现轴不碰策略(simple=CC 212 短形面缺省;classic=长形面,可按任务/模型试分)
168
- * ⇒ 无租户门(deferTools 同姿势);全委托树继承由 core 管。缺省不挂键(引擎缺省 simple,byte-compat)。
192
+ /** core 7.56.0 [ref] — body.promptLean → `TaskSpec.promptLean`(提示词形的唯一任务开关:`true` 加 `lean_prompt` 特征、`false` 去掉它、
193
+ * 缺省 = 模型声明)。纯呈现轴不碰策略 ⇒ 无租户门(deferTools 同姿势);全委托树继承由 core 管。缺省不挂键(模型目录条目的声明说话)。
169
194
  *
170
- * ⚠️ **这不是一条 defer 注**([ref] 件⑤ 对表结论,core [ref] 同判):本段说的是 `promptProfile` 这根
171
- * **呈现**轴,它与 `deferMode` / `deferTools` 的延迟披露轴**无耦合** —— 上一行提 deferTools 只是在借它
172
- * 的「无租户门」姿势作类比。「引擎缺省 simple」这句本身在 core 5.40.0 上仍逐字为真
173
- * (`core/types.d.ts`:default "simple"),本批亲验未变。
174
- * 真正的 defer 轴对表(core 5.40.0 起 `deferMode:"auto"` 不再 sweep 内建;7.15.0 起它不再是第二道门,
175
- * 只是把候选集拓宽后走同一道阈值门)记在
176
- * `src/capabilities/tool-defer.ts` 的头注 —— 别把两根轴的结论写到一处。
177
- * DEFENSIVE(resume 重放不过 HTTP 400 门):非法值 ⇒ undefined;提交面另有 fail-loud 400(邻居姿势)。 */
178
- export declare function promptProfileFromBody(raw: unknown): "simple" | "classic" | undefined;
195
+ * ⚠️ **这不是一条 defer 注**:本段说的是提示词形这根**呈现**轴,它与 `deferMode` / `deferTools` 的延迟披露轴**无耦合** —— 上一行提
196
+ * deferTools 只是在借它的「无租户门」姿势作类比。真正的 defer 轴对表记在 `src/capabilities/tool-defer.ts` 的头注 —— 别把两根轴的结论写到一处。
197
+ * DEFENSIVE(resume 重放不过 HTTP 400 门):非布尔 ⇒ undefined;提交面另有 fail-loud 400(邻居姿势)。 */
198
+ export declare function promptLeanFromBody(raw: unknown): boolean | undefined;
199
+ /**
200
+ * `TaskSpec.promptLean` 的座位片段:体里的 `promptLean`(布尔才算,见 {@link promptLeanFromBody})是唯一读数;缺席 ⇒ 不挂键。两条腿同一读法:
201
+ * 退役键 `promptProfile` 不读 —— 新提交带它在键闭集门 400;7.136.x 存体里的它由一次性迁移 M30 在起服时改写成 `promptLean`(`stored-request-prompt-profile-m30.ts`),
202
+ * 改写不到的残留行在续跑判据上拒(`http/stored-body-replay.ts` 第四问),到不了这里。
203
+ */
204
+ export declare function promptLeanSpecFragment(body: {
205
+ readonly promptLean?: unknown;
206
+ }): {
207
+ promptLean?: boolean;
208
+ };
179
209
  /** [ref]②(core 5.14.0 `TaskSpec.toolMaterializeStrategy`):deferred 工具激活后的 schema 供给策略。
180
- * 与 {@link promptProfileFromBody} 同姿势的**防御性归一**——提交面的 fail-loud 400 在 HTTP 门,这里
210
+ * 与 {@link promptLeanFromBody} 同姿势的**防御性归一**——提交面的 fail-loud 400 在 HTTP 门,这里
181
211
  * 只负责 resume 重放存量 body 时把不认识的值静默 DROP(回落 core 的 env/缺省链),而不是把它带上 spec。 */
182
212
  export declare function toolMaterializeStrategyFromBody(raw: unknown): "static" | "swap" | undefined;
183
213
  /** [ref]④ — 每键的运营方上限旋钮(env,缺省不设=不封顶)。 */
@@ -25,6 +25,20 @@ export function normalizeResilience(v, operator) {
25
25
  };
26
26
  return Object.keys(out).length > 0 ? out : undefined;
27
27
  }
28
+ export const ATTACHMENT_KEY_KINDS = {
29
+ todoReminder: "boolean",
30
+ todoReminderMode: "mode",
31
+ changedFiles: "changedFiles",
32
+ budgetUsd: "boolean",
33
+ backgroundTasks: "boolean",
34
+ toolsDelta: "boolean",
35
+ agentListing: "boolean",
36
+ skillsListing: "boolean",
37
+ mcpInstructions: "boolean",
38
+ mcpUnavailable: "boolean",
39
+ };
40
+ export const ATTACHMENT_KEYS = Object.keys(ATTACHMENT_KEY_KINDS);
41
+ export const ATTACHMENT_BOOLEAN_KEYS = ATTACHMENT_KEYS.filter((k) => ATTACHMENT_KEY_KINDS[k] === "boolean");
28
42
  export function normalizeAttachments(v) {
29
43
  if (v == null || typeof v !== "object" || Array.isArray(v))
30
44
  return undefined;
@@ -37,17 +51,19 @@ export function normalizeAttachments(v) {
37
51
  changedFiles =
38
52
  typeof mf === "number" && Number.isFinite(mf) && mf >= 1 ? { maxFiles: Math.min(100, Math.floor(mf)) } : true;
39
53
  }
40
- const out = {
41
- ...(o.todoReminder === true ? { todoReminder: true } : {}),
42
- ...(changedFiles !== undefined ? { changedFiles } : {}),
43
- ...(typeof o.backgroundTasks === "boolean" ? { backgroundTasks: o.backgroundTasks } : {}),
44
- ...(o.toolsDelta === true ? { toolsDelta: true } : {}),
45
- ...(o.todoReminderMode === "baseline" || o.todoReminderMode === "off" ? { todoReminderMode: o.todoReminderMode } : {}),
46
- ...(o.budgetUsd === true ? { budgetUsd: true } : {}),
47
- ...(o.mcpInstructions === true ? { mcpInstructions: true } : {}),
48
- ...(typeof o.agentListing === "boolean" ? { agentListing: o.agentListing } : {}),
49
- ...(typeof o.skillsListing === "boolean" ? { skillsListing: o.skillsListing } : {}),
54
+ const parts = {
55
+ todoReminder: o.todoReminder === true ? { todoReminder: true } : {},
56
+ todoReminderMode: o.todoReminderMode === "baseline" || o.todoReminderMode === "off" ? { todoReminderMode: o.todoReminderMode } : {},
57
+ changedFiles: changedFiles !== undefined ? { changedFiles } : {},
58
+ budgetUsd: o.budgetUsd === true ? { budgetUsd: true } : {},
59
+ backgroundTasks: typeof o.backgroundTasks === "boolean" ? { backgroundTasks: o.backgroundTasks } : {},
60
+ toolsDelta: o.toolsDelta === true ? { toolsDelta: true } : {},
61
+ agentListing: typeof o.agentListing === "boolean" ? { agentListing: o.agentListing } : {},
62
+ skillsListing: typeof o.skillsListing === "boolean" ? { skillsListing: o.skillsListing } : {},
63
+ mcpInstructions: o.mcpInstructions === true ? { mcpInstructions: true } : {},
64
+ mcpUnavailable: typeof o.mcpUnavailable === "boolean" ? { mcpUnavailable: o.mcpUnavailable } : {},
50
65
  };
66
+ const out = Object.assign({}, ...ATTACHMENT_KEYS.map((k) => parts[k]));
51
67
  return Object.keys(out).length > 0 ? out : undefined;
52
68
  }
53
69
  export function normalizeResumeAtMode(v, resumeAtResolved) {
@@ -90,6 +106,7 @@ const SKILL_FIELD_SHAPES = {
90
106
  disallowedTools: { required: false, ok: skillToolListOk },
91
107
  files: { required: false, ok: skillFilesOk },
92
108
  baseDir: { required: false, ok: isAbsoluteHostPath },
109
+ mods: { required: false, ok: () => false },
93
110
  };
94
111
  const skillOk = (s) => {
95
112
  if (!plainObject(s))
@@ -301,8 +318,12 @@ export function toolNameListFromBody(raw) {
301
318
  export function allowToolsSpecFragment(raw) {
302
319
  return raw === undefined ? {} : { allowTools: raw };
303
320
  }
304
- export function promptProfileFromBody(raw) {
305
- return raw === "simple" || raw === "classic" ? raw : undefined;
321
+ export function promptLeanFromBody(raw) {
322
+ return typeof raw === "boolean" ? raw : undefined;
323
+ }
324
+ export function promptLeanSpecFragment(body) {
325
+ const lean = promptLeanFromBody(body.promptLean);
326
+ return lean !== undefined ? { promptLean: lean } : {};
306
327
  }
307
328
  export function toolMaterializeStrategyFromBody(raw) {
308
329
  return raw === "static" || raw === "swap" ? raw : undefined;
@@ -0,0 +1,49 @@
1
+ /**
2
+ * 一次性迁移 M30 —— 升级之前停驻的行(`checkpoint_ctx`)里请求体的退役键 `promptProfile`,起服**原地改写**成 `promptLean`。
3
+ * 🔴 M30 · 窗口见 `plugins/one-time-migrations.ts` 的 ONE_TIME_MIGRATIONS 登记表(窗、删法、删后由谁接住只写在那一行)。
4
+ *
5
+ * ## 为什么要它(持久数据面)
6
+ * 引擎 7.56.0 把提示词形收成一个布尔(`TaskSpec.promptLean`),双形词 `promptProfile`(`"simple" | "classic"`)整键退役;新提交带它在键闭集门 400。
7
+ * 7.136.x 及以前停驻的任务,`checkpoint_ctx` 存着的请求体带的是旧键 —— 续跑腿重放它,没有读者 ⇒ `"classic"`(要长形)静默回到模型声明的短形。
8
+ * 持久数据面 = 一次性迁移把旧表示消灭(不是续跑时按日历再读一遍:那样存体从不改,窗内续跑过一次、再停驻、窗关后再续跑,意图照样静默丢)。
9
+ *
10
+ * ## 法(一条映射,与 MIGRATION 写给调用方的同一张)
11
+ * 窗内每次起服扫一遍 `checkpoint_ctx`(两孪生共有的 ctx 行改写店腿 `rewriteCtxRows`,与 M28 同一只;SQL 按原文 CAS、`updated_at_ms` 不动;local 信封的 `updatedAt` 不动),
12
+ * 体里带自有键 `promptProfile` 的行:删掉它;`"classic"` 且体里没有布尔 `promptLean` ⇒ 写 `promptLean: false`(长形的意图);`"simple"`(当年的缺省形)/ 词表外的值 ⇒
13
+ * 只删键;体里已有布尔 `promptLean`(它说了算)⇒ 只删键。体的其余键、行上的读法记号与凭据位原样随行(行改写 = `http/checkpoint-ctx.ts` `rewriteStoredBodyKeys`)。
14
+ * 已改写 / 不带旧键的行零写;读不出的行计数、不动(留给读口的响亮臂)。读数一行 info `checkpoint_ctx_prompt_profile_rewritten`(行数,不带值),不进
15
+ * `OneTimeMigrationReport`(登记行 `reportKeys` 空,与 M28 同形)。窗外不扫。
16
+ *
17
+ * ## 改写不到的行(响亮拒,不是第二种读法)
18
+ * 续跑腿不读旧键(`resolveSpec` 只读布尔 `promptLean`)。存体里仍带 `promptProfile` 的行 —— 窗内从没起过本版的部署,或滚动升级里旧副本在本版起服扫描之后才写下的行 ——
19
+ * 在五个续跑问点的同一只判据上拒(`http/stored-body-replay.ts` 第四问,409 `checkpoint.unsupported_version`);窗内再起一次本版即改写它。
20
+ *
21
+ * ## 为什么不在 `one-time-migrations.ts` 的迁移段里
22
+ * 那一段跑在店层(起服第 3 段),checkpoint 店还没建;本条与 M28 同在起服第 6 段 checkpoint 店建成之后、任何路由装配之前调一次。
23
+ */
24
+ import { type SealedCheckpointCtx } from "./http/checkpoint-ctx.js";
25
+ import { type OneTimeMigrationWindow } from "./plugins/one-time-migrations.js";
26
+ import type { CheckpointCtxRowsRewriter } from "./plugins/checkpoint-store-sql.js";
27
+ /** M30 一次起服的读数(起服 info 行逐键打出;测试按它断言)。`window: "closed"` ⇒ 一行都没读(其余全 0)。`rowsLongFormKept` = 改写成 `promptLean: false` 的行。 */
28
+ export interface PromptProfileRetireM30Report {
29
+ readonly window: "open" | "closed";
30
+ readonly rowsScanned: number;
31
+ readonly rowsRewritten: number;
32
+ readonly rowsLongFormKept: number;
33
+ readonly rowsUnreadable: number;
34
+ readonly rowsTooLarge: number;
35
+ }
36
+ /**
37
+ * 一行存量 ctx 的 M30 改写(纯函数;店腿逐行调):体里没有自有键 `promptProfile`(或体不是对象)⇒ `undefined`(不写);否则交回改写后的落盘形与改动数
38
+ * (写了 `promptLean: false` 记 1,只删键记 0)。导出给两孪生的真库钉(`checkpoint-ctx-credential-seal-db-integration.test.ts`)直接喂店腿。
39
+ */
40
+ export declare function retirePromptProfileRowM30(stored: object): {
41
+ readonly ctx: SealedCheckpointCtx;
42
+ readonly values: number;
43
+ } | undefined;
44
+ /** 跑一次 M30(`today` = UTC 日历日 YYYY-MM-DD;`window` 缺省 = 登记表 M30 那一行 —— 只有测试递别的窗)。窗关 ⇒ 不扫。 */
45
+ export declare function retirePromptProfileM30(store: CheckpointCtxRowsRewriter, opts: {
46
+ readonly today: string;
47
+ readonly window?: Pick<OneTimeMigrationWindow, "removableAfter">;
48
+ }): Promise<PromptProfileRetireM30Report>;
49
+ //# sourceMappingURL=stored-request-prompt-profile-m30.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { rewriteStoredBodyKeys } from "./http/checkpoint-ctx.js";
2
+ import { ONE_TIME_MIGRATIONS, migrationWindowOpen } from "./plugins/one-time-migrations.js";
3
+ const RETIRED_KEY = "promptProfile";
4
+ export function retirePromptProfileRowM30(stored) {
5
+ const body = stored.body;
6
+ if (body === null || typeof body !== "object" || Array.isArray(body) || !Object.hasOwn(body, RETIRED_KEY))
7
+ return undefined;
8
+ const fields = body;
9
+ const keepsLongForm = fields[RETIRED_KEY] === "classic" && typeof fields["promptLean"] !== "boolean";
10
+ return { ctx: rewriteStoredBodyKeys(stored, { drop: [RETIRED_KEY], ...(keepsLongForm ? { set: { promptLean: false } } : {}) }), values: keepsLongForm ? 1 : 0 };
11
+ }
12
+ function m30Window() {
13
+ const row = ONE_TIME_MIGRATIONS.find((w) => w.id === "M30");
14
+ if (row === undefined)
15
+ throw new Error("stored-request-prompt-profile-m30: the one-time migration registry has no M30 row — this migration outlived its registry row; delete it with that row");
16
+ return row;
17
+ }
18
+ export async function retirePromptProfileM30(store, opts) {
19
+ if (!migrationWindowOpen(opts.window ?? m30Window(), opts.today)) {
20
+ return { window: "closed", rowsScanned: 0, rowsRewritten: 0, rowsLongFormKept: 0, rowsUnreadable: 0, rowsTooLarge: 0 };
21
+ }
22
+ const r = await store.rewriteCtxRows((_sessionId, ctx) => retirePromptProfileRowM30(ctx));
23
+ return { window: "open", rowsScanned: r.scanned, rowsRewritten: r.rewritten, rowsLongFormKept: r.valuesRewritten, rowsUnreadable: r.unreadable, rowsTooLarge: r.tooLarge };
24
+ }
25
+ //# sourceMappingURL=stored-request-prompt-profile-m30.js.map
@@ -1,102 +1,73 @@
1
- /**
2
- * [DESIGN-269 车1 §2.2/§2.3 — A2A client seam] — project a caller's per-request A2A peers
3
- * (`TaskRequest.a2aPeers`) into the engine, so a `sema` run can talk to the agents the USER declares,
4
- * not only the ones the deployment's web-admin declares. Point-for-point mirror of `task-mcp.ts`
5
- * (the MCP seam), because the trust question is the same question — and deliberately NOT a copy where
6
- * the two protocols differ (see 「A2A 比 MCP 窄」 below).
7
- *
8
- * 🔒 SECURITY — an A2A peer is a remote **AGENT**, not a data source: it acts on its own side. core ruled
9
- * (2026-08-03, `A2aServerSpec` doc) that every skill such a peer advertises mounts with `egress: true` +
10
- * `effect: "write"`, i.e.接入即引入对外写通道 — it registers the approval gate, is never auto-allowed on a
11
- * no-policy deployment, and its replies reach the model inside an untrusted-data fence. The trust boundary
12
- * is therefore the SAME one the MCP seam draws, for the same reason:
13
- * - SINGLE-USER deployment (`requirePrincipal !== false`… i.e. `!== true`): the requester IS the
14
- * super-admin of their own worker, so the peers they name are their own choice (CC-parity), on EVERY
15
- * execution lane — an A2A call is a plain outbound HTTPS request made by the worker, so the lane where
16
- * the agent's TOOL CALLS run is irrelevant (exactly the fact that decoupled the MCP gate from the lane).
17
- * - MULTI-TENANT deployment (`requirePrincipal === true`): a tenant must NOT make the SHARED worker POST
18
- * to a body-chosen URL (SSRF) carrying body-chosen headers, nor mount write-capable tools from an agent
19
- * the operator never vetted. Gate CLOSED → body peers ignored; the fleet gets peers only through center
20
- * config (`config.a2aPeers`).
21
- * When the gate is closed a sent `a2aPeers` is IGNORED — and SAID (`a2a_injection_ignored` + the
22
- * `capabilities.a2aInjection` advertisement), never silently swallowed.
23
- *
24
- * ⚠️ **A2A 的轴比 MCP 窄,这不是简化而是协议事实**:A2A has no per-skill annotation vocabulary, so there is
25
- * no server-hint leg to fold — `toolAxes` (the CALLER's own judgement) is the ONLY thing that can move an axis
26
- * off the fail-closed default. core says as much on `A2aToolAxis`: `irreversibility:"never"` / `egress:false`
27
- * 「appears ONLY via an explicit caller override」, enforcement ignores the loosening (tighten-only) and the
28
- * ask's risk-axes REPORT face consumes it. So this module carries the caller's overrides through verbatim —
29
- * they are a judgement, not silence — while knowing that core will not let them widen enforcement.
30
- *
31
- * ⚠️ **两票判据的词表在 core 5.36 尚未到货**(分单件 C-1/C-2,core 已认领排 5.37 后首个 A2A 窗):
32
- * `LockedKey` 是 `"mcp"|"toolPolicy"|"compliancePosture"|"retentionPolicy"`,`ComplianceCapability` 是
33
- * `"mcp_servers"|"workflows"|"web_fetch"|"org_memory_mount"` —— 两张表里都还没有 A2A 的位。本模块因此按
34
- * **字符串**判(server config 的 `lockedConfigKeys` 本就是 server 自己的声明面,不经 core 闭集型),
35
- * 判据一到货就换 core 真源、钉子逐字不用改。
36
- * 🔴 **今天这两票在 env 通道上还打不响**,而这是刻意如实记下的、不是被忽略的缺口:`LOCKED_CONFIG_KEYS`
37
- * 经 core 的 `resolveLockedKeys` 校验(未知键拒启)、`COMPLIANCE_ADDITIONAL_DENIES` 经 `COMPLIANCE_CAPABILITIES`
38
- * 校验(同拒),所以运维今天**写不进** `a2a` / `a2a_peers`。而且合规那一票还有第二层:即便有人跳过 boot 期
39
- * 校验把 `a2a_peers` 塞进档位,`resolveComplianceDenies` 对闭集外的词是**抛**(亲测 core 5.36),于是这条
40
- * 请求腿的失败方向是**响亮**(500)而不是安静放行 —— 方向正确,故本模块不加任何兜底。两票的代码先在场是
41
- * 纵深:core 词表到货那一拍这条腿自己就活了,不需要有人记得回来补;反过来(等词表到了再写判据)才是
42
- * 「广告了却拦不住」的那一类缺口。钉在 `test/task-a2a.test.ts`(含到货后该怎么改那一格的原地说明)。
43
- */
44
- import { type A2aServerSpec, type CompliancePosture } from "@sema-agent/core";
1
+ import type { A2aServerSpec } from "@sema-agent/core";
2
+ import { type DeclarationRefusal } from "./request-declaration-refusal.js";
45
3
  import type { StoredToolAxesRereadM19 } from "./stored-request-tool-axes-m19.js";
4
+ import { type PrincipalAxisInput } from "./deployment-shape.js";
46
5
  /** Bound on caller-supplied peers (anti-DoS; a real declaration names a handful of agents). */
47
6
  export declare const MAX_REQUEST_A2A_PEERS = 32;
48
- /** The deployment-facing shape this module reads. `lockedConfigKeys` is deliberately `readonly string[]`
49
- * and not core's `LockedKey[]`: the `a2a` member does not exist in core's union yet (see module header),
50
- * and a predicate that cannot even NAME the key it guards is a predicate that silently guards nothing. */
51
- export interface A2aGateConfig {
52
- requirePrincipal?: boolean;
53
- lockedConfigKeys?: readonly string[];
54
- compliancePosture?: CompliancePosture;
7
+ /**
8
+ * 一条**没有被挂上**的请求腿对端的事实 —— 运维 warn `a2a_injection_dropped` 的 `dropped` 条目(`validateRequestA2a` 的 `dropped` 同形)。与 MCP 面 {@link McpInjectionDrop}(`mcp_injection_dropped`)
9
+ * **同形同键名**:`reason` · `field`,只有名字键各座自己的(MCP `server` ↔ A2A `peer`;键集两向钉在下面的 `_GuardDropKeys*` 上,任一边改名 ⇒ 编译红)。
10
+ * · `peer`:申报名(调用方文本,限长 128,读不出 ⇒ `<malformed>`;撞帽的尾项是一条合并标签 `(+N over cap of 32)`);
11
+ * · `reason`:**判官表**({@link A2A_PEER_KEY_JUDGES})对这一键的原因句 —— 与同一份体上新提交门 400 拒句里的那一句逐字同一句(同一只组句器 `declarationIssueFacts`,不回显值),**只有一臂例外**:
12
+ * 一次性迁移 M19 的重读入参克隆不了(访问器成员 / BigInt / Proxy / 环 / 非纯数据)⇒ 句子带前缀 `declaration not cloneable (<because>) — the one-time migration re-reads the stored declaration as plain JSON data and this one is not; `,**其后**才是判官对原声明的那一句(新提交门不铸这一臂,所以 400 拒句里没有这个前缀);
13
+ * 条目不是对象 = 列表级骨架的头一句(`declarationEntryNotObject`);撞帽 = 撞帽铸点的头一句(`declarationOverCapFacts`,受理口撞帽拒句以同一句开头)。**`reason` 只有一种内容 = 句子**,本座不自铸原因词,
14
+ * 机读词(`over_cap`)留在 400 拒体的 `facts`、不进日志的 `reason`;
15
+ * · `field`:体内坐标 `a2aPeers[i].<键路径>`(条目不是对象 ⇒ `a2aPeers[i]`;撞帽 ⇒ `a2aPeers`),与受理口拒体 `field` 同一个坐标系。
16
+ * 与 MCP 面的差只有两处,都是各自协议的事实:MCP 的 `reason` 是引擎词表的闭集词(`malformed_entry` …),A2A 引擎没有这张词表,`reason` 恒是句子(判官的答案 / 撞帽句);MCP 的 `field` 是条目内键路径,
17
+ * A2A 的是体内绝对坐标(它的拒体 `field` 本就如此)。
18
+ */
19
+ export interface A2aInjectionDrop {
20
+ readonly peer: string;
21
+ readonly reason: string;
22
+ readonly field: string;
55
23
  }
24
+ /** The deployment-facing shape this module reads: the principal axis only (the single-user gate). */
25
+ export type A2aGateConfig = PrincipalAxisInput;
56
26
  /**
57
- * Does THIS deployment honor caller-supplied per-request A2A peers? Three vetoes, ALL of them here (this
58
- * predicate is the single owner — the capability bit and the request leg both read it, so there is exactly
59
- * one place where the answer can be wrong):
60
- * ① the deployment locks the `a2a` key — a locked deployment that advertised `a2aInjection:true` would
61
- * hand every consumer an affordance whose every use 400s (`config.locked_key`); "says yes ⟺ route
62
- * works" breaks on the spot. Same conjunction, same reason, as `mcpInjectionHonored`'s lock veto;
63
- * ② the compliance posture denies `a2a_peers` — advertised-but-refused again;
64
- * ③ multi-tenant (deployment-shape row `multiTenant`) — a tenant cannot point the shared worker at an agent.
65
- *
66
- * ⚠️ **`resolveComplianceDenies` is deliberately NOT wrapped in try/catch** (same ruling as the MCP twin):
67
- * it is fail-loud on a posture outside the closed set, and the posture has already been validated twice
68
- * before reaching here (config parse + boot assembly). If it ever throws here, someone bypassed both doors
69
- * and the LOUD direction (route 500) is the correct one — swallowing it into a boolean would let a
70
- * deployment with a broken posture keep advertising the capability (仓规:安全轴禁静默兜底).
27
+ * Does THIS deployment honor caller-supplied per-request A2A peers? One veto — multi-tenant (deployment-shape row `multiTenant`): a tenant cannot
28
+ * point the shared worker at an agent. The capability bit and the request leg both read this predicate, so there is exactly one place where the answer can be wrong.
71
29
  */
72
30
  export declare function a2aInjectionHonored(config: A2aGateConfig): boolean;
31
+ /**
32
+ * 请求体 `a2aPeers[i]` 的**键闭集**(判序 = 本数组序:名 → 对端地址 → 它的 agent card 地址 → 凭据头 → 身份头 → 技能收窄 → 轴覆写)。两向钉在 core 的 `A2aServerSpec` 上:
33
+ * 型上多一个键而表没跟 ⇒ 编译红(新键会被词表外的键门 400 掉 —— wire 上的静默回归);表里写一个型上没有的词 ⇒ 也红。于是这张表是从 core 的型**派生**出来的数据,而不是谁记得去同步的清单。
34
+ */
35
+ export declare const A2A_PEER_ENTRY_KEYS: readonly ["name", "url", "cardUrl", "headers", "principalHeader", "allowSkills", "toolAxes"];
36
+ /**
37
+ * **请求入口的一次读**(`boot/resolve-spec.ts` 在腿首铸一份,受理门与读器——续跑重放腿只有读器——都吃这一份):`body.a2aPeers` 若是数组,返回同形数组
38
+ * (每个对象条目换成它的 {@link PeerSnapshot};非对象条目原样;长度保真 —— 界外的条数仍是受理门撞帽拒与读器丢弃留声的依据,只快照界内的条目);不是数组(缺席 / `null` / 别的形)原样返回。
39
+ * 为什么在入口铸而不是各调用点各铸:快照按调用点铸,受理口一份、读器一份,嵌入方递来的 getter 对象在两次读之间变形(第一次给干净 URL、第二次给带凭据 URL;`headers` 成员第一次
40
+ * `Bearer accepted`、第二次 `Bearer changed`)就让门判第一份、读器挂第二份 —— 门独有的凭据一问被绕过、鉴权头被换掉。入口铸一次、往下传,「门判的就是读器挂的」才字面成立;
41
+ * 快照是纯数据到叶子(见 {@link PeerSnapshot}),后续任何读者都不再触碰源对象。
42
+ */
43
+ export declare function snapshotRequestA2a(raw: unknown, options: {
44
+ readonly reread: boolean;
45
+ }): unknown;
73
46
  /** 读这条对端的是哪条腿:`fresh` = 新提交;`resume` = 续跑重放升级前存下的请求体(`boot/resolve-spec.ts` 的 `opts.leg` 分流,同一个读法)。 */
74
47
  type A2aRequestLeg = "fresh" | "resume";
75
48
  /**
76
49
  * Shape-check the raw `body.a2aPeers`. `null` → a non-array (caller error; the route may 400). Otherwise the
77
- * valid subset + the names of dropped (malformed/over-cap) entries.
50
+ * valid subset + the dropped (malformed/over-cap) entries as {@link A2aInjectionDrop} facts (peer name · reason · body coordinate).
78
51
  */
79
52
  export declare function validateRequestA2a(raw: unknown): {
80
53
  ok: A2aServerSpec[];
81
- dropped: string[];
54
+ dropped: A2aInjectionDrop[];
82
55
  } | null;
83
- /** fresh 提交腿的 `a2aPeers` URL 门:{@link requestA2aPeerUrlRefusal} 有答案 ⇒ 同步 400(码 / 句 / 机读位原样)。 */
84
- export declare function assertRequestA2aPeerUrls(bodyA2a: unknown): void;
85
56
  /**
86
- * DESIGN-269 §2.4 —— **同步**拒面:部署锁了 `a2a` 而请求仍带 `a2aPeers` ⇒ 400 `config.locked_key`
87
- * (逐字沿用 `assertRequestMcpUnlocked` 的裁定,连错误码都同一个 —— 消费端判的是「某个键被行政锁住了」,
88
- * 不是「哪个键」;码分裂只会让 SDK 多写一条等价分支)。
89
- *
90
- * 判据是「请求**占位**」而不是「请求的值合不合法」:锁是两态的,占了就整拒,不静默丢(静默丢正是把
91
- * 判决变成探针的那一形)。键缺席 / 显式 `null` 都不是占位;**空数组是占位**(调用方确实写了这个键)。
92
- *
93
- * ⚠️ **不看车道**:多租户腿本来就会忽略 body peers(`a2aInjectionHonored` 关),但锁在场时「忽略」是
94
- * 错的失败方向 —— operator 声明了「本部署不收任务自带 A2A peer」,那就该说出来。
57
+ * 请求体 `a2aPeers`「这份声明能不能原样用」的回答者(与 MCP 的 `requestMcpDeclarationRefusal` 同一副骨架、同一个拒形):
58
+ * ① **列表**:在场却不是数组 / 超过 {@link MAX_REQUEST_A2A_PEERS} 条(撞帽机读位一组键)/ 某一条不是对象 ⇒ `400 request.field_invalid`;
59
+ * ② **键名**:条目上词表外的键 ⇒ `400 request.body_shape` + `unknownKeys`;
60
+ * ③ **键值**:逐键问判官表 {@link A2A_PEER_KEY_JUDGES} ⇒ `400 request.field_invalid`,拒句点名 `a2aPeers[i].<键路径>`、peer 名与该键判官的原因句;`url` / `cardUrl` 带凭据时拒体另带机读 `field` / `reason`。
61
+ * 整份拒而不是挂前 32 条 / 丢掉读不出的那条 / 整只忽略:一份被悄悄截短、少了几条或整只没生效的声明,在发送方那里读起来是「生效了」(修前:这些形全部 200 + 运维 warn;其中 `allowSkills`
62
+ * 写成 `allowSkill` 的对端照样挂上远端卡声明的全部技能 —— 收窄意图坏形时退化成放行)。同时这份体整份落盘,界内每一条的 `url` / `cardUrl` 都被判官看过 —— 超过界的列表整份拒,所以扫描有界。
95
63
  *
96
- * ⚠️ 参数类型是 `ReadonlySet<string>`:core 的 `LockedKey` 尚无 `a2a` 成员(见模块头),而
97
- * `ReadonlySet<LockedKey>` 结构上可当 `ReadonlySet<string>` 传入,所以调用点无需任何转换。
64
+ * 纯值域、与租户车道无关(多租户腿整只 `a2aPeers` 本会被忽略,告诉调用方「这样写不行」只多不少)。
65
+ * 只在 fresh 门上判(`boot/resolve-spec.ts` 在 MCP 条目门旁):重放存量 body 的腿不问它 —— 拒会砖死升级前停驻的任务(本仓 `opts.leg` 先例),走宽容读器({@link resolveRequestA2a}:坏条目不挂 +
66
+ * `a2a_injection_dropped` 留声)。A2A serve 腿(`routes/a2a-serve.ts`)铸的体只有 `objective` / `taskId` / `sessionId` / `scenario` 四键,到不了这一座。
98
67
  */
99
- export declare function assertRequestA2aUnlocked(bodyA2a: unknown, lockedKeys: ReadonlySet<string>): void;
68
+ export declare function requestA2aDeclarationRefusal(list: unknown): DeclarationRefusal | undefined;
69
+ /** fresh 提交腿的 `a2aPeers` 门:{@link requestA2aDeclarationRefusal} 有答案 ⇒ 同步 400(码 / 句 / `unknownKeys` / 机读位原样)。 */
70
+ export declare function assertRequestA2aEntries(bodyA2a: unknown): void;
100
71
  /**
101
72
  * Merge GATED per-request peers OVER the deployment baseline (center/config). The baseline WINS on a name
102
73
  * clash — a caller can ADD a peer but can never SHADOW a configured one. This is load-bearing on THIS lane