@sema-agent/server 7.130.0 → 7.132.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 (294) hide show
  1. package/MIGRATION.md +396 -0
  2. package/README.md +13 -6
  3. package/README.zh-CN.md +9 -5
  4. package/USAGE.md +187 -50
  5. package/dist/approval-card.d.ts +3 -1
  6. package/dist/approval-card.js +2 -3
  7. package/dist/audit.d.ts +7 -10
  8. package/dist/audit.js +4 -1
  9. package/dist/auth-bridge.d.ts +4 -0
  10. package/dist/auth-bridge.js +10 -11
  11. package/dist/bench/s1/live-deps.js +2 -0
  12. package/dist/boot/deployment-mods.d.ts +31 -0
  13. package/dist/boot/deployment-mods.js +26 -0
  14. package/dist/boot/execution-env.d.ts +1 -1
  15. package/dist/boot/execution-env.js +19 -6
  16. package/dist/boot/memory-boundary.d.ts +2 -2
  17. package/dist/boot/read-deny-anchor-audit.d.ts +17 -0
  18. package/dist/boot/read-deny-anchor-audit.js +36 -0
  19. package/dist/boot/resolve-spec.d.ts +1 -5
  20. package/dist/boot/resolve-spec.js +56 -61
  21. package/dist/boot/runner-deps.d.ts +19 -8
  22. package/dist/boot/runner-deps.js +14 -2
  23. package/dist/boot/session-faces.d.ts +1 -7
  24. package/dist/boot/stage-02-web-admin-pull.js +9 -1
  25. package/dist/boot/stage-03-store-backend.d.ts +1 -1
  26. package/dist/boot/stage-03-store-backend.js +2 -2
  27. package/dist/boot/stage-04-stores.d.ts +1 -1
  28. package/dist/boot/stage-05-execution-env.d.ts +4 -4
  29. package/dist/boot/stage-05-execution-env.js +7 -10
  30. package/dist/boot/stage-06-runners.d.ts +2 -2
  31. package/dist/boot/stage-06-runners.js +5 -4
  32. package/dist/boot/stage-07-capability-layer.d.ts +2 -2
  33. package/dist/boot/stage-07-capability-layer.js +3 -3
  34. package/dist/boot/stage-08-reapers.d.ts +2 -2
  35. package/dist/boot/stage-09-leader.d.ts +3 -9
  36. package/dist/boot/stage-10-http-server.d.ts +3 -9
  37. package/dist/boot/stage-10-http-server.js +12 -10
  38. package/dist/boot/stores.d.ts +1 -1
  39. package/dist/boot/stores.js +5 -6
  40. package/dist/boot/web-admin.d.ts +0 -3
  41. package/dist/boot/web-admin.js +35 -35
  42. package/dist/brain.js +17 -22
  43. package/dist/budget.js +5 -4
  44. package/dist/caller-text-echo.d.ts +20 -0
  45. package/dist/caller-text-echo.js +24 -0
  46. package/dist/capabilities/brand-identity.d.ts +26 -0
  47. package/dist/capabilities/brand-identity.js +27 -0
  48. package/dist/capabilities/builtin-tools.js +2 -1
  49. package/dist/capabilities/center-plugins.js +1 -1
  50. package/dist/capabilities/center-prompts.d.ts +32 -59
  51. package/dist/capabilities/center-prompts.js +18 -32
  52. package/dist/capabilities/composite-members.d.ts +1 -0
  53. package/dist/capabilities/composite-members.js +1 -0
  54. package/dist/capabilities/engine-capabilities.js +2 -1
  55. package/dist/capabilities/hands-lane.d.ts +9 -6
  56. package/dist/capabilities/hands-lane.js +3 -3
  57. package/dist/capabilities/host-tool-names.d.ts +17 -0
  58. package/dist/capabilities/host-tool-names.js +15 -0
  59. package/dist/capabilities/mcp-probe.d.ts +14 -1
  60. package/dist/capabilities/mcp-probe.js +22 -133
  61. package/dist/capabilities/repo-tools.js +4 -3
  62. package/dist/capabilities/scenarios.d.ts +42 -47
  63. package/dist/capabilities/scenarios.js +19 -35
  64. package/dist/capabilities/select-environment-tool.js +2 -1
  65. package/dist/capabilities/send-user-file-tool.d.ts +0 -1
  66. package/dist/capabilities/send-user-file-tool.js +2 -2
  67. package/dist/capabilities/skills.d.ts +19 -4
  68. package/dist/capabilities/skills.js +30 -10
  69. package/dist/capabilities/tool-defer.js +2 -1
  70. package/dist/config-catalog.js +22 -11
  71. package/dist/config-invariants.js +2 -2
  72. package/dist/config-lkg.d.ts +9 -9
  73. package/dist/config-lkg.js +20 -4
  74. package/dist/config-provider.d.ts +3 -1
  75. package/dist/config-provider.js +14 -6
  76. package/dist/config-types.d.ts +13 -9
  77. package/dist/config.d.ts +2 -2
  78. package/dist/config.js +34 -20
  79. package/dist/device-ws-protocol.d.ts +1 -1
  80. package/dist/device-ws-protocol.js +1 -0
  81. package/dist/elicitation.d.ts +7 -0
  82. package/dist/elicitation.js +20 -5
  83. package/dist/env-name-allowlist-knobs.d.ts +12 -2
  84. package/dist/env-name-allowlist-knobs.js +5 -4
  85. package/dist/exec-bounds.d.ts +15 -3
  86. package/dist/exec-bounds.js +4 -0
  87. package/dist/execution-lane-caps.d.ts +9 -2
  88. package/dist/execution-lane-caps.js +11 -0
  89. package/dist/hooks/classic-stations.d.ts +86 -0
  90. package/dist/hooks/classic-stations.js +27 -0
  91. package/dist/hooks/hook-llm.d.ts +8 -5
  92. package/dist/hooks/hook-llm.js +80 -37
  93. package/dist/hooks/hook-runner.d.ts +273 -75
  94. package/dist/hooks/hook-runner.js +293 -317
  95. package/dist/http/admission.d.ts +8 -2
  96. package/dist/http/admission.js +103 -59
  97. package/dist/http/approval-sweeps.js +59 -18
  98. package/dist/http/checkpoint-ctx.d.ts +36 -18
  99. package/dist/http/checkpoint-ctx.js +14 -10
  100. package/dist/http/claimed-run.d.ts +13 -0
  101. package/dist/http/claimed-run.js +15 -0
  102. package/dist/http/device-placement.js +5 -10
  103. package/dist/http/dispatch.d.ts +0 -4
  104. package/dist/http/dispatch.js +6 -10
  105. package/dist/http/durable-run-leg.d.ts +2 -1
  106. package/dist/http/durable-run-leg.js +5 -3
  107. package/dist/http/health-self-report.d.ts +7 -5
  108. package/dist/http/health-self-report.js +4 -18
  109. package/dist/http/principal-gate.d.ts +23 -6
  110. package/dist/http/principal-gate.js +24 -5
  111. package/dist/http/refusal-body.d.ts +21 -0
  112. package/dist/http/refusal-body.js +4 -0
  113. package/dist/http/request-guards.d.ts +27 -0
  114. package/dist/http/request-guards.js +24 -3
  115. package/dist/http/resume-legs.d.ts +25 -0
  116. package/dist/http/resume-legs.js +48 -26
  117. package/dist/http/routes/approvals-assistant.js +1 -1
  118. package/dist/http/routes/capabilities.js +7 -17
  119. package/dist/http/routes/diagnostics.js +1 -1
  120. package/dist/http/routes/rules.js +2 -2
  121. package/dist/http/routes/runs.js +13 -17
  122. package/dist/http/routes/session-sync.js +4 -2
  123. package/dist/http/routes/sessions.js +23 -11
  124. package/dist/http/routes/shared-memory.js +2 -13
  125. package/dist/http/routes/side-query.js +2 -3
  126. package/dist/http/routes/tasks.js +34 -19
  127. package/dist/http/scenario-read-face.d.ts +14 -0
  128. package/dist/http/scenario-read-face.js +5 -0
  129. package/dist/http/send.d.ts +13 -1
  130. package/dist/http/send.js +12 -1
  131. package/dist/http/server.d.ts +37 -23
  132. package/dist/http/server.js +30 -4
  133. package/dist/http/stored-body-replay.d.ts +10 -3
  134. package/dist/http/stored-body-replay.js +27 -6
  135. package/dist/http/submit-ctx.d.ts +25 -0
  136. package/dist/http/submit-ctx.js +39 -0
  137. package/dist/http/wire-types.d.ts +18 -5
  138. package/dist/index.d.ts +3 -2
  139. package/dist/index.js +3 -2
  140. package/dist/lane-home-probe.d.ts +43 -0
  141. package/dist/lane-home-probe.js +35 -0
  142. package/dist/limit-refusal.d.ts +47 -0
  143. package/dist/limit-refusal.js +12 -0
  144. package/dist/main.js +1 -1
  145. package/dist/mcp-assertion-header.d.ts +3 -11
  146. package/dist/mcp-assertion-header.js +3 -9
  147. package/dist/mcp-tool-faces.d.ts +5 -0
  148. package/dist/mcp-tool-faces.js +5 -1
  149. package/dist/memory-scope.d.ts +1 -1
  150. package/dist/model-entry-refusal.d.ts +1 -7
  151. package/dist/model-provider.d.ts +39 -12
  152. package/dist/model-provider.js +19 -2
  153. package/dist/model-route-endpoint.d.ts +52 -12
  154. package/dist/model-route-endpoint.js +48 -26
  155. package/dist/model-route-gap.d.ts +5 -4
  156. package/dist/model-route-gap.js +1 -1
  157. package/dist/model-select.d.ts +58 -0
  158. package/dist/model-select.js +31 -0
  159. package/dist/namespaced-rule-name.d.ts +7 -4
  160. package/dist/namespaced-rule-name.js +4 -3
  161. package/dist/observability/cost-taxonomy.d.ts +7 -7
  162. package/dist/observability/fail-open.d.ts +53 -12
  163. package/dist/observability/fail-open.js +47 -7
  164. package/dist/observability/metrics.js +3 -1
  165. package/dist/observability/prompt-manifest.d.ts +47 -82
  166. package/dist/observability/prompt-manifest.js +119 -17
  167. package/dist/observability/run-terminal.js +14 -6
  168. package/dist/observability/secret-env-scrub.d.ts +13 -1
  169. package/dist/observability/secret-env-scrub.js +13 -1
  170. package/dist/observability/tool-trace.d.ts +16 -21
  171. package/dist/observability/tool-trace.js +51 -42
  172. package/dist/per-task-image.d.ts +7 -1
  173. package/dist/per-task-image.js +3 -3
  174. package/dist/plain-string-record.d.ts +25 -0
  175. package/dist/plain-string-record.js +32 -0
  176. package/dist/plugins/blob-backend.d.ts +68 -13
  177. package/dist/plugins/blob-backend.js +53 -10
  178. package/dist/plugins/checkpoint-store-sql.d.ts +14 -4
  179. package/dist/plugins/checkpoint-store-sql.js +39 -26
  180. package/dist/plugins/k8s-bg-scripts.d.ts +11 -0
  181. package/dist/plugins/k8s-bg-scripts.js +22 -0
  182. package/dist/plugins/local-checkpoint-store.js +5 -2
  183. package/dist/plugins/local-session-store.js +3 -3
  184. package/dist/plugins/one-time-migrations.d.ts +147 -91
  185. package/dist/plugins/one-time-migrations.js +372 -208
  186. package/dist/plugins/permission-rule-store-sql.d.ts +13 -7
  187. package/dist/plugins/permission-rule-store-sql.js +4 -18
  188. package/dist/plugins/pg-session-storage.d.ts +4 -5
  189. package/dist/plugins/pg-session-storage.js +7 -17
  190. package/dist/plugins/remote-env-adb.d.ts +6 -0
  191. package/dist/plugins/remote-env-adb.js +9 -4
  192. package/dist/plugins/remote-env-device.js +3 -0
  193. package/dist/plugins/remote-env-e2b.d.ts +1 -1
  194. package/dist/plugins/remote-env-e2b.js +21 -9
  195. package/dist/plugins/remote-env-host.d.ts +9 -9
  196. package/dist/plugins/remote-env-host.js +10 -32
  197. package/dist/plugins/remote-env-k8s.d.ts +95 -26
  198. package/dist/plugins/remote-env-k8s.js +265 -90
  199. package/dist/plugins/remote-env-local-docker.d.ts +20 -1
  200. package/dist/plugins/remote-env-local-docker.js +77 -9
  201. package/dist/plugins/remote-env-ssh.d.ts +15 -0
  202. package/dist/plugins/remote-env-ssh.js +109 -3
  203. package/dist/plugins/remote-shell.d.ts +0 -1
  204. package/dist/plugins/remote-shell.js +1 -2
  205. package/dist/plugins/retention-store-sql.js +6 -2
  206. package/dist/plugins/schema-consistency.d.ts +54 -0
  207. package/dist/plugins/schema-consistency.js +52 -0
  208. package/dist/plugins/session-epoch-anchor.d.ts +13 -0
  209. package/dist/plugins/session-epoch-anchor.js +23 -0
  210. package/dist/plugins/shared-memory-store-sql.d.ts +9 -3
  211. package/dist/plugins/shared-memory-store-sql.js +5 -16
  212. package/dist/plugins/sql-driver.d.ts +141 -0
  213. package/dist/plugins/sql-driver.js +115 -1
  214. package/dist/plugins/sql-errors.d.ts +41 -0
  215. package/dist/plugins/sql-errors.js +36 -0
  216. package/dist/plugins/store-backend.js +2 -1
  217. package/dist/plugins/tidb-session-storage.d.ts +7 -11
  218. package/dist/plugins/tidb-session-storage.js +6 -16
  219. package/dist/plugins/tidb-session-store.js +1 -1
  220. package/dist/prompts-domain-validate.d.ts +17 -61
  221. package/dist/prompts-domain-validate.js +9 -119
  222. package/dist/question.d.ts +18 -9
  223. package/dist/question.js +21 -13
  224. package/dist/request-key-closure.d.ts +4 -4
  225. package/dist/request-key-closure.js +18 -13
  226. package/dist/rule-entry-list.d.ts +134 -24
  227. package/dist/rule-entry-list.js +162 -30
  228. package/dist/run-local.d.ts +3 -3
  229. package/dist/run-local.js +26 -25
  230. package/dist/runs.d.ts +48 -2
  231. package/dist/runs.js +61 -2
  232. package/dist/server-secret-env.d.ts +44 -18
  233. package/dist/server-secret-env.js +49 -8
  234. package/dist/session-incarnation.d.ts +15 -5
  235. package/dist/session-incarnation.js +16 -9
  236. package/dist/session-titler.js +12 -2
  237. package/dist/spec-fields.d.ts +34 -18
  238. package/dist/spec-fields.js +46 -53
  239. package/dist/sql-engine-posture.d.ts +29 -4
  240. package/dist/sql-engine-posture.js +36 -1
  241. package/dist/stored-request-hooks-m20.d.ts +23 -0
  242. package/dist/stored-request-hooks-m20.js +124 -0
  243. package/dist/stored-request-tool-axes-m19.d.ts +20 -5
  244. package/dist/stored-request-tool-axes-m19.js +30 -2
  245. package/dist/task-a2a.d.ts +9 -1
  246. package/dist/task-a2a.js +73 -47
  247. package/dist/task-mcp.d.ts +54 -102
  248. package/dist/task-mcp.js +194 -92
  249. package/dist/task-settings.d.ts +47 -25
  250. package/dist/task-settings.js +46 -61
  251. package/dist/text-bidi.d.ts +3 -46
  252. package/dist/text-bidi.js +3 -3
  253. package/dist/tool-approval.d.ts +1 -1
  254. package/dist/trace/core-keyset-guard.d.ts +24 -4
  255. package/dist/trace/engine-notice-wire.d.ts +11 -3
  256. package/dist/trace/engine-notice-wire.js +8 -1
  257. package/dist/trace/ledger-events.d.ts +3 -1
  258. package/dist/trace/ledger-sink.d.ts +29 -0
  259. package/dist/trace/ledger-sink.js +15 -1
  260. package/dist/trace/model-segment.js +1 -1
  261. package/dist/trace/project.d.ts +25 -6
  262. package/dist/trace/project.js +68 -22
  263. package/dist/trace/wire-projection-faces.d.ts +80 -2
  264. package/dist/trace/wire-projection-faces.js +23 -1
  265. package/dist/user-authored-text.d.ts +7 -0
  266. package/dist/user-authored-text.js +3 -0
  267. package/dist/web-admin-client/apply-effective.js +10 -5
  268. package/dist/web-admin-client/candidate-gate.d.ts +6 -6
  269. package/dist/web-admin-client/candidate-gate.js +3 -3
  270. package/dist/web-admin-client/http-client.js +0 -6
  271. package/dist/web-admin-client/read-warnings.d.ts +13 -0
  272. package/dist/web-admin-client/read-warnings.js +10 -0
  273. package/dist/web-admin-client/skills-mcp.d.ts +3 -0
  274. package/dist/web-admin-client/skills-mcp.js +9 -6
  275. package/dist/web-admin-client/types.d.ts +3 -4
  276. package/dist/workspace-cache.d.ts +35 -0
  277. package/dist/workspace-cache.js +36 -0
  278. package/dist/workspace-space.d.ts +3 -2
  279. package/dist/workspace-space.js +2 -0
  280. package/docs/DEVICE-EXECUTOR-PROTOCOL.md +8 -1
  281. package/package.json +4 -4
  282. package/scripts/drain-check-local.mjs +37 -3
  283. package/scripts/drain-check.mysql.sql +30 -2
  284. package/scripts/drain-check.pg.sql +29 -2
  285. package/dist/capabilities/memory-notice.d.ts +0 -138
  286. package/dist/capabilities/memory-notice.js +0 -64
  287. package/dist/capabilities/prompt.d.ts +0 -17
  288. package/dist/capabilities/prompt.js +0 -6
  289. package/dist/mcp-content-origin.d.ts +0 -34
  290. package/dist/mcp-content-origin.js +0 -10
  291. package/dist/tool-axis-words.d.ts +0 -27
  292. package/dist/tool-axis-words.js +0 -9
  293. package/dist/wire-name-bound.d.ts +0 -14
  294. package/dist/wire-name-bound.js +0 -13
@@ -10,6 +10,7 @@ import type { RunStore, ImageIndex, ImageBake, CheckpointStoreFull, ResumeAnchor
10
10
  import type { RuleConsentLane } from "../rules-consent.js";
11
11
  import { type MemorySyncRequest, type MemorySyncResponse } from "../memory-sync.js";
12
12
  import type { TaskAttachmentStore } from "../plugins/task-attachment-store.js";
13
+ import type { SqlBlobCapReading } from "../plugins/blob-backend.js";
13
14
  import type { LeaderEndpoint } from "../leader/endpoint.js";
14
15
  import { type WorkflowAgentRegistry } from "../orchestration/workflow-agent-steer.js";
15
16
  import type { SubagentSteerRegistry } from "../orchestration/subagent-steer.js";
@@ -34,11 +35,10 @@ export { cascadeConfig };
34
35
  import { coarseStatusForState, errorCodeForExit } from "./routes/images.js";
35
36
  export { coarseStatusForState, errorCodeForExit };
36
37
  import { MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills } from "./admission.js";
37
- import { hasServiceAuth } from "./dispatch.js";
38
38
  import { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath } from "./route-table.js";
39
39
  export { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, hasServiceAuth };
40
40
  export { MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills };
41
- import { explicitOperatorOk, isOperator } from "./principal-gate.js";
41
+ import { explicitOperatorOk, isOperator, hasServiceAuth } from "./principal-gate.js";
42
42
  export { explicitOperatorOk, isOperator };
43
43
  /** Per-request authorization context resolved before building the spec (identity, owned session). */
44
44
  export interface RequestAuth {
@@ -58,7 +58,7 @@ export interface RequestAuth {
58
58
  * 平铺形的直接后果 = main.ts 一个上千行的装配字面量,键与键之间没有任何「属于同一件事」的编译期表达,
59
59
  * 键落错家/从未接线只能靠源码钉逐个盯(1.300/1.301/1.304/1.307/1.310 五起真缺陷都是这个病族)。
60
60
  *
61
- * 药:七个**窄**接口 + 顶层必填三件。装配点按组构造(每组一个带类型标注的中间 const ⇒ 受 TS 多余
61
+ * 药:七个**窄**接口 + 顶层必填五件。装配点按组构造(每组一个带类型标注的中间 const ⇒ 受 TS 多余
62
62
  * 属性检查保护),键放错组当场编译红。
63
63
  *
64
64
  * 兼容形(本批**不动消费点**):`ServiceDeps` = 平铺视图 ∩ 组槽。旧的平铺构造(96 个测试文件 +
@@ -66,8 +66,8 @@ export interface RequestAuth {
66
66
  * 入口摊平回平铺视图,server.ts 内的 ~700 处 `deps.x` 消费点原样保留。消费点迁移是后批的事——
67
67
  * 一步到位需要同批改 ~700 处 src + ~800 处 test 键位,与「先立形、后搬家」相比没有额外收益。
68
68
  */
69
- /** createHttpServer 的**必填四件**——引擎、部署配置、请求→TaskSpec 的映射、side-query 执行席。
70
- * 四者恒在场,故留在顶层(不进任何可选组):没有它们 server 根本起不来,包一层可选组只会把编译期
69
+ /** createHttpServer 的**必填五件**——引擎、部署配置、请求→TaskSpec 的映射、side-query 执行席、读口场景门。
70
+ * 五者恒在场,故留在顶层(不进任何可选组):没有它们 server 根本起不来,包一层可选组只会把编译期
71
71
  * 错误推迟到运行期(本仓 E-HIGH-1 病族的成因就是「可选键从未接线、编译期无声」)。 */
72
72
  export interface ServiceCoreDeps {
73
73
  runner: Runner;
@@ -123,6 +123,18 @@ export interface ServiceCoreDeps {
123
123
  * `runnerFor: () => runner` —— 那是一句表态,不是一个回落。
124
124
  */
125
125
  runnerFor: (spec: TaskSpec) => Runner;
126
+ /**
127
+ * 读口的场景名过门 —— `capabilities/scenarios.ts` `createScenarioGate` 铸的**那一只**(与 `resolveSpec` 同一个工厂、同一张场景表、同一份
128
+ * `principalCaps`、同一份部署缺省):凡回答「此主体在此场景能看见哪些 MCP 服务器 / A2A 对端」的口 —— `GET /v1/capabilities/mcp` 的状态面、
129
+ * `GET /v1/sessions/:id/mcp` 与 `…/a2a` 两张会话面板 —— 的场景名都由它给,**点名与缺席都问**:点名 ⇒ 判在册 / allowlist,
130
+ * 拒体(400 `scenario_unknown` 附在册词表 / 400 `scenario_not_allowed` 附 allowlist)与任务提交腿逐字同;缺席 ⇒ 指派链(中心 ruling 胜者,
131
+ * 否则部署缺省),与这位主体 run 时同一读法(指派悬空 ⇒ 503 `state.scenario_assignment_unknown`,同提交腿)。
132
+ * 读面上这只门走**只读腿**(`createScenarioGate(…, "peek")`):问中心裁定时 center 抖动的那一拍,不替这个主体的真提交留下 fail-closed 降级项
133
+ * (提交腿自己是 `"enforce"`)。
134
+ * 🔴 **必填**:读口的场景名只有这一个来源,没有「缺接缝 ⇒ 读部署缺省 / 点名 404」这类第二种读法 —— 漏接是**编译错**(嵌入方自己装配时,工厂与它的型从包根导出:
135
+ * `createScenarioGate` / `ScenarioGate` / `ScenarioGateLeg` / `ScenarioGateSources`)。
136
+ */
137
+ scenarioGate: import("../capabilities/scenarios.js").ScenarioGate;
126
138
  }
127
139
  /** **durable 持久面**:每个键 present ⇔ 对应路由/能力位在场,absent ⇒ 501(诚实缺席),
128
140
  * 绝不静默降级。装配点 = main.ts 的 store backend 开箱段。 */
@@ -563,14 +575,6 @@ export interface ServiceSeamDeps {
563
575
  * per-principal 查询走 caps client 的 executionRuling 同车(零额外 RTT);absent = 无 center(单用户/
564
576
  * dry-run)⇒ 观测面不接线,零行为差。fail-open:观测失败绝不影响 sync 面本身。 */
565
577
  sessionMirrorRuling?: (principal: string | undefined) => Promise<SessionMirrorRuling | undefined>;
566
- /** 请求点名的场景名过门 —— `capabilities/scenarios.ts` `createScenarioGate` 铸的**那一只**(与 `resolveSpec` 同一个工厂、同一张场景表、同一份
567
- * `principalCaps`、同一份部署缺省):`GET /v1/capabilities/mcp?scenario=<名>` 的状态面靠它回答「这个场景名在不在册、这位 principal 放不放行」,
568
- * 拒体(400 `scenario_unknown` 附在册词表 / 400 `scenario_not_allowed` 附 allowlist)因此与任务提交腿逐字同。
569
- * 读面上这只门走**只读腿**(`createScenarioGate(…, "peek")`):问中心裁定时 center 抖动的那一拍,不替这个主体的真提交留下 fail-closed 降级项
570
- * (提交腿自己是 `"enforce"`)。只在请求**点名了**场景时才问(缺席 ⇒ 部署缺省场景,不问门、不多一次中心往返;点名空串也交门答,与提交腿 `scenario: ""` 同码)。
571
- * 本接缝缺席 = 嵌入方的 HTTP 面没有场景表可问:状态面点名场景答 404 `scenario_not_found`,与场景详情读面({@link scenarioDetails} 缺席)同一个答复,
572
- * 不另造空表门、不静默回缺省集。 */
573
- scenarioGate?: import("../capabilities/scenarios.js").ScenarioGate;
574
578
  /** Degenerate-output a/b instrument: on errorCode=output.degenerate, inspect the session's turns to
575
579
  * classify where the salvageable answer was (counter + log). Fire-and-forget; no-op otherwise. */
576
580
  instrumentDegenerate?: (result: TaskResult) => void;
@@ -773,12 +777,18 @@ export interface ServiceDeploymentDeps {
773
777
  * `GET /v1/capabilities` 的 `memoryEngine` 位(窄投影)。缺席 = 这个进程不是由 composition root 装
774
778
  * 起来的(测试夹具形)⇒ 诊断面报 null、能力位取诚实下限 false。 */
775
779
  memoryPosture?: import("../memory-posture.js").MemoryPosture;
776
- /** S-131:SQL 引擎姿态的 **live getter**(`sql-engine-posture.ts` 的单一推导点 —— boot 期借一条池连接
777
- * 触发驱动的连接初始化,读的是 `SET` 之后**回读复核**过的真值)。两个读面共用:
778
- * `GET /v1/diagnostics/wiring` 的 `sqlEngine` 段(operator-only,全量含版本)与 `GET /v1/capabilities`
779
- * 的 `store.sql` 位(窄投影;7.106.0 前是顶层 `sql`,S-866 ①)。getter 而不是快照:池重连后驱动会重新初始化并刷新事实,快照会说谎。
780
- * 缺席 / 返回 null = 本部署没有 SQL 后端(env-only worker、local 文件后端)—— 诚实缺席,不铸空壳。 */
781
- sqlEngineFacts?: () => import("../plugins/sql-driver.js").SqlEngineFacts | null;
780
+ /** S-131:SQL **引擎读口**(`sql-engine-posture.ts` 的单一推导点 —— boot 期借一条池连接触发驱动的连接初始化,交回本池的驱动:
781
+ * `dialect`(SQL 文本轴,恒在)+ 活的 `facts`(`SET` 之后**回读复核**过的真值;池重连后驱动会重新初始化并刷新,快照会说谎)。
782
+ * 读者:`GET /v1/diagnostics/wiring` 的 `sqlEngine` 段(operator-only,全量含版本与两堵墙)与 `GET /v1/capabilities` 的 `store.sql` 位(窄投影;
783
+ * 7.106.0 前是顶层 `sql`,S-866 ①)读 `facts`;提交受理口的 413 把整只读口交给唯一判官 `sql-driver.ts` `sqlWallsOf`(本服务的装配另用同一只读口铸
784
+ * `snapshotBlobSqlCap`,`PUT /sync/blobs` 的前置帽)—— 墙的方言只从这里来(与事实同出一只驱动),不另从店后端读。
785
+ * 两种缺席、两个值:**席缺席** = 本部署没有 SQL 后端(env-only worker、local 文件后端);**`facts` 是 `null`** = 有 SQL 后端、但事实此刻没建立
786
+ * (池上最近一次连接初始化被拒,驱动当场作废了事实)。两者在两个读面上都报缺席(诚实缺席,不铸空壳);墙按方言读后者(MySQL 协议 ⇒ 最保守的假定墙)。
787
+ * 7.132.0 前这一席是 `sqlEngineFacts: () => SqlEngineFacts | null`(只给事实、不给方言);照旧传它 ⇒ `createHttpServer` 起服拒。
788
+ * 🔴 **SQL 后端在场(`backend` 交出了 `mysqlPool()` / `pgPool()`)⇒ 本席必填**,缺席 ⇒ `createHttpServer` 起服拒(席缺席只表示「没有 SQL 后端」,不能是「忘了给」);
789
+ * 本服务自己的装配(`boot/stores.ts` → `stage-10`)按同一个谓词(`sqlPoolsOf`)建立它,恒给。值形也在起服时判(同一只判官 `sqlEngineSeatIssue` 的另一臂):
790
+ * `{ dialect: "tidb" | "pg", facts }`,`facts` 是 `null` 或带 `maxRowBytes` / `maxPacketBytes` / `wallSources` 的引擎事实;只改了键名的 `() => facts` 之类 ⇒ 起服拒。 */
791
+ sqlEngine?: import("../plugins/sql-driver.js").SqlEngineReading;
782
792
  /** S-138:**写保护名表**的姿态(`write-protection.ts` 的 boot 期单一推导点 —— 与递给每只 Runner 的
783
793
  * `writeProtectedPaths` 座同一份 config 决定)。两个读面共用:`GET /v1/diagnostics/wiring` 的
784
794
  * `writeProtection` 段(operator-only,**逐行**表 + 来源 + 被丢的缺省行名)与 `GET /v1/capabilities`
@@ -817,10 +827,14 @@ export interface ServiceDeploymentDeps {
817
827
  /** **数值旋钮**:部署可调的上限/拍距。缺省值写在消费点(`?? 256` 之类),此处只承载覆写。 */
818
828
  export interface ServiceKnobDeps {
819
829
  /** (a)(clay 拍 a+c,2026-07-27)当快照 blob 走 SQL 默认店时(逃生口形/覆写形),该店的 per-blob
820
- * 承载帽——PUT /sync/blobs 面据此**前置 413**(typed `blob_too_large_for_sql`)。不设=不前置(MinIO
821
- * 形无帽)。为什么在 HTTP 面重复店里的检查:店的 never-throw 结果形把一切写失败折成 502,而 502
830
+ * 承载帽的**读口**——PUT /sync/blobs 面每个请求调一次、据此**前置 413**(typed `blob_too_large_for_sql`)。
831
+ * 键缺席=不前置(MinIO 形无帽);读口答 `undefined`=此刻没有墙(pg 形)=不前置。读口而非数字:帽由库报的墙推导,
832
+ * 库调墙、池连接换代后活事实会变,门限必须跟着变(与店写口 `SqlBlobBackend` 读同一份池级事实、同一只函数
833
+ * `sqlBlobCapOf`)。读口答的是**帽 + 它的出处**(`{ capBytes, source }`,`source` ∈ `operator` / `reported` / `assumed`,见 `SqlBlobCapReading`):
834
+ * 413 的句子与机读位 `wallSource` 按出处分三形(运维旋钮 / 库报的墙 / 假定的墙),不把假定或运维的旋钮说成库的上限。
835
+ * 为什么在 HTTP 面重复店里的检查:店的 never-throw 结果形把一切写失败折成 502,而 502
822
836
  * 语义=可重试,对端会对一个永远过不去的 blob 无限重试——413 才是「别再送了」的诚实形。 */
823
- snapshotBlobSqlCapBytes?: number;
837
+ snapshotBlobSqlCap?: () => SqlBlobCapReading | undefined;
824
838
  /** [ref] SSE 连接帽(缺省 256/副本;超限 503+Retry-After=消费方回落 /head 轮询)。 */
825
839
  sessionEventsMaxConnections?: number;
826
840
  /** [ref] SSE 心跳/owner 复核拍距 ms(缺省 25s;测试注入用)。 */
@@ -838,7 +852,7 @@ export interface ServiceDepGroups {
838
852
  deployment?: ServiceDeploymentDeps;
839
853
  knobs?: ServiceKnobDeps;
840
854
  }
841
- /** 平铺视图 = 必填三件 + 其余七组的全可选并集。**派生**自组接口,故与分组形永不漂。 */
855
+ /** 平铺视图 = 必填五件 + 其余七组的全可选并集。**派生**自组接口,故与分组形永不漂。 */
842
856
  export type FlatServiceDeps = ServiceCoreDeps & Partial<ServiceStoreDeps & ServiceCoordinatorDeps & ServiceSeamDeps & ServiceObservabilityDeps & ServiceGovernanceDeps & ServiceDeploymentDeps & ServiceKnobDeps>;
843
857
  /** createHttpServer 的入参:两形皆可(平铺=存量,分组=推荐)。同名键两形都给时,**顶层显式键赢**
844
858
  * (含显式 `undefined`)——一处装配点只该用一形,混用时以肉眼最近的那个为准。 */
@@ -3,6 +3,7 @@ import { outwardPlane } from "../terminal.js";
3
3
  import { redactHead } from "../observability/run-terminal.js";
4
4
  import { validatePendingSteer } from "@sema-agent/core";
5
5
  import {} from "../web-admin-client/facade.js";
6
+ import { describeValueShape } from "@sema-agent/settings-schema";
6
7
  import { HttpError } from "../security.js";
7
8
  import {} from "../memory-sync.js";
8
9
  import {} from "../orchestration/workflow-agent-steer.js";
@@ -17,17 +18,18 @@ import { cascadeConfig } from "./run-meta.js";
17
18
  export { cascadeConfig };
18
19
  import { coarseStatusForState, errorCodeForExit } from "./routes/images.js";
19
20
  export { coarseStatusForState, errorCodeForExit };
20
- import { sendError, sendSessionError, httpErrorCode, msg } from "./send.js";
21
+ import { sendError, sendHttpError, sendSessionError, msg } from "./send.js";
21
22
  import { createRequestGuards } from "./request-guards.js";
23
+ import { sqlEngineSeatIssue } from "../sql-engine-posture.js";
22
24
  import { createAdmission, MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills } from "./admission.js";
23
25
  import { createResumeLegs } from "./resume-legs.js";
24
26
  import * as facts from "../capability-facts.js";
25
- import { createDispatch, hasServiceAuth } from "./dispatch.js";
27
+ import { createDispatch } from "./dispatch.js";
26
28
  import { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, isProbePath } from "./route-table.js";
27
29
  import { createApprovalSweeps } from "./approval-sweeps.js";
28
30
  export { routeLabel, isBillableSubmitPath, isCredentialGatedRewrite, isMethodDispatchedSubmitPath, hasServiceAuth };
29
31
  export { MAX_SKILL_CONTENT_CHARS, MAX_SYSTEM_PROMPT_CHARS, MAX_OUTPUT_SCHEMA_CHARS, validateUserSkills };
30
- import { explicitOperatorOk, isOperator } from "./principal-gate.js";
32
+ import { explicitOperatorOk, isOperator, hasServiceAuth } from "./principal-gate.js";
31
33
  export { explicitOperatorOk, isOperator };
32
34
  class DrainYieldingPreemptBook extends Map {
33
35
  drainingNow;
@@ -57,6 +59,30 @@ export function createHttpServer(rawDeps) {
57
59
  if (typeof deps.runnerFor !== "function") {
58
60
  throw new Error("createHttpServer: the runnerFor seat is required (it picks each task's Runner from its execution lane) — pass the hands-lane selector, or `runnerFor: () => runner` for a single-Runner embedding; refusing to start rather than run every task on the widest Runner");
59
61
  }
62
+ if (deps.snapshotBlobSqlCapBytes !== undefined) {
63
+ throw new Error("createHttpServer: snapshotBlobSqlCapBytes was replaced by snapshotBlobSqlCap in 7.132.0 — pass a reader `() => { capBytes, source } | undefined` (called on every PUT /v1/sessions/:id/sync/blobs/:hash; `source` is \"operator\" for a cap you set yourself, \"reported\" / \"assumed\" for one derived from the database's walls; `undefined` = no cap) — for a fixed cap: `() => ({ capBytes: <bytes>, source: \"operator\" })`; refusing to start rather than run without the blob cap");
64
+ }
65
+ if (deps.snapshotBlobSqlCap !== undefined && typeof deps.snapshotBlobSqlCap !== "function") {
66
+ throw new Error(`createHttpServer: snapshotBlobSqlCap must be a reader \`() => { capBytes, source } | undefined\` (called on every PUT /v1/sessions/:id/sync/blobs/:hash), got ${typeof deps.snapshotBlobSqlCap} — pass the reader (or \`() => undefined\` for no cap), or leave it unset; refusing to start rather than answer every blob upload with a 500`);
67
+ }
68
+ if (deps.sqlEngineFacts !== undefined) {
69
+ throw new Error("createHttpServer: sqlEngineFacts was replaced by sqlEngine in 7.132.0 — pass the SQL pool's engine reading as sqlEngine: `{ dialect: \"tidb\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded, or leave both unset when there is no SQL store; refusing to start rather than run the submit admission without the database's walls");
70
+ }
71
+ {
72
+ const issue = sqlEngineSeatIssue(deps.backend, deps.sqlEngine);
73
+ if (issue !== undefined) {
74
+ switch (issue) {
75
+ case "required":
76
+ throw new Error("createHttpServer: sqlEngine is required when a SQL store backend is wired (the backend hands out a SQL pool) — pass the pool's engine reading as sqlEngine: `{ dialect: \"tidb\" | \"pg\", facts }` where `facts` is read live (a getter) and is null while the pool's connection setup has not succeeded; refusing to start rather than read the database's row and statement limits as absent and admit task bodies the database cannot store");
77
+ case "bad_shape":
78
+ throw new Error(`createHttpServer: sqlEngine must be the SQL pool's engine reading \`{ dialect: "tidb" | "pg", facts }\` where \`facts\` is read live (a getter) and is null while the pool's connection setup has not succeeded, otherwise the engine facts object (maxRowBytes, maxPacketBytes and wallSources included) — got ${typeof deps.sqlEngine === "function" ? "a function (the 7.131.x reader \`() => facts\` goes in as \`{ dialect, get facts() { return f(); } }\`)" : describeValueShape(deps.sqlEngine)}; refusing to start rather than answer every task submission with a 500`);
79
+ default: {
80
+ const unhandled = issue;
81
+ throw new Error(`sqlEngine seat issue without a refusal: ${String(unhandled)}`);
82
+ }
83
+ }
84
+ }
85
+ }
60
86
  const idemCache = new IdempotencyCache();
61
87
  const inflightRuns = new Map();
62
88
  const preemptableRuns = new DrainYieldingPreemptBook(() => deps.drainState?.draining === true);
@@ -121,7 +147,7 @@ export function createHttpServer(rawDeps) {
121
147
  void handle(req, res).catch((err) => {
122
148
  if (err instanceof HttpError) {
123
149
  if (!res.headersSent)
124
- sendError(res, err.status, httpErrorCode(err.status, err.code), err.message, { ...(err.extra ?? {}) });
150
+ sendHttpError(res, err);
125
151
  else
126
152
  res.end();
127
153
  return;
@@ -9,6 +9,7 @@
9
9
  */
10
10
  import type { PermissionMode } from "@sema-agent/core";
11
11
  import { type Autonomy } from "../runtime-governance.js";
12
+ import { type LaneHomeDeployment } from "../execution-lane-caps.js";
12
13
  import { type StoredBodyReplayRefusal } from "./checkpoint-ctx.js";
13
14
  import type { CheckpointCtx } from "./route-ctx.js";
14
15
  /**
@@ -21,8 +22,14 @@ export declare function permissionModeReadingUnstated(ctx: CheckpointCtx, floor:
21
22
  floor: PermissionMode;
22
23
  } | undefined;
23
24
  /**
24
- * 三问一只判据:不能重放 ⇒ 返回拒的那条规则;能 ⇒ `undefined`。顺序:allow 读法记号 → 技能拒侧读成空 → 模式词读法记号(几问同中时答先中的那一问 ——
25
- * 任一问中都不重放,句子只需一句)。`autonomy` = 本部署**此刻**的 `config.autonomy`(活 config:热改即生效);地板由它的唯一属主算,问点不自己算。
25
+ * 预判读的部署配置:`autonomy`(第三问的模式词地板)与执行车道的 home 两位(`~/` 形规则那一问)。`ServiceConfig` 结构上满足,四个问点传 `deps.config` 整份。
26
26
  */
27
- export declare function storedBodyReplayRefusal(ctx: CheckpointCtx, autonomy: Autonomy | undefined): StoredBodyReplayRefusal | undefined;
27
+ export type StoredReplayDeployment = LaneHomeDeployment & {
28
+ readonly autonomy?: Autonomy | undefined;
29
+ };
30
+ /**
31
+ * 三问一只判据:不能重放 ⇒ 返回拒的那条规则;能 ⇒ `undefined`。顺序:allow 读法记号 → 请求设置里的条目表(**与拒点同序**:桶门〔形 / 空串 / 超帽〕→ 工具名清单读成空〔**只问限制方向**:放行方向的存量条目读成空,续跑照旧、只留一行运维 warn〕→ deny / ask 的名字层 + 规则文法)→ 模式词读法记号(几问同中时答先中的那一问 ——
32
+ * 任一问中都不重放,句子只需一句)。`deployment` = 本部署**此刻**的 `config`(活 config:热改即生效):`autonomy` 的地板由它的唯一属主算,`~/` 形规则的 home 由 `executionLaneHomeDir` 算,问点都不自己算。
33
+ */
34
+ export declare function storedBodyReplayRefusal(ctx: CheckpointCtx, deployment: StoredReplayDeployment): StoredBodyReplayRefusal | undefined;
28
35
  //# sourceMappingURL=stored-body-replay.d.ts.map
@@ -1,6 +1,8 @@
1
- import { storedBodyPermissionMode } from "../task-settings.js";
1
+ import { REQUEST_SETTINGS_REFUSAL_PREFIX, rulePolicyBucketsRefusal, settingsPermissionBucketIssue, storedBodyPermissionMode } from "../task-settings.js";
2
2
  import { autonomyModeFloor, entryPermissionMode } from "../runtime-governance.js";
3
- import { skillDenyInertEntryOf } from "../rule-entry-list.js";
3
+ import { inertToolListEntryOf, replayInertEntry } from "../rule-entry-list.js";
4
+ import { executionLaneHomeDir } from "../execution-lane-caps.js";
5
+ import { httpErrorCode } from "./send.js";
4
6
  import { allowListReadingEraOf, allowListReadingUnstated, permissionModeReadingStated } from "./checkpoint-ctx.js";
5
7
  export function permissionModeReadingUnstated(ctx, floor) {
6
8
  if (floor === undefined || permissionModeReadingStated(ctx))
@@ -8,14 +10,33 @@ export function permissionModeReadingUnstated(ctx, floor) {
8
10
  const stored = storedBodyPermissionMode(ctx.body);
9
11
  return entryPermissionMode(stored, floor).effective === stored ? undefined : { stored, floor };
10
12
  }
11
- export function storedBodyReplayRefusal(ctx, autonomy) {
13
+ const BUCKET_GATE_CODE = "request.field_invalid";
14
+ function storedPermissions(body) {
15
+ const permissions = body?.settings?.permissions;
16
+ return permissions !== null && typeof permissions === "object" && !Array.isArray(permissions) ? permissions : undefined;
17
+ }
18
+ function storedPermissionBucketRefusal(body) {
19
+ const issue = settingsPermissionBucketIssue(storedPermissions(body));
20
+ if (issue === null)
21
+ return undefined;
22
+ return replayInertEntry(issue.fields.field, issue.fields.field === "settings.permissions.allow" ? "allow" : "deny", BUCKET_GATE_CODE, issue.message, { ...issue.fields });
23
+ }
24
+ function storedRulePolicyRefusal(body, deployment) {
25
+ const permissions = storedPermissions(body);
26
+ if (permissions === undefined)
27
+ return undefined;
28
+ const home = executionLaneHomeDir(deployment);
29
+ const refused = rulePolicyBucketsRefusal({ ...(Array.isArray(permissions["ask"]) ? { ask: permissions["ask"] } : {}), ...(Array.isArray(permissions["deny"]) ? { deny: permissions["deny"] } : {}) }, home !== undefined ? { home } : {});
30
+ return refused === undefined ? undefined : replayInertEntry(`settings.permissions.${refused.bucket}`, "deny", httpErrorCode(422), `${REQUEST_SETTINGS_REFUSAL_PREFIX}${refused.message}`);
31
+ }
32
+ export function storedBodyReplayRefusal(ctx, deployment) {
12
33
  const writer = ctx.writerVersion !== undefined ? { writerVersion: ctx.writerVersion } : {};
13
34
  if (allowListReadingUnstated(ctx))
14
35
  return { kind: "allow_list_reading", era: allowListReadingEraOf(ctx), ...writer };
15
- const entry = skillDenyInertEntryOf(ctx.body);
36
+ const entry = storedPermissionBucketRefusal(ctx.body) ?? inertToolListEntryOf(ctx.body, ["deny"]) ?? storedRulePolicyRefusal(ctx.body, deployment);
16
37
  if (entry !== undefined)
17
- return { kind: "skill_deny_inert", entry };
18
- const mode = permissionModeReadingUnstated(ctx, autonomyModeFloor(autonomy));
38
+ return { kind: "inert_tool_list", entry };
39
+ const mode = permissionModeReadingUnstated(ctx, autonomyModeFloor(deployment.autonomy));
19
40
  if (mode !== undefined)
20
41
  return { kind: "permission_mode_reading", ...mode, ...writer };
21
42
  return undefined;
@@ -0,0 +1,25 @@
1
+ import type { RunStore } from "../plugins/store-backend.js";
2
+ import type { Logger } from "../observability/logger.js";
3
+ import type { Metrics } from "../observability/metrics.js";
4
+ import { buildCheckpointCtx } from "./checkpoint-ctx.js";
5
+ import { type RefusalBody } from "./refusal-body.js";
6
+ /** 写不进的那一种可答复的结局(各腿把它交回自己的出口:同步 / durable 腿直接回,活流腿编码成终帧)。 */
7
+ export interface SubmitCtxRefusal {
8
+ readonly status: 413;
9
+ readonly body: RefusalBody;
10
+ }
11
+ /**
12
+ * 写这一笔(行体经续跑输入的唯一构造口 `buildCheckpointCtx` 铸 —— 新的持久化写都经它,读法记号随之盖上);写不进 ⇒ 撤掉
13
+ * `claim` 指的那条刚认领的 run(无 run 店的部署没有认领 ⇒ `undefined`),再按成因答复(见文件头)。
14
+ * 返回 `undefined` = 写进了,腿照常起跑。
15
+ */
16
+ export declare function persistSubmitCtx(store: {
17
+ putCtx(sessionId: string, ctx: object): Promise<void>;
18
+ }, deps: {
19
+ readonly logger?: Logger | undefined;
20
+ readonly metrics?: Metrics | undefined;
21
+ }, claim: {
22
+ readonly runStore: RunStore;
23
+ readonly taskId: string;
24
+ } | undefined, sessionId: string, fields: Parameters<typeof buildCheckpointCtx>[0]): Promise<SubmitCtxRefusal | undefined>;
25
+ //# sourceMappingURL=submit-ctx.d.ts.map
@@ -0,0 +1,39 @@
1
+ import { StoreRowTooLargeError } from "../plugins/sql-errors.js";
2
+ import { releaseClaimedRun } from "./claimed-run.js";
3
+ import { buildCheckpointCtx } from "./checkpoint-ctx.js";
4
+ import { refusalBody } from "./refusal-body.js";
5
+ function rowTooLargeRefusal(tooLarge) {
6
+ switch (tooLarge.wall) {
7
+ case "row":
8
+ return { status: 413, body: refusalBody({ errorCode: "request.payload_too_large", message: `the database refused to store this task: it is larger than the database keeps in one row (${tooLarge.dbMessage}) — nothing was run; shrink the inline images / userAttachments, or ask the operator to raise the database's single-row limit (TiDB performance.txn-entry-size-limit)` }) };
9
+ case "statement":
10
+ return { status: 413, body: refusalBody({ errorCode: "request.payload_too_large", message: `the database refused to store this task: it is larger than the database accepts in one statement (${tooLarge.dbMessage}) — nothing was run; shrink the inline images / userAttachments, or ask the operator to raise the database's max_allowed_packet` }) };
11
+ case "value":
12
+ return { status: 413, body: refusalBody({ errorCode: "request.payload_too_large", message: `the database refused to store this task: it is larger than PostgreSQL holds in one value (${tooLarge.dbMessage}) — nothing was run; shrink the inline images / userAttachments` }) };
13
+ default: {
14
+ const unhandled = tooLarge.wall;
15
+ throw new Error(`row-too-large refusal without an HTTP answer: ${String(unhandled)}`);
16
+ }
17
+ }
18
+ }
19
+ export async function persistSubmitCtx(store, deps, claim, sessionId, fields) {
20
+ try {
21
+ await store.putCtx(sessionId, buildCheckpointCtx(fields));
22
+ return undefined;
23
+ }
24
+ catch (err) {
25
+ const tooLarge = err instanceof StoreRowTooLargeError ? err : undefined;
26
+ if (claim !== undefined) {
27
+ const why = tooLarge !== undefined ? tooLarge.message : `the run's resume inputs could not be stored: ${err instanceof Error ? err.message : String(err)}`;
28
+ await releaseClaimedRun(claim.runStore, claim.taskId, why, (releaseErr, step) => {
29
+ deps.logger?.warn("submit_ctx_run_release_failed", { taskId: claim.taskId, sessionId, step, err: releaseErr instanceof Error ? releaseErr.message : String(releaseErr) });
30
+ deps.metrics?.inc("submit_ctx_run_release_failed_total", { step });
31
+ });
32
+ }
33
+ if (tooLarge === undefined)
34
+ throw err;
35
+ deps.logger?.warn("submit_ctx_row_too_large", { sessionId, taskId: claim?.taskId, wall: tooLarge.wall, db: tooLarge.dbMessage });
36
+ return rowTooLargeRefusal(tooLarge);
37
+ }
38
+ }
39
+ //# sourceMappingURL=submit-ctx.js.map
@@ -33,6 +33,12 @@ export interface TaskRequestBody {
33
33
  } | {
34
34
  url: string;
35
35
  }>;
36
+ /** 请求层用户附件(引擎 `TaskSpec.userAttachments`,至多 20 条):挂在**这次提交的目标**上,原样交给引擎 —— 每条以引擎铸的消息紧随目标送到模型,
37
+ * 交付结局在 `human_input{carrier:"objective"}.attachments` 报一次。条目形 = 引擎的 `UserAttachment`(`{ path, lines? }` 读本次 run 的工作区 /
38
+ * `{ name, text, startLine? }` / `{ name, image: { data, mimeType } }` 宿主持有的字节)。**形判属主 = 引擎**:本服务不另判,坏形 / 超 Read 上限的
39
+ * text / 过不了图片准入 / 无工作区的 path 由引擎在第一次模型调用之前拒 `config.user_attachment_invalid`(同步腿 400)。只随目标走:送话口不收
40
+ * (400 `request.body_shape`,键落 `unsupportedKeys`),续跑 / 投递腿的重建不带它(`http/resume-legs.ts` 的一次性键表)。能力位 `userAttachments`。 */
41
+ userAttachments?: TaskSpec["userAttachments"];
36
42
  /** D-1 通用文件上传:预上传附件的句柄数组(POST /v1/attachments 的 `id`)。提交时绑定到会话并在
37
43
  * 执行环境工作目录 `attachments/` 下物化;objective 尾部追加告知(名字/mime/尺寸,内容不进流)。
38
44
  * 上限 16/task;未知或他人 id → 400(fresh 腿)。⚠️ 名为 `attachmentIds` 而非 `attachments`——
@@ -308,12 +314,15 @@ export interface TaskRequestBody {
308
314
  * 坏形不挂键。不投递技能正文(正文照旧由 `Skill` 工具 / 调用方负责)。 */
309
315
  userInvokedSkills?: string[];
310
316
  /** [ref]② (core 1.314 工具面控制批): roster 真卸载清单(schema 不上 wire,manifest 收窄)。wire 工具名;
311
- * tighten-only(core 继承不变量 union 进子 spawn)。数组-of-string fail-loud at submit。 */
317
+ * tighten-only(core 继承不变量 union 进子 spawn)。数组-of-string fail-loud at submit。
318
+ * 读成空的条目(退役拼法 `bash`、大小写孪生 `BASH`、任何工具名都不可能有的拼法、`*`)7.131.0 起受理口 400 `config.tool_face_control` 并点名现名
319
+ * (拒侧读成空 = 放行,不照跑);读得出的名字与真未知名(拼写合法、没有近似也没有退役对应)照收。 */
312
320
  excludeTools?: string[];
313
321
  /** S-1448(core 7.49.0 #1623,[ref]):引擎的**可用性选择器** —— 这一 run 只用列出的工具(wire 名、别名、`Tool(content)` 整只、
314
322
  * `mcp__srv` / `mcp__srv__*` / 工具段通配;`"*"` = 本层不设名单;`[]` = 什么都不给)。宿主**原样透传**进 `TaskSpec.allowTools`:
315
- * 不算补集、不过滤、不与 `settings.permissions.allow`(免问)混词;没有任何工具答应的名字照跑(原样保留,今天什么都不准,之后挂上同名工具即生效;引擎告知运维一次),
316
- * 任何工具名都不可能有的拼法由引擎开跑前拒(`config.tool_face_control`,同步腿 400)。
323
+ * 不算补集、不过滤、不与 `settings.permissions.allow`(免问)混词;真未知名(拼写合法、没有近似也没有退役对应:懒挂载的合法形)照跑(原样保留,今天什么都不准,之后挂上同名工具即生效;引擎告知运维一次),
324
+ * 任何工具名都不可能有的拼法由引擎开跑前拒(`config.tool_face_control`,同步腿 400);7.131.0 起受理口另拒近似名(大小写孪生 `BASH`:想放的什么也没放 = 静默收窄,句子点名现名);
325
+ * 放行侧的内容形(`Agent(Explore)`)、文法读不出与没有后继的退役名(`MultiEdit`)照旧受理、交引擎既有通告;有后继的退役名(`bash` · `Task`)引擎开跑前拒 `config.tool_face_control`(core 7.52.0 起,同步腿 400)。
317
326
  * `excludeTools` 是同一只运算的减项(deny 赢)。值形:字符串数组(受理门 400 `request.field_invalid`,与 `excludeTools` 同一只门);
318
327
  * 装着的引擎不认该座 ⇒ 400 `request.field_invalid` 点名所需引擎版本(不静默丢)。无租户门(收窄)。 */
319
328
  allowTools?: string[];
@@ -501,15 +510,19 @@ export interface TaskRequestBody {
501
510
  * worker, not the exec env); IGNORED on multi-tenant deployments (can't make the shared worker run an arbitrary
502
511
  * command). Validated + gated downstream; the center/config baseline wins on a name clash.
503
512
  *
513
+ * 每个受理键一条律:新提交(fresh)腿上,条目的任一受理键(`name` / `transport` 及其子键 / `allowTools` / `toolAxes` / `toolFaces` / `contentOrigin` / `elicitation` / `source`)
514
+ * 在场却判不出形 ⇒ 同步 400 `request.field_invalid`,拒句点名 `mcpServers[i].<键路径>`、server 名与该键判官的原因句(不回显值),整份请求不收;键缺席恒合法。
515
+ * 耐久 resume 重放存量 body 的腿不拒(会砖死已 park 任务):坏硬键整条 server 不进 + 运维 warn,坏软键丢键、server 照挂。
516
+ *
504
517
  * [ref](core 5.60.0):条目上可选的 `contentOrigin`(`"local"|"execution"|"external"`)= **内容
505
518
  * 出处声明**,只影响记忆写治理(会话污染标记),对审批门/策略/角色表零作用。缺席 = pre-378 逐字节
506
519
  * 现行为(判 external)。🔴 **新提交(fresh)腿上,词表外的值 ⇒ 同步 400 `request.field_invalid`** ——
507
520
  * 静默丢会把一次信任边界声明变成探针。⚠️ **耐久 resume 腿上不拒**:那条腿重放的是存量 body,4xx 会把
508
521
  * 一条 parked 任务永久砖死(折成 `409 resume_blocked_by_policy`),所以坏值在那里**降级**为「键缺席」+
509
- * 一条 `mcp_content_class_dropped` warn(本仓三处 `opts.leg` 先例的同款姿势)。两条腿上 server 本体都
522
+ * 一条 `mcp_content_class_dropped` warn(本仓三处 `opts.leg` 先例的同款姿势)。重放腿上 server 本体
510
523
  * 保留 —— 丢的只是声明。core 把这个键定性为**部署面**的键,本仓对它的 reject-or-strip 义务由既有的单用户闸
511
524
  * **结构性**兑现:多租户腿整只 `mcpServers` 被忽略 ⇒ 租户够不着;单用户腿 = core 明文豁免的超管面
512
- * (完整论证见 `task-mcp.ts` 的 `assertRequestMcpContentOrigin` 顶注)。部署面的正门是 center 下发的
525
+ * (完整论证见 `task-mcp.ts` 的 `assertRequestMcpEntries` 顶注)。部署面的正门是 center 下发的
513
526
  * `CenterMcpServer.contentOrigin`。
514
527
  *
515
528
  * S-1515:`transport.kind:"http"` 的条目可选 `assertionHeader`(托管连接器断言头的**头名**,契约包 settings-schema ≥12.2.0 同键)。
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { composeExecutionLane, assertExecutionLaneInvariants, type ExecutionLane
3
3
  export { createBrain } from "./brain.js";
4
4
  export { createSessionStore } from "./plugins/session-store.js";
5
5
  export { createStoreBackend, type StoreBackend, type SessionCaptureRecordSource } from "./plugins/store-backend.js";
6
- export { RetiredSchemaPresentError } from "./plugins/one-time-migrations.js";
6
+ export { RetiredSchemaPresentError } from "./plugins/schema-consistency.js";
7
7
  export { CachingSessionStore, type CachingOptions } from "./plugins/caching-session-store.js";
8
8
  export type { RunRecord, RunEvent } from "./plugins/store-contracts.js";
9
9
  export { runInBackground } from "./runs.js";
@@ -17,7 +17,7 @@ export { RateLimiter, type RateDecision } from "./observability/rate-limit.js";
17
17
  export { GiteaClient, GitHubClient, createRepoClient, GIT_API_KINDS, isGitApiKind, repoToolsFor, parseRepo, type GitApiKind, type RepoCoords, type RepoReadClient } from "./capabilities/repo-tools.js";
18
18
  export { nowTool } from "./capabilities/builtin-tools.js";
19
19
  export { loadSkills, skillsForScenario, type LoadedSkill } from "./capabilities/skills.js";
20
- export { buildScenarios, selectScenario, type Scenario, type ScenarioBundle, type ScenarioContext, type ScenarioDeps, type ScenarioRequest, } from "./capabilities/scenarios.js";
20
+ export { buildScenarios, selectScenario, createScenarioGate, type Scenario, type ScenarioBundle, type ScenarioContext, type ScenarioDeps, type ScenarioGate, type ScenarioGateLeg, type ScenarioGateSources, type ScenarioRequest, } from "./capabilities/scenarios.js";
21
21
  export { createTaskListLane, taskListKeyFor, MAX_TASK_LIST_SESSIONS, type TaskListLane, type TaskListLaneBackend, type TaskListLaneOpts } from "./boot/task-list-lane.js";
22
22
  export { ensureTiDBTaskListSchema, ensurePgTaskListSchema } from "./plugins/task-list-store-sql.js";
23
23
  export { createAuthorizer, principalFrom, HttpError, type AuthContext, type OwnerAwareSessionStore, } from "./security.js";
@@ -30,5 +30,6 @@ export { isModelKeyPoison, ModelKeyPoisonedError, type ModelKeyPoison, type Mode
30
30
  export { CATALOG_ENTRY_HEADER_LANES, CATALOG_ENTRY_HEADER_NAMES, type CatalogEntryHeaderName } from "./model-entry-headers.js";
31
31
  export { judgeModelRouteGap, type ModelRouteGapReading, type ModelRouteGapOptions } from "./model-route-gap.js";
32
32
  export type { ModelRouteGap } from "./model-route-endpoint.js";
33
+ export { judgeServedModelRoute, type ServedModelRouteView, type ServedModelRouteOptions, type ModelRouteEndpointVerdict } from "./model-route-endpoint.js";
33
34
  export type { UserInputLedgerStore, UserInputAcceptance, NewUserInputAcceptance, OpenScanCursor, OpenScanPage, SettleHow, WriterGoneEvidence } from "./user-input-ledger.js";
34
35
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ export { composeExecutionLane, assertExecutionLaneInvariants } from "./boot/exec
3
3
  export { createBrain } from "./brain.js";
4
4
  export { createSessionStore } from "./plugins/session-store.js";
5
5
  export { createStoreBackend } from "./plugins/store-backend.js";
6
- export { RetiredSchemaPresentError } from "./plugins/one-time-migrations.js";
6
+ export { RetiredSchemaPresentError } from "./plugins/schema-consistency.js";
7
7
  export { CachingSessionStore } from "./plugins/caching-session-store.js";
8
8
  export { runInBackground } from "./runs.js";
9
9
  export { createHardenedVmRunner, runInHardenedVm } from "./orchestration/hardened-vm-runner.js";
@@ -15,7 +15,7 @@ export { RateLimiter } from "./observability/rate-limit.js";
15
15
  export { GiteaClient, GitHubClient, createRepoClient, GIT_API_KINDS, isGitApiKind, repoToolsFor, parseRepo } from "./capabilities/repo-tools.js";
16
16
  export { nowTool } from "./capabilities/builtin-tools.js";
17
17
  export { loadSkills, skillsForScenario } from "./capabilities/skills.js";
18
- export { buildScenarios, selectScenario, } from "./capabilities/scenarios.js";
18
+ export { buildScenarios, selectScenario, createScenarioGate, } from "./capabilities/scenarios.js";
19
19
  export { createTaskListLane, taskListKeyFor, MAX_TASK_LIST_SESSIONS } from "./boot/task-list-lane.js";
20
20
  export { ensureTiDBTaskListSchema, ensurePgTaskListSchema } from "./plugins/task-list-store-sql.js";
21
21
  export { createAuthorizer, principalFrom, HttpError, } from "./security.js";
@@ -26,4 +26,5 @@ export { createKeyResolver, resolveModelApiKey } from "./key-resolver.js";
26
26
  export { isModelKeyPoison, ModelKeyPoisonedError } from "./key-resolver.js";
27
27
  export { CATALOG_ENTRY_HEADER_LANES, CATALOG_ENTRY_HEADER_NAMES } from "./model-entry-headers.js";
28
28
  export { judgeModelRouteGap } from "./model-route-gap.js";
29
+ export { judgeServedModelRoute } from "./model-route-endpoint.js";
29
30
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,43 @@
1
+ /**
2
+ * 执行环境的家目录:**声明 × 实测**的唯一判官(纯叶:零值依赖)。
3
+ *
4
+ * ## 病
5
+ * `REMOTE_EXEC_HOME_DIR` 是运维对「执行环境以哪个用户的家目录运行」的声明,它是 `~/` 形权限规则的基、引擎家锚拒读行(`~/.ssh` / `~/.npmrc` …)
6
+ * 的落点(`execution-lane-caps.ts` `executionLaneHomeDir` 一只属主,四个消费面同读)。k8s / local-docker / ssh 三条车道的家目录是镜像 / 目标机
7
+ * 登录用户的属性,boot 期不可知 —— 声明了就照单全收。声明 `/home/y` 而车道真实家目录是 `/home/x` 时,`Edit(~/.ssh/**)` 守的是 `/home/y`,
8
+ * `/home/x/.ssh` 照读照写,运维与用户零告警:限制写了不生效且无人知。
9
+ *
10
+ * ## 律(一句)
11
+ * 家目录只有一只真源:声明在场、车道能问的,**开环境那一拍问一次**(与命令同一条 shell、同一份 env:`printf %s "$HOME"`),两者不一致 ⇒
12
+ * 这只执行环境不开(拒句点名两值与两条改法),环境答了的判定记在环境上(同一镜像 / 同一目标机再问也是同一个答案,不重试成风暴);问不出答案同样不开
13
+ * (证不了声明 = 不拿一个没证过的目录去守),但不记 —— 与任何一次建连失败同,下一次重问。车道问不了的(adb / device)声明照单全收 —— 那是声明唯一的用处。
14
+ * 没声明的车道不问:规则基与 422 门在下单那一刻就要家目录,而那一刻执行环境还没开(把实测值接进规则基要引擎的座,见收车档)。
15
+ */
16
+ /** 探针答案的行首标记:登录脚本 / profile 往 stdout 打的横幅不会被读成家目录 —— 只认带这个标记的那一行(取最后一行)。 */
17
+ export declare const LANE_HOME_PROBE_MARKER = "sema-lane-home=";
18
+ /**
19
+ * 执行环境里问家目录的那一句 —— 经车道自己的命令通道跑(同一条 shell、同一份 env),答的就是命令看到的 `$HOME`。
20
+ * 先换一行再打标记行:横幅没以换行收尾时,标记行照样从行首开始。
21
+ */
22
+ export declare const LANE_HOME_PROBE_COMMAND = "printf '\\nsema-lane-home=%s\\n' \"$HOME\"";
23
+ /** 一次问家目录的读数:问到了(stdout 原文)/ 没问到(原因)。 */
24
+ export type LaneHomeProbe = {
25
+ readonly ok: true;
26
+ readonly stdout: string;
27
+ } | {
28
+ readonly ok: false;
29
+ readonly reason: string;
30
+ };
31
+ /**
32
+ * 判定:`undefined` = 一致,照开;否则这只环境不开 —— `refusal` 是拒句,`answered` = 环境**答了**它的家目录(不一致 / 不是绝对路径;同一镜像 / 同一登录用户
33
+ * 再问也是同一个答案 ⇒ 调用方记在环境上),`false` = 没答上(探针失败 / 超时 / 非零退出 / 输出里没有标记行 ⇒ 这一次不开、不记、下一次重问)。
34
+ */
35
+ export type LaneHomeVerdict = {
36
+ readonly refusal: string;
37
+ readonly answered: boolean;
38
+ } | undefined;
39
+ /**
40
+ * 声明 × 实测的唯一判官。`lane` 只进句子。拒句三形:实测与声明不一致 / 实测不是绝对路径(含空)/ 没问到。每一形都点名声明值与改法,不回显任何别的东西。
41
+ */
42
+ export declare function judgeLaneHome(lane: string, declared: string, probe: LaneHomeProbe): LaneHomeVerdict;
43
+ //# sourceMappingURL=lane-home-probe.d.ts.map
@@ -0,0 +1,35 @@
1
+ export const LANE_HOME_PROBE_MARKER = "sema-lane-home=";
2
+ export const LANE_HOME_PROBE_COMMAND = `printf '\\n${LANE_HOME_PROBE_MARKER}%s\\n' "$HOME"`;
3
+ const SHOWN_MAX = 256;
4
+ const shown = (raw) => JSON.stringify(raw.length > SHOWN_MAX ? `${raw.slice(0, SHOWN_MAX)}…` : raw);
5
+ const comparable = (p) => (p.length > 1 ? p.replace(/\/+$/, "") : p);
6
+ function markedHome(stdout) {
7
+ const lines = stdout.split("\n").filter((l) => l.startsWith(LANE_HOME_PROBE_MARKER));
8
+ const last = lines[lines.length - 1];
9
+ return last === undefined ? undefined : last.slice(LANE_HOME_PROBE_MARKER.length).replace(/\r$/, "");
10
+ }
11
+ export function judgeLaneHome(lane, declared, probe) {
12
+ const head = `REMOTE_EXEC_HOME_DIR=${shown(declared)} is the home "~/" permission rules and the engine's home-anchored read-deny rows are placed under on the ${lane} execution lane`;
13
+ const measured = probe.ok ? markedHome(probe.stdout) : undefined;
14
+ if (measured === undefined) {
15
+ const reason = probe.ok ? "the probe printed no home line" : probe.reason;
16
+ return {
17
+ refusal: `${head}, but the home of this execution environment could not be read (${reason}) — the declaration cannot be confirmed, so this environment is not started. Fix the lane, or unset REMOTE_EXEC_HOME_DIR (home-relative rules are then refused at submission instead).`,
18
+ answered: false,
19
+ };
20
+ }
21
+ if (!measured.startsWith("/")) {
22
+ return {
23
+ refusal: `${head}, but this execution environment reports HOME=${shown(measured)}, not an absolute path — the declaration cannot be confirmed, so this environment is not started. Give the environment's user a home (HOME), or unset REMOTE_EXEC_HOME_DIR.`,
24
+ answered: true,
25
+ };
26
+ }
27
+ if (comparable(measured) === comparable(declared))
28
+ return undefined;
29
+ return {
30
+ refusal: `${head}, but its commands run with HOME=${shown(measured)} — rules would guard ${shown(declared)} while ${shown(measured)} stays readable and writable, ` +
31
+ `so this environment is not started. Set REMOTE_EXEC_HOME_DIR to ${shown(measured)}, or run the environment as the user whose home is ${shown(declared)}.`,
32
+ answered: true,
33
+ };
34
+ }
35
+ //# sourceMappingURL=lane-home-probe.js.map
@@ -0,0 +1,47 @@
1
+ /**
2
+ * **帽的拒**(一张表条数太多 / 一段文字太长)在本仓受理口的一只写法:句子的头一句 + 机读位,一处铸。
3
+ *
4
+ * 律:请求体上任何一处撞了帽,拒体带同一组机读位 ——
5
+ * · `field` = 撞帽的那一处在请求体里的坐标(`skills[1].allowedTools`、`agents[0].denyTools[3]`、`settings.permissions.allow`);
6
+ * · `reason` = 帽的量纲,闭集两词:`over_cap`(条数:数组的条目数)/ `too_long`(字符数:一段文字的长度);
7
+ * · `count` = 送来的量(条数或字符数,量纲由 `reason` 定);
8
+ * · `cap` = 帽。
9
+ * 句子的头一句同一句:`<field> has <count> entries|characters — at most <cap> are accepted`;之后各面可以接自己的出路句(为什么拒而不截、怎么改)。
10
+ * 帽本身(数字)归各面的属主;本模块只管「撞了帽怎么说、怎么机读」。
11
+ *
12
+ * 量纲 → `reason` 是一张闭表({@link LIMIT_REASONS}):加一种量纲 ⇒ 这里加一行,`reason` 的词随之进闭集,读者穷举读。
13
+ */
14
+ /** 量纲 → 机读 `reason` 词(闭集)。 */
15
+ export declare const LIMIT_REASONS: {
16
+ readonly entries: "over_cap";
17
+ readonly characters: "too_long";
18
+ };
19
+ /** 帽的量纲:条数 / 字符数(句子里就是这个词)。 */
20
+ export type LimitMeasure = keyof typeof LIMIT_REASONS;
21
+ /** 机读 `reason`:`over_cap`(条数)/ `too_long`(字符数)。 */
22
+ export type LimitReason = (typeof LIMIT_REASONS)[LimitMeasure];
23
+ /** 一处撞帽的机读位(原样进拒体:`refusalBody` 的 facts / `HttpError.extra`;型别名而不是接口 —— 要能直接当 `Record<string, unknown>` 用)。 */
24
+ export type LimitFacts = {
25
+ readonly field: string;
26
+ readonly reason: LimitReason;
27
+ readonly count: number;
28
+ readonly cap: number;
29
+ };
30
+ /** 一处撞帽的拒:句子 + 机读位。 */
31
+ export interface LimitRefusal {
32
+ readonly message: string;
33
+ readonly facts: LimitFacts;
34
+ }
35
+ /** 撞帽的头一句(全仓同一句;`field` 是句子里点名的那一处)。 */
36
+ export declare function describeLimit(field: string, measure: LimitMeasure, count: number, cap: number): string;
37
+ /** 机读位:`reason` 由量纲定。 */
38
+ export declare function limitFacts(field: string, measure: LimitMeasure, count: number, cap: number): LimitFacts;
39
+ /**
40
+ * 一处撞帽的拒:句子 = {@link describeLimit}(+ `tail`:该面的出路句,接在头一句之后),机读位 = {@link limitFacts}(`field` 同一个坐标)。
41
+ * `sentenceField` 只在该面的句子沿用另一种点名写法时给(子代定义的句子写作 `agents[0]: agent.name`,机读位仍是体内坐标 `agents[0].name`)。
42
+ */
43
+ export declare function limitRefusal(field: string, measure: LimitMeasure, count: number, cap: number, opts?: {
44
+ readonly tail?: string;
45
+ readonly sentenceField?: string;
46
+ }): LimitRefusal;
47
+ //# sourceMappingURL=limit-refusal.d.ts.map
@@ -0,0 +1,12 @@
1
+ export const LIMIT_REASONS = { entries: "over_cap", characters: "too_long" };
2
+ export function describeLimit(field, measure, count, cap) {
3
+ return `${field} has ${count} ${measure} — at most ${cap} are accepted`;
4
+ }
5
+ export function limitFacts(field, measure, count, cap) {
6
+ return { field, reason: LIMIT_REASONS[measure], count, cap };
7
+ }
8
+ export function limitRefusal(field, measure, count, cap, opts = {}) {
9
+ const head = describeLimit(opts.sentenceField ?? field, measure, count, cap);
10
+ return { message: opts.tail === undefined ? head : `${head}. ${opts.tail}`, facts: limitFacts(field, measure, count, cap) };
11
+ }
12
+ //# sourceMappingURL=limit-refusal.js.map
package/dist/main.js CHANGED
@@ -15,7 +15,7 @@ async function main() {
15
15
  const s02 = await runStage02(s01);
16
16
  const s03 = await runStage03(s02);
17
17
  const s04 = await runStage04(s03);
18
- const s05 = runStage05(s04);
18
+ const s05 = await runStage05(s04);
19
19
  await settleHostLaneShell(s05.config, s05.logger);
20
20
  const s06 = runStage06(s05);
21
21
  const s07 = await runStage07(s06);