@sema-agent/sdk 16.2.0 → 17.0.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 (54) hide show
  1. package/README.md +116 -0
  2. package/dist/errors.d.ts +83 -13
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +96 -11
  5. package/dist/errors.js.map +1 -1
  6. package/dist/events.d.ts +16 -0
  7. package/dist/events.d.ts.map +1 -1
  8. package/dist/events.js.map +1 -1
  9. package/dist/index.d.ts +20 -4
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +11 -2
  12. package/dist/index.js.map +1 -1
  13. package/dist/resources/approvals.d.ts +34 -30
  14. package/dist/resources/approvals.d.ts.map +1 -1
  15. package/dist/resources/approvals.js +30 -0
  16. package/dist/resources/approvals.js.map +1 -1
  17. package/dist/resources/memory.d.ts +4 -0
  18. package/dist/resources/memory.d.ts.map +1 -1
  19. package/dist/resources/memory.js +4 -0
  20. package/dist/resources/memory.js.map +1 -1
  21. package/dist/resources/rules.d.ts +4 -7
  22. package/dist/resources/rules.d.ts.map +1 -1
  23. package/dist/resources/rules.js.map +1 -1
  24. package/dist/resources/runs.d.ts +6 -0
  25. package/dist/resources/runs.d.ts.map +1 -1
  26. package/dist/resources/runs.js +6 -0
  27. package/dist/resources/runs.js.map +1 -1
  28. package/dist/resources/session-sync.d.ts.map +1 -1
  29. package/dist/resources/session-sync.js +2 -3
  30. package/dist/resources/session-sync.js.map +1 -1
  31. package/dist/resources/sessions.d.ts +8 -0
  32. package/dist/resources/sessions.d.ts.map +1 -1
  33. package/dist/resources/sessions.js +8 -0
  34. package/dist/resources/sessions.js.map +1 -1
  35. package/dist/resources/tasks.d.ts +18 -1
  36. package/dist/resources/tasks.d.ts.map +1 -1
  37. package/dist/resources/tasks.js +18 -1
  38. package/dist/resources/tasks.js.map +1 -1
  39. package/dist/resources/tool-approvals.d.ts +104 -84
  40. package/dist/resources/tool-approvals.d.ts.map +1 -1
  41. package/dist/resources/tool-approvals.js +55 -11
  42. package/dist/resources/tool-approvals.js.map +1 -1
  43. package/dist/settings.d.ts +20 -10
  44. package/dist/settings.d.ts.map +1 -1
  45. package/dist/sync.d.ts +7 -7
  46. package/dist/sync.d.ts.map +1 -1
  47. package/dist/sync.js +32 -17
  48. package/dist/sync.js.map +1 -1
  49. package/dist/types.d.ts +105 -33
  50. package/dist/types.d.ts.map +1 -1
  51. package/dist/types.js +23 -0
  52. package/dist/types.js.map +1 -1
  53. package/openapi.yaml +347 -172
  54. package/package.json +1 -1
package/dist/types.d.ts CHANGED
@@ -57,7 +57,7 @@
57
57
  * null" may be correct — check for a normalizer at the boundary before widening it to `| null`.
58
58
  */
59
59
  import type { SemaSettings } from "./settings.js";
60
- import type { AskOrigin, ClassifierUnavailable, DenialLimitFallback, PersistedRuleMandate, RuleOffer, RuleOffersAbsence, ToolApprovalFrame } from "./resources/tool-approvals.js";
60
+ import type { AllowRuleShadow, AskOrigin, AutoModeFallbackCause, BoundSkillGrants, ClassifierUnavailable, DenialLimitFallback, PersistedRuleMandate, RuleOffer, RuleOffersAbsence, ToolApprovalFrame } from "./resources/tool-approvals.js";
61
61
  /** Authenticated end-user identity. Opaque to the service (used as memory scope + session owner). The SDK
62
62
  * normalizes; the service does NOT validate the format. Convention: `user:` / `org:` / `ai:` / `anon:`. */
63
63
  export type Principal = string;
@@ -212,6 +212,14 @@ export interface TaskStats {
212
212
  /** 🔴 开集:引擎 `result.stats` 可携带本类型未命名的字段(如 `costBreakdown.*` 明细;live 实测),原样透传不丢。 */
213
213
  [key: string]: unknown;
214
214
  }
215
+ /**
216
+ * 请求键 {@link TaskRequest.approvalReach} 的闭集 —— 引擎 `APPROVAL_REACH`(core 7.43.0 #1354)逐字:今天只有 `"none"`(这条 run 上没有人能被问审批)。
217
+ * 没有正向词:「有人可问」是 `interactionPosture:"interactive"` 那一门的承诺。**闭集**(server 用引擎谓词 `isApprovalReach` 判,集外 400):加词 = 引擎下一版 +
218
+ * 本常量与 spec `ApprovalReach` enum 同批加。
219
+ */
220
+ export declare const APPROVAL_REACH: readonly ["none"];
221
+ /** {@link APPROVAL_REACH} 的成员型。 */
222
+ export type ApprovalReach = (typeof APPROVAL_REACH)[number];
215
223
  /** Common request body. `objective` is required; everything else is optional and server-capped where noted.
216
224
  * 🔴 `jobId` is the work-view correlation key (DIRECTION §2): set it so the workspace groups the runs of one
217
225
  * logical job into one Task — across BOTH doors.
@@ -368,6 +376,12 @@ export interface TaskRequest {
368
376
  * **单独送 `debate:true` 不会有辩论轮**;②`resolve-spec` 的显式组队判据是 `council || debate`
369
377
  * (`:940/1555`)⇒ 单独送它**仍然**会放宽租期预算并抑制自动升档。同样只有字面 `true` 算数。 */
370
378
  debate?: boolean;
379
+ /** 图文输入:`{ data, mimeType }`(内联 base64)或 `{ url }`。
380
+ * 🔴 **内联臂的准入(server ≥7.117.0 / core 7.42.0)**:`mimeType` 必须是 `image/png` / `image/jpeg` / `image/gif` / `image/webp` 之一(发 API 自己的类型词,不发扩展名),解码后的字节必须带**声明类型**的文件签名,
381
+ * 解码后不得超 5 MiB —— 过不了 ⇒ 引擎在**第一次模型调用之前**拒(UserPromptSubmit hook 之后,一个模型 token 没烧),**400 `config.image_invalid`**,`error` 以 `TaskSpec.images: ` 起
382
+ * (`config.` 不是前缀族 ⇒ 带码的 `APIError`,按 `errorCode` 分支;400 不自动重试)。≤7.116.x 没有这道门:这种图原样送到模型供应方,整只首请求在供应方那边失败(没有本包可依的码)。
383
+ * **「base64 太长」不走本码**:一张内联图的 base64 串超过 5 242 880 字符(模型 API 的 5 MB 图片界;server 读引擎导出的同一只常量)⇒ 受理口先拒 **413 `request.payload_too_large`**(零模型调用、不跑提交钩子、不建 run 行)。
384
+ * 出路:发文件的原样字节与 API 的类型词;超 5 MB 的图先缩。URL 臂(`{ url }`)不变(server 早已按签名认类型)。模型要支持图片输入(见 {@link ModelInfo.vision};缺席 ⇒ 照发)。 */
371
385
  images?: Array<{
372
386
  data: string;
373
387
  mimeType: string;
@@ -680,6 +694,15 @@ export interface TaskRequest {
680
694
  * deployment supports them). Probe `capabilities.interactiveTools` (server hardcodes true — the `interactiveTools` bit in `routes/capabilities.ts`)
681
695
  * before sending to OLDER servers — an unknown-field deployment on the strict lane would 400. */
682
696
  interactiveTools?: boolean;
697
+ /**
698
+ * server ≥7.118.0(core 7.43.0 #1354)—— **声明这条 run 上没有人能答审批**。唯一一词 `"none"`({@link APPROVAL_REACH});原样投引擎 `TaskSpec.approvalReach`。
699
+ *
700
+ * 给 `-p` 这类握着流、却没有人能答审批的壳:不声明时部署的审批席照发活卡、wiring 清单报 `ask.effective:"human_reachable"`。声明之后活的回调不再是
701
+ * 这条 run 的审批人(wiring 清单 `ask.form:"declared_none"`);**有停驻设施的部署上第一次门控调用就停驻**(run `paused`)—— 要「拒了接着跑」用
702
+ * `permissionMode:"dontAsk"`。它**不**放行、**不**释放任何东西。引擎不把它写进检查点,续跑腿由 server 从持久化体重供。
703
+ * 读不出的值(集外词 / 非串)⇒ `400 request.field_invalid`。先探 {@link Capabilities.approvalReach}(缺席 = 老 server)。不发 = 零变化。
704
+ */
705
+ approvalReach?: ApprovalReach;
683
706
  /**
684
707
  * 🔴 ONE-SHOT SUBMISSION declaration (core ≥5.23.0 `TaskSpec.oneShot`, server ≥7.12.0 —
685
708
  * `src/http/wire-types.ts` 的请求形;非 boolean = fail-loud 400 `request.field_invalid`
@@ -913,17 +936,12 @@ export interface TaskAgentDefinition {
913
936
  /** Denylist of tool names (subtractive; applied after `allowTools`). */
914
937
  denyTools?: string[];
915
938
  /** Skills preloaded into the agent: `{ name, description, content }` (+ optional allowedTools / disallowedTools / files).
916
- * server ≥7.116.0:子代技能受理两只清单(`allowedTools` / `disallowedTools`,读法见 {@link SkillSpec.allowedTools};≤7.115.x 是未知键整条拒)。 */
939
+ * server ≥7.116.0:子代技能受理两只清单(`allowedTools` / `disallowedTools`,读法见 {@link SkillSpec.allowedTools};≤7.115.x 是未知键整条拒)。
940
+ * ⚰️ sdk 17.0.0 删 `manifest`(core 7.41.0 退役、server ≥7.116.0 整条拒;≤7.115.x 收下也不生效)—— 改写:`manifest.allowTools` → `allowedTools`,`allowPaths` 无替身(用会话规则 `allowDirs`)。 */
917
941
  skills?: Array<{
918
942
  name: string;
919
943
  description: string;
920
944
  content: string;
921
- /** @deprecated server ≥7.116.0 **整条技能拒**(子代技能上 `manifest` 是未知键 ⇒ `agent.skills must be …` 400;顶层技能是 400 `request.field_invalid`,
922
- * 句首 `skill.manifest was retired in core 7.41.0 — `)—— core 7.41.0 退役了技能 `manifest`(硬破坏,零别名)。**改写**:`manifest.allowTools` →
923
- * 技能的 `allowedTools`(语义变了:allow 规则来源、不是围栏,见 {@link SkillSpec.allowedTools});写围栏 `allowPaths` 没有替身
924
- * (圈写路径用会话规则 `allowDirs`)。详见 server 随包 `MIGRATION.md` 7.116.0 节。
925
- * 本成员**留着**:老一代 server(≤7.115.x)仍收它,删公开成员 = major,下个 major 删;对 ≥7.116.0 的 server 别再发。 */
926
- manifest?: Record<string, unknown>;
927
945
  allowedTools?: string[];
928
946
  disallowedTools?: string[];
929
947
  files?: Array<{
@@ -1136,9 +1154,15 @@ export interface SyncSubmitResult extends TaskResult {
1136
1154
  * 先到先得:一条腿只被中止一次,先落地的那次定词(断连之后又到的取消动词、取消之后又断连,终局说的都是真正让它停下来的那一个)。
1137
1155
  * **闭集**,按 additive 规矩只会加词(加词 = server 新版本的 wire 变更〔`wire-changes` 登记〕+ 本包下一版形变,spec 具名 schema `AbortCause` 的 enum 同批):
1138
1156
  * 认不得的词读作「server 中止,成因不认识」。属主是 server `plugins/store-contracts.ts` 的 `ABORT_CAUSES`(自铸登记 `trace/self-minted-wire.ts#abortCause`);
1139
- * 测试对已装 server 的真登记做四方相等(server 常量 / 登记 / spec enum / 本型的词)。读法与在场闸见 {@link TaskResult.abortCause}。
1157
+ * 测试对已装 server 的真登记做四方相等(server 常量 / 登记 / spec enum / 本常量)。读法与在场闸见 {@link TaskResult.abortCause}。
1158
+ *
1159
+ * 🔴 **运行期常量**(sdk 17.0.0 起导出;消费方的生成表直接读它,不手抄第二份):与 server 的 `ABORT_CAUSES` **同名同序**;
1160
+ * server 包根不导出那一只(`./dist/*` 子路径也不导出),所以本包是消费方能 import 的唯一一处 —— 测试对已装 server 发布字节里的真常量逐词逐序对拍。
1161
+ * `Object.freeze` 的字面元组(公面消费者 push 一下就能改写判定的病形)。
1140
1162
  */
1141
- export type AbortCause = "client_disconnected" | "ask_park_grace_exhausted" | "cancel_verb";
1163
+ export declare const ABORT_CAUSES: readonly ["client_disconnected", "ask_park_grace_exhausted", "cancel_verb"];
1164
+ /** {@link ABORT_CAUSES} 的成员型。 */
1165
+ export type AbortCause = (typeof ABORT_CAUSES)[number];
1142
1166
  /**
1143
1167
  * 取消现场快照里的**大脑相位**(server `RunBrainStatusSnapshot`,`turn-activity.ts` `pickRunBrainStatus` 投出的五键子集;K-43,sdk 16.0.0 具名)——
1144
1168
  * 「取消那一刻引擎正在重试第几次 / 在等什么 / 什么错类」。`phase` 是这只快照的存在理由(没有它就没有快照,不铸半只)。
@@ -1394,7 +1418,10 @@ export interface ModelInfo {
1394
1418
  provider?: string;
1395
1419
  /** 该模型是否 reasoning 档(picker 可标徽章)。 */
1396
1420
  reasoning?: boolean;
1397
- /** 是否支持图片输入。 */
1421
+ /** 这条目录行**收不收图片输入**,三态(server ≥7.117.0;之前对没声明的条目报 `false`):`true` = 条目声明了 `input` 且含 `"image"`;`false` = 声明了 `input` 且不含它;
1422
+ * **键缺席 = 条目没声明 `input`**(手写的目录条目;env 车道与配置中心车道恒声明,不会缺席)—— 缺席 = **不知道**,不是 `false`。
1423
+ * 🔴 消费方读法:**缺席 ⇒ 照发并告知**(把图交给 server,由引擎处理;收不收以引擎为准),**不要读成 false(也就是别据此把用户的图拦在本地)** —— server 对同一条目在运行期照样把图交给模型,
1424
+ * 拦截只会让「目录说不知道」变成「用户发不出图」。≤7.116.x 的 server 对没声明的条目报 `false`(那是它们的读法,同一个坑);只有明说 `false` 才该提示「这个模型不收图」。 */
1398
1425
  vision?: boolean;
1399
1426
  /** E4(shell-host;service src/http/routes/capabilities.ts,SHIPPED)— 上下文窗口 token 总额 = 「% 上下文已用 / 距 compact N
1400
1427
  * token / 低上下文告警」仪表的**分母**。soft-degrade:未知(0)则 service 省略 → 壳渲染裸 token 数无 %。
@@ -2399,7 +2426,7 @@ export type DeniedBy = "policy" | "hook" | "org" | "persisted_rule" | "classifie
2399
2426
  */
2400
2427
  export type PermissionMode = "default" | "acceptEdits" | "plan" | "auto" | "bypassPermissions" | "dontAsk";
2401
2428
  /**
2402
- * 一只问**属于哪一类**(core `ASK_CLASSES`:7.34.0 铸二十词,core 7.39.0 起 `shell_floor` 入册 ⇒ 二十一词,core 7.40.0 起 `unstated` 入册 ⇒ 二十二词,core 7.41.0 起 `requires_user_interaction` 入册 ⇒ **二十三词**;模式 × 类仲裁表的列)。K-32 扩项 / server ≥7.106.0 起出现在
2429
+ * 一只问**属于哪一类**(core `ASK_CLASSES`:7.34.0 铸二十词,core 7.39.0 起 `shell_floor` 入册 ⇒ 二十一词,core 7.40.0 起 `unstated` 入册 ⇒ 二十二词,core 7.41.0 起 `requires_user_interaction` 入册 ⇒ 二十三词,core 7.43.0 起 `classifier_no_ruling` 入册 ⇒ **二十四词**;模式 × 类仲裁表的列)。K-32 扩项 / server ≥7.106.0 起出现在
2403
2430
  * {@link ModeRelease.askClass} / `.classes` 与 deny 臂的 `askClass` / `classes` 上,以及通告 `permission.ask_released_by_mode` 的 detail 里;
2404
2431
  * K-37 扩项 / server ≥7.109.0(S-934 ②)起也在审批面:活卡帧 / 卡面 / 运维队列行 / `/stream` `pending` 帧的 `askClass` / `classes`
2405
2432
  * (同样经 core `isAskClass` 筛,读不出整对不投;见 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.askClass})。
@@ -2421,6 +2448,9 @@ export type PermissionMode = "default" | "acceptEdits" | "plan" | "auto" | "bypa
2421
2448
  * `plan` 模式下只有**只读**的服务器工具出这张卡。本类说的是「**没人说**」,不是 `ask_rule` / `org_rule` 那种「有人说了问」。
2422
2449
  */
2423
2450
  export type AskClass = "content_question" | "hook" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback"
2451
+ /** core 7.43.0 #1353 / server ≥7.118.0:auto 模式的分类器**没判出来**(它跑不了 —— `error` / `timeout`,或答了却没有判词 —— `parse_error`),于是交给人:
2452
+ * denial-limit 回落那一行(只有人的答清得掉;**免疫 bypass**,allow 规则清不掉,分类器不再被问)。活卡帧 / 收件箱行另带成因 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.classifierNoRuling}。 */
2453
+ | "classifier_no_ruling"
2424
2454
  /** core 7.41.0 / server ≥7.116.0:服务器工具申报声明「每次调用都要用户在场」(见本型顶注)—— **不在** `bypassPermissions` 可放的十类里,只有人的答清得掉。 */
2425
2455
  | "requires_user_interaction" | "operator_forced"
2426
2456
  /** core 7.39.0(#1260;server ≥7.113.0 提货):运维旋钮 `shellGate: "always"` 在**跑 shell 的席位**上的地板 —— `operator_always` 授权词所披露的那一问,
@@ -3250,19 +3280,26 @@ export interface SkillSpec {
3250
3280
  * 🔴 **读法变了:它不是围栏**(≤7.115.x 引擎 7.40 把它当「只许这些」的围栏读)—— 7.116.0 起**没列的工具照常判**(询问类模式下问、
3251
3281
  * `bypassPermissions` 或部署 allow 下直接跑),不再因为没列被拒;**列着的工具在这只技能被激活之后、本 run 内免问**
3252
3282
  * (激活 = 请求顶层 {@link TaskRequest.userInvokedSkills} 点了它的名〔开跑即生效、不出 `Skill` 卡〕,或模型调 `Skill` 激活且那张卡被批准)。
3253
- * 清的是引擎的普通问与「没人表态」两类问,所以**比同版 `settings.permissions.allow` 更宽**(后者仍只是表态,不放内置工具上引擎自己的
3254
- * 写门 / shell 普通问);deny 规则 / ask 规则 / `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / shell 地板 / 写保护 / plan 模式的问,清单都清不掉。
3283
+ * 清的是引擎的普通问与「没人表态」两类问;deny 规则 / ask 规则 / `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / shell 地板 / 写保护 / plan 模式的问,清单都清不掉。
3284
+ * 🔴 **与 `settings.permissions.allow` 的关系随 server 代际变(7.117.0 起收成一种读法)**:**≥7.117.0**(能力位 `settings.permissions.allowLayer`,core 7.42.0)两只请求级放行源是**同一读法**
3285
+ * —— 同一条条目逐格同读(都进引擎的 allow 层、都清内置工具的写门 / shell 普通问、读成空的条目都发通告 `permission.allowed_tool_not_granted`);**7.116.x 上**请求自带技能的清单
3286
+ * **比同版 `settings.permissions.allow` 更宽**(后者当时只是表态,不放内置工具上引擎自己的写门 / shell 普通问)—— 那一口径到 7.116.x 为止。
3255
3287
  * 值形:字符串数组(含空数组)⇒ 受理;裸串 / 含非串 / 对象 ⇒ 400 `request.field_invalid`;协议名的服务器段铸不出 / 缺段 / 带通配(`mcp__*`)⇒ 400
3256
- * (顶层 `skills[]` 与子代 `agents[].skills[]` 两处受理口同判)。
3288
+ * (顶层 `skills[]` 与子代 `agents[].skills[]` 两处受理口同判)。🔴 **7.117.0 起另有两道**(两张清单、顶层与子代两处受理口同判):**名字层**与 `settings.permissions.allow` 同一只判官 —— 退役名 / 无前缀短名(例 `Task`)
3289
+ * 提交即 400(7.116.x 受理,引擎读作一个永不命中的名字);每张清单**超过 1000 条** ⇒ 400(句子给写法「合并成更宽的条目」;7.116.x 无帽)。
3257
3290
  * 🔴 **先探 `capabilities.skillToolLists`**:位缺席 = 老 server ⇒ 顶层技能上的两只清单**照收但引擎不读**(静默不生效,没有 400 可探 ——
3258
3291
  * 别指望清单拦得住工具,圈工具用 deny 规则),子代技能上是未知键整条拒。
3259
3292
  * 🔴 `manifest` 键 server ≥7.116.0 **提交即拒**(顶层 400 `request.field_invalid`、子代整条技能拒);改写 `manifest.allowTools` → 本键;
3260
3293
  * 写围栏 `allowPaths` 没有替身(圈写路径用会话规则 `allowDirs`)。本型从不声明 `manifest` ⇒ 顶层按型写不出它。 */
3261
3294
  allowedTools?: string[];
3262
3295
  /** server ≥7.116.0:这只技能的 **deny 规则来源**(同 {@link allowedTools} 的文法 / 两道受理门 / 探测位):技能被激活之后,本 run 内这些工具**拒**(不执行、零卡,
3263
- * `tool_end.gate.disposition` 为 `{ kind: "denied", deniedBy: "policy" }`)。`*` 与域名形(`WebFetch(domain:…)`)在这一侧也读作「无」—— 受理 2xx,
3264
- * 只进运维面通告 `skills.allowed_tool_not_granted`(core 引擎通告,受众 operator,不上会话流);写路径形(`Write(/tmp/**)`)与其余条目照编 deny 行
3265
- * (这两句取自 server 契约 / 判据 C2.d·C19.e 对 core `compileSkillGrant` 读数的转述;core 的通告文案把「写路径 / 域名」一并列为「grant or refuse nothing」,**本包未亲跑引擎**核 deny 侧的写路径形)。位缺席 = 老 server(见 {@link allowedTools})。 */
3296
+ * `tool_end.gate.disposition` 为 `{ kind: "denied", deniedBy: "policy" }`);写路径形(`Write(/tmp/**)`)与命令规则照编 deny 行。
3297
+ * 🔴 **server ≥7.117.0:引擎读成空的条目提交即 400**(顶层 `skills[]` 与子代 `agents[].skills[]` 两处受理口同判)—— `*`、域名形(`WebFetch(domain:…)`)、协议名带通配、带空白 / 畸形的名字:
3298
+ * `400 request.field_invalid`,`error` = `skill.disallowedTools entry "<条目>" reads as nothing (<原因词>): <怎么写>`(子代那一层前缀 `agents[<i>]: skills[<j>]: `)。
3299
+ * 为什么拒:一条以为拒了、其实什么也不拒的条目,比没有更坏(≤7.116.x 受理这种条目,只发一条 operator 受众、不上会话流的通告;**那个旧码已改名**为 `permission.allowed_tool_not_granted`,user 受众、上会话流 —— 见 `engine_notice` 臂)。
3300
+ * 🔴 **续跑同判**:升级时还停驻、提交体里带这种条目的任务,续跑 ⇒ 认领之前 **409 `resume_blocked_by_policy`**(`blockedBy:"request.field_invalid"`,`error` 带同一句;行与卡一个字节不动,出路 = 取消、改好条目重提;
3301
+ * 终态 run 的 `POST /v1/runs/:id/steer` 在铸唤醒卡之前当场同答)—— 因为引擎 7.41 去首尾空白(`"Bash "` 曾是一条有效的拒)而 7.42 逐字读(读成空),不判就是升级后那条拒无声消失。
3302
+ * allow 侧不拒(`allowedTools` 里读成空的条目发通告)。位缺席 = 老 server(见 {@link allowedTools})。 */
3266
3303
  disallowedTools?: string[];
3267
3304
  }
3268
3305
  /** A per-request MCP server (CC `.mcp.json` parity) — core-native `McpServerSpec` shape (core types.ts:277).
@@ -3607,8 +3644,10 @@ export interface Capabilities {
3607
3644
  * 🔴 **两端都读**:同步是 src → dst 两个 peer,**任一端为 `false` ⇒ 只同步对话**:别推 `fileHistory`、别 PUT blob(把 `fileHistory` 推给没有 blob 面的对端,
3608
3645
  * commit 之后因缺 blob 422 `missing_blob`)。位为 `false` 时两口答 **501 `capability.snapshot_store_required`**(任何会话 id 同一句,先于属主判);
3609
3646
  * blob「未被会话历史图引用 / 字节不存在」仍是 404 `not_found.blob`(scope 边界,只在有 blob 面的后端上可达)。
3610
- * ⚠️ **缺席 = 老 server(≤7.115.x)**:那里 `sessionSync: true` 的 local 部署上 PUT blob 恒 501(位说「能」而口恒拒)—— 缺席时**读不出**这一面能不能用,
3611
- * 既有 verb 照旧试(`pushSessionBundle` / `pullSessionBundle` 对缺席位照旧尝试,见 {@link import("./sync.js").PushSessionResult.fileHistory})。 */
3647
+ * ⚠️ **缺席 = 老 server(≤7.115.x)= 不知道**:那里 `sessionSync: true` 的 local 部署上 PUT blob 恒 501、`GET …/sync/history/blobs` 对清单引用的 blob 恒 404(位说「能」而口恒拒)。
3648
+ * sdk 17.0.0 起编排 verb 按一条律读(`pushSessionBundle` / `pullSessionBundle` / `importSessionBundle` 同读):**信封引用了 blob 而某一端位缺席 ⇒ 不搬**(`fileHistory:"skipped"`,只同步对话);
3649
+ * 信封不引用 blob(只有回退边界)⇒ 照带 —— 16.2.0–16.3.0「缺席 ⇒ 照旧尝试」退役(那一读法在 7.52–7.115 的 local 后端上改过文件的会话整次抛),
3650
+ * 见 {@link import("./sync.js").PushSessionResult.fileHistory}。 */
3612
3651
  sessionSyncFileHistory?: boolean;
3613
3652
  /** 🔴 K-5 session-resume gates(service src/http/routes/capabilities.ts,§0.5 session 抽象)—— shell 的 `/resume` picker 据此诚实
3614
3653
  * gate,别 trial-by-501:`sessionList` = list 可用(`Boolean(sessionStorage.listSessions ?? runStore.listSessions)`,
@@ -3684,15 +3723,20 @@ export interface Capabilities {
3684
3723
  hooks?: boolean;
3685
3724
  [k: string]: unknown;
3686
3725
  };
3687
- /** 🔴 **server ≥7.115.0 起恒在**:`{ permissions: { allowGrant: true } }` —— 「请求体 `settings.permissions.allow` 按**哪一种读法**收」的**版本位**(S-654;wire additive,新顶层键)。
3688
- * `permissions.allowGrant === true` = 这台 server 把 `allow` 桶编成 **allow 规则**:命中 = 给出「有人表态」(让没人表态的 MCP / A2A 服务器工具调用不再出卡),**不是免问、不是名单**
3689
- * (名单外的工具不再被拒;引擎对内置工具的写门 / shell 检查照问,deny / ask 照赢;坏形 / 内容形名字提交即 422 —— 读法全文见 {@link import("./settings.js").SettingsPermissions.allow})。
3690
- * 🔴 **键缺席 = 老 server(≤7.114.x,按名单读 `allow`:名单外一律拒)—— 别投 allow 桶**(投了只是一份收窄,方向安全,但不是你要的「表态」)。
3726
+ /** 🔴 **server ≥7.115.0 起恒在**:`{ permissions: { allowGrant: true } }`;**≥7.117.0 起 `permissions` 多一位 `allowLayer: true`** —— 「请求体 `settings.permissions.allow` 按**哪一种读法**收」的**版本位**(wire additive;两位都是恒真、
3727
+ * 不随部署形变:单用户与 `REQUIRE_PRINCIPAL=true` 两形同值,不挂任何设施)。逐位读,三段读 `settings` → `permissions` → <位>:
3728
+ * · `allowGrant === true`(≥7.115.0)= 两代都成立的那句话:**allow 桶按 allow 规则读,不是名单**(名单外的工具不再被拒);键缺席 = 老 server(≤7.114.x,按名单读)—— **别投 allow 桶**(投了只是一份收窄,方向安全,但不是你要的)。
3729
+ * · `allowLayer === true`(**≥7.117.0**,core 7.42.0)= 这台 server 把 `allow` **整份原样**交给引擎的 **allow 层**:表里的调用**免问** —— 清「普通问 + 没人表态」两类(内置工具的写门 / shell 普通问也清,与参照实现的 `permissions.allow` 同读);
3730
+ * **内容形受理**(`Bash(git:*)`、`Read(//dir/<glob>)`);引擎读成空的条目(`*`、写路径 / 域名形、带空白的名字、`Read(~/…)`)**不拒**,开跑时收 `engine_notice` `permission.allowed_tool_not_granted`(user 受众);
3731
+ * 清不掉的:任何一层的 deny / ask 规则、运维强制类(`APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / `MANUAL_MODE_SHELL_GATE=always` / 写保护 / 敏感写 / 治理)、hook 的问、plan 的问 —— 清不掉而命中时卡上带 `allowRuleShadowed`
3732
+ * ({@link import("./resources/tool-approvals.js").ToolApprovalFrame.allowRuleShadowed});受理口只判**名字**(退役名 / 无前缀短名 / 协议名对端段铸不出 ⇒ 422)与条数(≤1000,超了 400),内容不判。
3733
+ * 🔴 **键缺席 = 7.115.0–7.116.x(allow 只表态:不放掉内置工具的写门 / shell 检查,内容形整请求 422)或更老 —— 别指望内置工具免问、别投内容形**。
3691
3734
  * ⚠️ 与 `taskSettings.permissions` 不是一件事:那一位不变、仍是布尔(只说「受理这一面」,读 `=== true` 的旧端不失明);判 allow 的读法只看本位。
3692
- * 本位是**版本位**:恒 `true`、不随部署形变;部署级「替谁表了态」(运维 env `APPROVAL_GRANT`)不在能力面,在 operator 诊断面 {@link ServerWiringGates.approvalGrant}。 */
3735
+ * 运维侧「替谁表了态」(env `APPROVAL_GRANT`)不在能力面,在 operator 诊断面 {@link ServerWiringGates.approvalGrant}。 */
3693
3736
  settings?: {
3694
3737
  permissions?: {
3695
3738
  allowGrant?: boolean;
3739
+ allowLayer?: boolean;
3696
3740
  [k: string]: unknown;
3697
3741
  };
3698
3742
  [k: string]: unknown;
@@ -3709,6 +3753,9 @@ export interface Capabilities {
3709
3753
  retainBackgroundProcesses?: boolean;
3710
3754
  /** TaskRequest.interactiveTools 认词(`routes/capabilities.ts` 的能力对象 硬编码 true;-p 无人值守语义探测位 —— 见 TaskRequest 注)。 */
3711
3755
  interactiveTools?: boolean;
3756
+ /** server ≥7.118.0(`routes/capabilities.ts` 的能力对象**硬编码 true**,与请求键同一个词)—— 请求键 {@link TaskRequest.approvalReach} 认词的**版本探测位**。
3757
+ * 缺席 = 老 server:别发那只键(严格体会拒)。 */
3758
+ approvalReach?: boolean;
3712
3759
  /** TaskRequest.cwd honored(`routes/capabilities.ts` 的能力对象 `cwdHonored`:local 单用户 host-adapter 才 true;多租户 fail-closed)。
3713
3760
  * 🔴 K-32 扩项(server ≥7.106.0 / S-895):本位也是请求键 {@link TaskRequest.inheritEnv} `"all"` 的**精确兑现读数** —— 谓词(host 车道 ∧
3714
3761
  * 非托管)与那个键的车道门 + 射程门逐组合相等(契约附录 B.1 该行 / §18)。`false` ⇒ 发 `"all"` 会拿 400(非 host 车道)或 422(托管)。 */
@@ -3786,6 +3833,12 @@ export interface Capabilities {
3786
3833
  * 「这个二进制认识这个键」——与 {@link permissionRulesRevoke} 的存在性信号同族,刻意不挂任何设施谓词。
3787
3834
  */
3788
3835
  approvalDecisionNote?: boolean;
3836
+ /**
3837
+ * server ≥7.118.0(`routes/capabilities.ts` 的能力对象**硬编码 true**,恒真的版本位)—— 三条审批决定口收决定体的出处位 `decidedBy`
3838
+ * ({@link import("./resources/approvals.js").ApprovalDecidedBy})。**见位才发**:位缺席 = 老 server —— 耐久两口与 `plan_review` 对它 400、
3839
+ * live `respond` 静默丢 + 200,照老形发(不带这只键)。与 {@link approvalDecisionNote} 同族:只答「这个二进制认识这个键」,不挂设施谓词。
3840
+ */
3841
+ approvalDecidedBy?: boolean;
3789
3842
  /**
3790
3843
  * #340(server ≥7.44.0,`routes/capabilities.ts` 的能力对象**硬编码 true**)—— live 回决口
3791
3844
  * `POST /v1/tool-approvals/:id/respond` 收 `persistRule.edited: true` 的**版本探测位**:
@@ -4608,6 +4661,13 @@ export interface PendingCheckpoint {
4608
4661
  /** core 5.11.0([2625] Added②):铸造时在场的 shell 门 doctrine 自报——仅 shell-gated ask 铸造
4609
4662
  * 时在场(在场条件敏感,勿按在场性判别 code;[2597] 案取证缺口的结构性补)。 */
4610
4663
  shellGateDoctrine?: "classify" | "always";
4664
+ /** server ≥7.117.0(core 7.42.0)—— allow 层披露:命中这次调用、却没能清掉这只 ask 的成员,`{ member, entries, omitted? }[]`(见 {@link AllowRuleShadow};
4665
+ * 语义逐字见 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.allowRuleShadowed} —— 本键是它的**耐久对偶**,经 `GET /v1/approvals` 与 `/stream` 的 `riskDescriptor`
4666
+ * 整体透传;条目在读边界另过 server 的脱敏)。缺席 ≠ 「你没有规则」。
4667
+ * 🔴 **旧键 `shadowedRule`(字符串)已退役**(≤7.116.x 的耐久对偶,本型从未声明它):SQL 后端在 7.117.0 升级起服时把停驻行一次性改写成
4668
+ * `[{ member: "persisted", entries: [<旧值>] }]`;**file 后端升级前的停驻行与已落盘的 run 结果**(`checkpointGate.riskDescriptor`)上旧键原样留着(文本仍脱敏,只缺结构化披露)——
4669
+ * 读这两处的消费端要同时认得「旧串」,本包不为它再声明一个键。 */
4670
+ allowRuleShadowed?: AllowRuleShadow[];
4611
4671
  } | null;
4612
4672
  [k: string]: unknown;
4613
4673
  }
@@ -4639,11 +4699,15 @@ export interface SessionRecord {
4639
4699
  * 承载它的 server 进程却在那条 run 收场前死了(**引擎在进程死前没来得及确认消费**;server ≥7.113.0 / core 7.39.0 #1273 起引擎确认消费过的受理结清成 `consumed`、
4640
4700
  * **不再**列在这里 —— 7.112.x 及以前「消费与否未知」的口径随之收窄;它**仍不**说「从未消费」,见 `engine_notice` `task.user_steer_undrained{cause:"crashed"}`)。
4641
4701
  * 只列收敛行、同 (taskId, messageId) 一行、至多最新 500 条;`announced` = 已在哪条新 run 首拍告知过。server ≥7.111.0(S-966)起行里**含同步子代的 steer**
4642
- * (记在回执上那条 run 名下,`messageId` = 那张子代 steer 回执的 `messageId`,行形与 run steer 同 —— `kind` 仍只有 `"steer"`)。**缺席 = 这一次读没有可报的条目**
4643
- * (零条,或这一次账本读不出 —— 权威告知是 run 流上的通告帧,不是本键);`?message=` 单条形不带。 */
4702
+ * (记在回执上那条 run 名下,`messageId` = 那张子代 steer 回执的 `messageId`,行形与 run steer 同)。**缺席 = 这一次读没有可报的条目**
4703
+ * (零条,或这一次账本读不出 —— 权威告知是 run 流上的通告帧,不是本键);`?message=` 单条形不带。
4704
+ * 🔴 **`kind` = 受理时它排进的引擎车道**(server ≥7.118.0 / core 7.44.0 #1362,闭两词):`"steer"`(`priority` 为 `now` / `next` 或缺省)·
4705
+ * **`"follow_up"`**(`priority:"later"`,排到 run 收场的那一道)。对应的崩溃告知码分两族:`task.user_steer_undrained` / `task.user_followup_undrained`
4706
+ * (后者 `detail: { followUp, cause:"crashed", taskId, sessionId }`)。按 `kind === "steer"` 过滤的消费方会少看见 `later` 那几行 —— 两词同读,按 `cause` 分支。
4707
+ * 升级前受理、升级后才告知的 `later` 受理按当时的族(`steer`)报。 */
4644
4708
  userInputUndrained?: Array<{
4645
4709
  messageId: string;
4646
- kind: "steer";
4710
+ kind: "steer" | "follow_up";
4647
4711
  taskId: string;
4648
4712
  acceptedAt: string;
4649
4713
  cause: "crashed";
@@ -5099,10 +5163,9 @@ export interface SessionManifest {
5099
5163
  /** The session's current leaf entry id, or null. */
5100
5164
  leafId: string | null;
5101
5165
  /** 🔴 **server ≥7.52(S-15)起不发这个键、wire 上不再有它**(E19 整树快照纪元退役;server `exportSessionManifest` 铸 `{ sessionId, entryIds, entryCount, leafId, fileHistory, policy, anchors }`,
5102
- * 7.116.0 发布字节逐键核过)。≤7.51 老 server 仍发它。**本型承诺它恒是数组**:{@link import("./resources/session-sync.js").SessionSyncResource.manifest} 在 wire 缺席时填 `[]`
5103
- * —— 所以对 ≥7.52 的 server 它恒空,真正的文件历史在 {@link fileHistory}。
5104
- * 🚧 这是为了不在 minor 里收窄公开型的**披露性过渡**(`snapshots` 本该是可选 / 随退役纪元删除):**下一个 major 把它改可选并删掉 `manifest()` 的填充**。 */
5105
- snapshots: SyncSnapshot[];
5166
+ * 7.116.0 发布字节逐键核过)。≤7.51 老 server 仍发它。**缺席 = 这台 server 不发整树快照**(真正的文件历史在 {@link fileHistory});
5167
+ * sdk 17.0.0 起本成员可选、`manifest()` 原样交回 wire(16.x 在缺席时填 `[]`,那一层过渡删了 —— 读它的代码按「缺席 = 没有」处理)。 */
5168
+ snapshots?: SyncSnapshot[];
5106
5169
  /** server ≥7.52:per-edited-file 文件历史信封({@link FileHistoryExport});`null` = 没有历史 / 源店导不出;**键缺席 = ≤7.51 老 server**(那一代走 {@link snapshots})。
5107
5170
  * 搬 blob 前先读两端的 {@link Capabilities.sessionSyncFileHistory}(server ≥7.116.0)。 */
5108
5171
  fileHistory?: FileHistoryExport | null;
@@ -5116,7 +5179,8 @@ export interface SessionBundle {
5116
5179
  sessionId: string;
5117
5180
  /** The FULL durable conversation log, verbatim ids/parents/payload (oldest-first). */
5118
5181
  entries: SyncEntry[];
5119
- snapshots: SyncSnapshot[];
5182
+ /** 同 {@link SessionManifest.snapshots}(≤7.51 老 server 的整树快照;缺席 = 源是 ≥7.52)。 */
5183
+ snapshots?: SyncSnapshot[];
5120
5184
  /** 同 {@link SessionManifest.fileHistory}(server ≥7.52 的文件历史信封;键缺席 = 源是 ≤7.51 老 server)。 */
5121
5185
  fileHistory?: FileHistoryExport | null;
5122
5186
  policy: SessionRulesRecord[];
@@ -5494,6 +5558,14 @@ export interface InboxRow {
5494
5558
  * 且长过,读法与别处逐字相同:认已知词 + 一条 default 臂,未知词读「未知出身」而**不是**「没有出身」。
5495
5559
  * 这一位出现之前铸的老行读作缺席(未上报),不是「没有权威」。 */
5496
5560
  origin?: AskOrigin;
5561
+ /** server ≥7.118.0(core 7.43.0 #1348 / #1357)—— 引擎 `Skill` 工具的停驻卡上的授予绑定摘要,与活卡帧同名位同值
5562
+ * ({@link import("./resources/tool-approvals.js").ToolApprovalFrame.boundGrantDigest});别的卡缺席。 */
5563
+ boundGrantDigest?: string;
5564
+ /** server ≥7.118.0 —— 上一位哈希的那一份值;**只在它确实哈希成 {@link boundGrantDigest} 时**出现(引擎判,server 不重算 —— 摘要绑定另一份时清单读作缺席)。
5565
+ * 🔴 部署文本:渲染按上下文转义。 */
5566
+ boundGrants?: BoundSkillGrants;
5567
+ /** server ≥7.118.0(core 7.43.0 #1353)—— 只在类 `classifier_no_ruling` 的停驻卡上:分类器为什么没判({@link AutoModeFallbackCause})。 */
5568
+ classifierNoRuling?: AutoModeFallbackCause;
5497
5569
  /** server ≥7.69.0(core 7.10.0 #616)—— **为什么这一问会到我手上**:分类器被咨询过但答不了。inbox 是
5498
5570
  * **分诊**面,`breaker_open` 在这里价值最大 —— 它预告的是一场审批风暴,而不是一次偶发询问。
5499
5571
  * 形与三条硬读法(开集 `cause` / 缺席不是断言 / switch 带 default)逐字见 {@link ClassifierUnavailable}。