@sema-agent/sdk 16.1.0 → 16.2.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 (70) hide show
  1. package/README.md +62 -1
  2. package/dist/errors.d.ts +47 -11
  3. package/dist/errors.d.ts.map +1 -1
  4. package/dist/errors.js +26 -4
  5. package/dist/errors.js.map +1 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/resources/adoption.d.ts +2 -1
  10. package/dist/resources/adoption.d.ts.map +1 -1
  11. package/dist/resources/adoption.js +2 -1
  12. package/dist/resources/adoption.js.map +1 -1
  13. package/dist/resources/approvals.d.ts +10 -3
  14. package/dist/resources/approvals.d.ts.map +1 -1
  15. package/dist/resources/approvals.js +11 -3
  16. package/dist/resources/approvals.js.map +1 -1
  17. package/dist/resources/assistant.d.ts +4 -2
  18. package/dist/resources/assistant.d.ts.map +1 -1
  19. package/dist/resources/assistant.js.map +1 -1
  20. package/dist/resources/leader.d.ts +5 -4
  21. package/dist/resources/leader.d.ts.map +1 -1
  22. package/dist/resources/leader.js +5 -4
  23. package/dist/resources/leader.js.map +1 -1
  24. package/dist/resources/memory.d.ts +6 -2
  25. package/dist/resources/memory.d.ts.map +1 -1
  26. package/dist/resources/memory.js +3 -1
  27. package/dist/resources/memory.js.map +1 -1
  28. package/dist/resources/ops.d.ts +3 -0
  29. package/dist/resources/ops.d.ts.map +1 -1
  30. package/dist/resources/ops.js +3 -0
  31. package/dist/resources/ops.js.map +1 -1
  32. package/dist/resources/rules.d.ts +4 -3
  33. package/dist/resources/rules.d.ts.map +1 -1
  34. package/dist/resources/rules.js +3 -3
  35. package/dist/resources/rules.js.map +1 -1
  36. package/dist/resources/runs.d.ts +20 -6
  37. package/dist/resources/runs.d.ts.map +1 -1
  38. package/dist/resources/runs.js +3 -2
  39. package/dist/resources/runs.js.map +1 -1
  40. package/dist/resources/session-sync.d.ts +11 -7
  41. package/dist/resources/session-sync.d.ts.map +1 -1
  42. package/dist/resources/session-sync.js +9 -6
  43. package/dist/resources/session-sync.js.map +1 -1
  44. package/dist/resources/sessions.d.ts +9 -3
  45. package/dist/resources/sessions.d.ts.map +1 -1
  46. package/dist/resources/sessions.js +9 -3
  47. package/dist/resources/sessions.js.map +1 -1
  48. package/dist/resources/tasks.d.ts +7 -1
  49. package/dist/resources/tasks.d.ts.map +1 -1
  50. package/dist/resources/tasks.js +7 -1
  51. package/dist/resources/tasks.js.map +1 -1
  52. package/dist/resources/tool-approvals.d.ts +17 -3
  53. package/dist/resources/tool-approvals.d.ts.map +1 -1
  54. package/dist/resources/tool-approvals.js +4 -0
  55. package/dist/resources/tool-approvals.js.map +1 -1
  56. package/dist/resources/workflows.d.ts +5 -2
  57. package/dist/resources/workflows.d.ts.map +1 -1
  58. package/dist/resources/workflows.js +5 -2
  59. package/dist/resources/workflows.js.map +1 -1
  60. package/dist/settings.d.ts +7 -3
  61. package/dist/settings.d.ts.map +1 -1
  62. package/dist/sync.d.ts +19 -2
  63. package/dist/sync.d.ts.map +1 -1
  64. package/dist/sync.js +88 -2
  65. package/dist/sync.js.map +1 -1
  66. package/dist/types.d.ts +160 -19
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/types.js.map +1 -1
  69. package/openapi.yaml +318 -63
  70. package/package.json +1 -1
package/dist/types.d.ts CHANGED
@@ -309,8 +309,19 @@ export interface TaskRequest {
309
309
  * {@link import("./settings.js").SemaSettings.skillListingMaxDescChars} 两只旋钮。
310
310
  *
311
311
  * Merge: scenario WINS on name collision (user's dropped + warn-logged) — the safety baseline can't be
312
- * overridden. Injected by the trusted BFF, never raw user input. */
312
+ * overridden. Injected by the trusted BFF, never raw user input.
313
+ *
314
+ * 🔴 **server ≥7.116.0:每只技能可带 `allowedTools` / `disallowedTools`(本 run 的 allow / deny 规则来源,不是围栏 —— 读法与比 `settings.permissions.allow` 宽的口径见
315
+ * {@link SkillSpec.allowedTools};探测位 `capabilities.skillToolLists`),技能的 `manifest` 键提交即 400**(core 7.41.0 退役;`manifest.allowTools` 改写成 `allowedTools`)。 */
313
316
  skills?: SkillSpec[];
317
+ /** server ≥7.116.0(core 7.41.0 #1303):**人用名字点过的技能**(壳从人敲的 `/name` 解析出来的,按 {@link SkillSpec.name})—— 非空串数组。这些技能的
318
+ * `allowedTools` / `disallowedTools` **开跑即生效、不出 `Skill` 卡**(人自己点的名就是那句表态);**只管这一次** run(steer 不终止它,下一次提交不带)。
319
+ * 每个名字必须是这一 run 装着的技能(场景出厂 ∪ 本请求 `skills`),否则引擎拒启 **400 `config.user_invoked_skill_unknown`**(同步腿 `POST /v1/tasks`;
320
+ * 异步 / 活流腿 HTTP 2xx、同码落在终态 run 行);`disableSkills: true` 时点任何名字都是这个码。值形坏(裸串 / 含空串 / 含非串 / 对象 / null)⇒ 400
321
+ * `request.field_invalid`。不投递技能正文(正文照旧由 `Skill` 工具 / 调用方负责)。
322
+ * 🔴 **先探 `capabilities.userInvokedSkills`**(恒真):位缺席 = 老 server ⇒ **别发这个键**(≤7.115.x 答 400 `request.body_shape`,`unknownKeys` 逐字列名)。
323
+ * 清单的读法见 {@link SkillSpec.allowedTools}(比同版 `settings.permissions.allow` 宽;托管 / 多租户部署不设开关)。 */
324
+ userInvokedSkills?: string[];
314
325
  /** Per-turn reasoning strength (CC `/effort` parity). One of the core ThinkingLevel tiers:
315
326
  * `off`|`minimal`|`low`|`medium`|`high`|`xhigh`|`max`. Service maps it → `TaskSpec.thinking`
316
327
  * (server.ts reasoningEffort → main.ts:1270); an UNKNOWN value is a 400 (fail-loud). Omit ⇒ engine
@@ -901,12 +912,20 @@ export interface TaskAgentDefinition {
901
912
  allowTools?: string[];
902
913
  /** Denylist of tool names (subtractive; applied after `allowTools`). */
903
914
  denyTools?: string[];
904
- /** Skills preloaded into the agent: `{ name, description, content }` (+ optional manifest/files). */
915
+ /** 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 是未知键整条拒)。 */
905
917
  skills?: Array<{
906
918
  name: string;
907
919
  description: string;
908
920
  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 别再发。 */
909
926
  manifest?: Record<string, unknown>;
927
+ allowedTools?: string[];
928
+ disallowedTools?: string[];
910
929
  files?: Array<{
911
930
  path: string;
912
931
  content: string;
@@ -2073,7 +2092,17 @@ export interface RunRecord {
2073
2092
  result?: TaskResult | LegacyPlaneTaskResult;
2074
2093
  /** 本**行的列**,7.64.0 未变(照旧说五词);只是数据源改成从 `result.terminal` 投影一次(旧行则直接读平面键)。
2075
2094
  * ⚠️ K-24 / S-173(server ≥7.104.0):`needs_review` park 行上本位 = core 的规范码 **`review.pending`**(此前缺席)——
2076
- * **禁**把「本位在场」读成失败,先读 `status`。`suspended` park 行缺席。 */
2095
+ * **禁**把「本位在场」读成失败,先读 `status`。`suspended` park 行缺席。
2096
+ *
2097
+ * 🔴 **server ≥7.116.0 多三种取值(additive 读面;S-1099)**:run 店自己判的终局此前只在 `error` 句子里,现在同时带机读码 ——
2098
+ * **`run.stalled`**(失联收割:心跳旧于 `REAP_RUN_STALE_SEC` 的 `running` 行被收割;读面在收割落盘前提前折叠的那一形同码;句子 `run stalled (instance lost?)`)·
2099
+ * **`run.orphaned`**(local 车道重启回收 / 会话占用接管回收;句子 `run orphaned by engine restart`)·
2100
+ * **`approval.expired`**(审批过期收割:耐久审批停驻的 run 过期被收割;行上码列早就有,读面此前不投;句子 `approval expired before decision`)。句子照旧。
2101
+ * 这三码都**不是请求写错**,重试同一请求无意义,重新提交才有新 run;按 `error` 句子判「持有者没了」的消费端改按本码判;把「`errorCode` 在场」读成「core 报了错」的消费端
2102
+ * **先读 `status`**(`failed`)再按码分支。本位**仍是开集串**(词表属主在 server / core,分支永远带 `default`),没有闭集可加。
2103
+ * 🔴 **缺席语义(旧行)**:升级前(≤7.115.x)写下的死亡判决行只有 `error` 句子、码列为空 —— 7.116.0 每次起服做**一次性迁移补码**(`one_time_migrations_applied` 的
2104
+ * `holderDeathCodeRowsBackfilled`),SQL 后端的新副本读这种行时同样读成码(升级窗);**但迁移有窗**(发布日 + 30 天之后的第一个小版本把写回与读侧一起删),
2105
+ * 删后仍只有句子的行不再带码、`errorCode` 缺席 —— 所以「本位缺席 ≠ 不是持有者死亡」,**旧行迁移补码之后仍可能无码**,别拿缺席反推别的。 */
2077
2106
  errorCode?: string;
2078
2107
  error?: string;
2079
2108
  /** Work-view correlation. Present when the run has a jobId (omitted when null). LIVE server-side
@@ -2370,14 +2399,20 @@ export type DeniedBy = "policy" | "hook" | "org" | "persisted_rule" | "classifie
2370
2399
  */
2371
2400
  export type PermissionMode = "default" | "acceptEdits" | "plan" | "auto" | "bypassPermissions" | "dontAsk";
2372
2401
  /**
2373
- * 一只问**属于哪一类**(core `ASK_CLASSES`:7.34.0 铸二十词,core 7.39.0 起 `shell_floor` 入册 ⇒ 二十一词,core 7.40.0 起 `unstated` 入册 ⇒ **二十二词**;模式 × 类仲裁表的列)。K-32 扩项 / server ≥7.106.0 起出现在
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 起出现在
2374
2403
  * {@link ModeRelease.askClass} / `.classes` 与 deny 臂的 `askClass` / `classes` 上,以及通告 `permission.ask_released_by_mode` 的 detail 里;
2375
2404
  * K-37 扩项 / server ≥7.109.0(S-934 ②)起也在审批面:活卡帧 / 卡面 / 运维队列行 / `/stream` `pending` 帧的 `askClass` / `classes`
2376
2405
  * (同样经 core `isAskClass` 筛,读不出整对不投;见 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.askClass})。
2377
2406
  * 🔴 **门记录这一面是真闭集**(server 按 core `isAskClass` 筛,出集整条不上帧)。`bypassPermissions` 只放行其中**可放**的十类
2378
2407
  * (core `RELEASABLE_ASK_CLASSES`:`transcript_write` / `rule_unreadable` / `probe` / `write_protection` / `tool_marks_mcp` / `tool_marks_a2a` /
2379
2408
  * `artifact_shared_read` / `mode` / `unstated` / `ordinary`);其余(`operator_forced` 部署出身、`ask_rule` / `org_rule`、`hook`、`ancestor`、`content_question`、
2380
- * `unverifiable_delete`、`governance_unavailable`、`policy_rra` …)任何模式下都照问。
2409
+ * `unverifiable_delete`、`governance_unavailable`、`policy_rra`、`requires_user_interaction` …)任何模式下都照问。
2410
+ *
2411
+ * 🔴 **`requires_user_interaction`(core 7.41.0;server ≥7.116.0 提货)= 服务器声明「这只工具每次都要用户在场」**:MCP 服务器在工具申报里声明
2412
+ * `_meta["anthropic/requiresUserInteraction"] === true`(只认布尔 `true`)⇒ 这只工具的**每一次**调用都问人 —— **每种模式含 `bypassPermissions`** 都问(**不在**可放十类里),
2413
+ * 且**只有人的答**清得掉:请求 `settings.permissions.allow`、运维 `APPROVAL_GRANT`、技能清单 + `userInvokedSkills`、PreToolUse hook 的显式 allow 都清不掉它;
2414
+ * 无审批席 ⇒ 拒(服务器侧零收到)、无人值守腿不答这一类;帧上同带 `requiresRealApproval:true` / `mandated:true`(`origin:"safety_tighten"`),卡上没有「不再询问」规则。
2415
+ * 按 `askClass` 穷举渲卡的客户端要加这一个词;本型是闭集(server 对 `askClass` / `classes` 按 core `isAskClass` 筛,出集整对不投)。
2381
2416
  *
2382
2417
  * 🔴 **`unstated`(core 7.40.0;server ≥7.115.0 提货)= 没人表态的调用**:询问类模式(`default` / `acceptEdits` / `auto` / `plan`)下,MCP 服务器工具 / A2A 技能(引擎里「自己不表态权限」的席位)的调用,
2383
2418
  * 走到折叠尾**没有任何一层**(规则 / hook / 审批人 / 分类器 / 模式释放)说过「这次可以」⇒ 出一张 `askClass: "unstated"` 的卡(卡句 `The agent requested permission to use <tool>, but it has not been granted yet.`);
@@ -2385,7 +2420,9 @@ export type PermissionMode = "default" | "acceptEdits" | "plan" | "auto" | "bypa
2385
2420
  * 先探 `capabilities.settings.permissions.allowGrant`)· 运维 env `APPROVAL_GRANT` · PreToolUse hook 显式 `permissionDecision:"allow"` · 接审批面 · `permissionMode:"bypassPermissions"`(请求腿);
2386
2421
  * `plan` 模式下只有**只读**的服务器工具出这张卡。本类说的是「**没人说**」,不是 `ask_rule` / `org_rule` 那种「有人说了问」。
2387
2422
  */
2388
- export type AskClass = "content_question" | "hook" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback" | "operator_forced"
2423
+ export type AskClass = "content_question" | "hook" | "ancestor" | "unverifiable_delete" | "transcript_write" | "org_rule" | "governance_unavailable" | "rule_unreadable" | "ask_rule" | "denial_limit_fallback"
2424
+ /** core 7.41.0 / server ≥7.116.0:服务器工具申报声明「每次调用都要用户在场」(见本型顶注)—— **不在** `bypassPermissions` 可放的十类里,只有人的答清得掉。 */
2425
+ | "requires_user_interaction" | "operator_forced"
2389
2426
  /** core 7.39.0(#1260;server ≥7.113.0 提货):运维旋钮 `shellGate: "always"` 在**跑 shell 的席位**上的地板 —— `operator_always` 授权词所披露的那一问,
2390
2427
  * 自己成一类,免得持有另一种强制问的类集把它藏掉。与 `operator_forced` 同样**免疫 bypass**(不在 `bypassPermissions` 可放的十类里)。 */
2391
2428
  | "shell_floor" | "write_protection_unresolved" | "probe" | "write_protection" | "tool_marks_mcp" | "tool_marks_a2a" | "policy_rra" | "artifact_shared_read" | "mode"
@@ -3208,6 +3245,25 @@ export interface SkillSpec {
3208
3245
  name: string;
3209
3246
  description: string;
3210
3247
  content: string;
3248
+ /** server ≥7.116.0(core 7.41.0 技能清单取上游全形):这只技能的**allow 规则来源**(字符串数组;条目文法 = 持久规则文法 ——
3249
+ * 工具名、`mcp__<server>` / `mcp__<server>__*` 一类协议名;`*` / 写路径 / 域名形什么都不授予)。
3250
+ * 🔴 **读法变了:它不是围栏**(≤7.115.x 引擎 7.40 把它当「只许这些」的围栏读)—— 7.116.0 起**没列的工具照常判**(询问类模式下问、
3251
+ * `bypassPermissions` 或部署 allow 下直接跑),不再因为没列被拒;**列着的工具在这只技能被激活之后、本 run 内免问**
3252
+ * (激活 = 请求顶层 {@link TaskRequest.userInvokedSkills} 点了它的名〔开跑即生效、不出 `Skill` 卡〕,或模型调 `Skill` 激活且那张卡被批准)。
3253
+ * 清的是引擎的普通问与「没人表态」两类问,所以**比同版 `settings.permissions.allow` 更宽**(后者仍只是表态,不放内置工具上引擎自己的
3254
+ * 写门 / shell 普通问);deny 规则 / ask 规则 / `APPROVAL_REQUIRE` / `APPROVAL_NEVER_AUTO` / shell 地板 / 写保护 / plan 模式的问,清单都清不掉。
3255
+ * 值形:字符串数组(含空数组)⇒ 受理;裸串 / 含非串 / 对象 ⇒ 400 `request.field_invalid`;协议名的服务器段铸不出 / 缺段 / 带通配(`mcp__*`)⇒ 400
3256
+ * (顶层 `skills[]` 与子代 `agents[].skills[]` 两处受理口同判)。
3257
+ * 🔴 **先探 `capabilities.skillToolLists`**:位缺席 = 老 server ⇒ 顶层技能上的两只清单**照收但引擎不读**(静默不生效,没有 400 可探 ——
3258
+ * 别指望清单拦得住工具,圈工具用 deny 规则),子代技能上是未知键整条拒。
3259
+ * 🔴 `manifest` 键 server ≥7.116.0 **提交即拒**(顶层 400 `request.field_invalid`、子代整条技能拒);改写 `manifest.allowTools` → 本键;
3260
+ * 写围栏 `allowPaths` 没有替身(圈写路径用会话规则 `allowDirs`)。本型从不声明 `manifest` ⇒ 顶层按型写不出它。 */
3261
+ allowedTools?: string[];
3262
+ /** 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})。 */
3266
+ disallowedTools?: string[];
3211
3267
  }
3212
3268
  /** A per-request MCP server (CC `.mcp.json` parity) — core-native `McpServerSpec` shape (core types.ts:277).
3213
3269
  * `stdio` = a local command the worker spawns (single-user only); `http` = a remote streamable-HTTP server. */
@@ -3379,15 +3435,18 @@ export interface Capabilities {
3379
3435
  /** #13([1871] web asks;server ≥1.296)fleet 面能力族——对象=面在场,`false`/缺席=无 /v1/fleet/stream
3380
3436
  * (路由 501 同谓词)。`resume: "snapshot"` 是语义广告:总线是 latest-state 非事件日志,每次连接开头
3381
3437
  * 即全量 snapshot 帧 ⇒ 重连=重快照,行状态无丢帧(刻意无 last-event-id 游标——重放缓冲与 snapshot
3382
- * 重复建设);通知帧走 durable inbox 兜底重投。`steerPriority: "advisory"`=steer body.priority 收下+
3383
- * 枚举校验但 no-op(E15,候 core 队列 seam)——诚实不假 yes。开集容未来键。 */
3438
+ * 重复建设);通知帧走 durable inbox 兜底重投。`steerPriority` 答「steer body.priority 在这台 server 上生不生效」,
3439
+ * **两代值**:`steerPriority: "advisory"`(server ≤7.115.x)= 收下 + 枚举校验 + 回显但**不生效**(no-op,诚实不假 yes);
3440
+ * `steerPriority: "engine"`(server ≥7.116.0)= `priority`(`now` / `next` / `later`)交给引擎作注入档位,各档语义只有
3441
+ * 引擎那一个定义 —— `now` **当场**切断在飞的 turn(正在执行的工具收到中止、本副本上挂着的审批卡被撤),`later` 在 run 本会停下的那一 turn 之后才投,不带 = `next`。要不要给用户露出 priority 的选择,先读这一位;
3442
+ * 缺席 / 未知词(开集)⇒ 按「不生效」处理,别当 `"engine"`。开集容未来键。 */
3384
3443
  fleet?: false | {
3385
3444
  stream?: boolean;
3386
3445
  sessionScope?: boolean;
3387
3446
  observe?: boolean;
3388
3447
  resume?: "snapshot" | (string & {});
3389
3448
  bgNotifyFailClosed?: boolean;
3390
- steerPriority?: "advisory" | (string & {});
3449
+ steerPriority?: "advisory" | "engine" | (string & {});
3391
3450
  /** server ≥7.48.0(#281;K-32 扩项补声明 —— server 7.106.0 的复合位成员闭集 `COMPOSITE_CAPABILITY_MEMBERS` 登记了它,本包此前漏了):
3392
3451
  * 本二进制会在 `hook_notice` 帧上发**第二个** kind `hook_non_blocking_failure`(用户自配的 hook 自己坏了:exit ≠ 0 ∧ ≠ 2 / 超时 /
3393
3452
  * 起不来 / 坏 JSON)。缺席 = 老 worker 只发得出 `hook_decision_unavailable` 一个 kind ⇒ 渲染面按 `kind` 分派、未知 kind 别崩。 */
@@ -3441,7 +3500,8 @@ export interface Capabilities {
3441
3500
  /** S-32(server ≥7.53,`routes/capabilities.ts:731`)—— `GET /v1/config/catalog` operator lane(部署配置目录
3442
3501
  * 自描述,DESIGN-278 §5 S2)在**本部署**挂载。谓词**两项合取**,逐项对着路由拒绝臂写:①旋钮
3443
3502
  * `CONFIG_CATALOG_ENABLED` 开着(默认 on;合规部署显式关 ⇒ 路径 404,阀门族先例)∧ ②operator 名单**非空**
3444
- * (空名单下路由对任何身份恒 403)。
3503
+ * (空名单下路由对任何身份恒拒 —— server ≥7.116.0 答 **501 `capability.operator_principals_required`**,≤7.115.x 答 403)。
3504
+ * 🔴 server ≥7.116.0 旋钮关着(`CONFIG_CATALOG_ENABLED=false`)时路径答 **501 `feature.config_catalog_disabled`**(≤7.115.x:404;同路径 `POST` ⇒ 405 + `Allow: GET`)—— 「这台没有」按 `errorCode` 判。
3445
3505
  * 🔴 **部署级可用性,不是调用者授权**(codex R1 验真后订正):调用者自己的身份**不在**谓词里 —— 路由另要求
3446
3506
  * 当前 principal 是显式 operator(`routes/config-catalog.ts` `explicitOperatorOk`,否则 403 `auth.operator_only`),
3447
3507
  * 非 operator 读到 `true` 照样 403。只对**已另行确立**为 operator 的身份展示/调用目录;本位回答的是「这台机
@@ -3535,8 +3595,21 @@ export interface Capabilities {
3535
3595
  * `beginImportStaging` ∧ a file-snapshot store. 🔴 The fourth conjunct is the correction: this doc used to
3536
3596
  * list only three, and that three-item version was DISPROVEN in the field ([2024], cli 取证) — a warm-cache
3537
3597
  * wrapper store forwarded exactly those three and dropped the staging family, so caps said `true` while PUSH
3538
- * Phase A 501'd forever. Gate the whole `client.sessions.sync.*` surface off this — DON'T trial-by-501. */
3598
+ * Phase A 501'd forever. Gate the whole `client.sessions.sync.*` surface off this — DON'T trial-by-501.
3599
+ *
3600
+ * 🔴 **server ≥7.116.0:本位说的是「对话半族」**(manifest / entries / plan / import 两段)—— 文件历史的 **blob 两口**(`PUT …/sync/blobs/:hash` /
3601
+ * `GET …/sync/history/blobs/:hash`)归新位 {@link sessionSyncFileHistory}。三种生产后端(mysql / pg / local)上本位**值不变**,变的是广告的端点收窄;
3602
+ * 判据另加「策略店擦得动」(`deleteBySession`;嵌入方自带的策略店缺这只动词 ⇒ 整族 501 `capability.policy_purge_required`、本位为 `false`,
3603
+ * 7.115.x 只有 consented `overwrite-dst` 的导入在 commit 前答 501)。 */
3539
3604
  sessionSync?: boolean;
3605
+ /** server ≥7.116.0(S-509,契约附录 B.1,谓词类「设施依赖」):**会话同步的文件历史 blob 面**可用 —— `PUT /v1/sessions/:id/sync/blobs/:hash` 与
3606
+ * `GET /v1/sessions/:id/sync/history/blobs/:hash` 两口。= {@link sessionSync} ∧ 文件历史店有 blob 传输面(`syncBlobFaces`;**只有 SQL 后端有**,`DB_BACKEND=local` 上恒 `false`)。
3607
+ * 🔴 **两端都读**:同步是 src → dst 两个 peer,**任一端为 `false` ⇒ 只同步对话**:别推 `fileHistory`、别 PUT blob(把 `fileHistory` 推给没有 blob 面的对端,
3608
+ * commit 之后因缺 blob 422 `missing_blob`)。位为 `false` 时两口答 **501 `capability.snapshot_store_required`**(任何会话 id 同一句,先于属主判);
3609
+ * 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})。 */
3612
+ sessionSyncFileHistory?: boolean;
3540
3613
  /** 🔴 K-5 session-resume gates(service src/http/routes/capabilities.ts,§0.5 session 抽象)—— shell 的 `/resume` picker 据此诚实
3541
3614
  * gate,别 trial-by-501:`sessionList` = list 可用(`Boolean(sessionStorage.listSessions ?? runStore.listSessions)`,
3542
3615
  * 喂 picker 行);`sessions` = transcript preview 可用(`Boolean(sessionAudit)`,`GET /v1/sessions/:id`→SessionAudit)。
@@ -3762,8 +3835,15 @@ export interface Capabilities {
3762
3835
  s3PublicEndpoint?: string | null;
3763
3836
  /** GET /v1/files/sent 台账面(`routes/capabilities.ts` 的能力对象 `Boolean(sendFileLedger)`)。 */
3764
3837
  sendUserFileLedger?: boolean;
3765
- /** GET /v1/workflows 列表面(`routes/capabilities.ts` 的能力对象 `Boolean(workflowRunStore)`;`workflows` 总位见上)。 */
3838
+ /** GET /v1/workflows 的**列表 / 详情 / 流三口**(`Boolean(workflowRunStore)`;`workflows` 总位见上)。
3839
+ * 🔴 **server ≥7.116.0:本位只说这三口,journal 口看新位 {@link workflowsJournal}**(7.115.x 的本位广告 journal 口,而 journal 店缺席时那一口恒 501 —— 位说「能」而口恒拒)。
3840
+ * 本位**值不变**(= workflow 行店在场)。 */
3766
3841
  workflowsList?: boolean;
3842
+ /** server ≥7.116.0(S-509,谓词类「设施依赖」):`GET /v1/workflows/:id/journal` 可用 = workflow 行店 ∧ journal 店。
3843
+ * 无后端部署(`DB_BACKEND=memory`、多租户裸起、SQL 坐标没配齐)+ 自编排开着的形上 `workflowsList: true`、本位 `false`;位为 `false` 时 journal 口答
3844
+ * **501 `capability.workflow_store_required`**(对任何 id 同一句,先于按行判属主;行店缺席时是 `capability.self_orchestration_required`)。
3845
+ * 🔴 **journal 入口读本位,别读 `workflowsList`**;**缺席 = 老 server(≤7.115.x)**⇒ 按 `workflowsList` 兜底(= 旧行为:位为真而 journal 口可能恒 501)。 */
3846
+ workflowsJournal?: boolean;
3767
3847
  /** device lane 探测位(server `routes/capabilities.ts:162`;design/device-executor-lane-v2 §4.8)——
3768
3848
  * **一个诚实对象或 `false`**,与 {@link fleet} / {@link workspace} 同族三态形。谓词 = `deps.deviceHub`
3769
3849
  * 在场,而那正是 `GET /v1/device/ws` 的 upgrade 处理器挂没挂的**同一个**判据(`server.ts` 的
@@ -3925,13 +4005,14 @@ export interface Capabilities {
3925
4005
  * **例外**是配置被 lock 时,提交口 400 `config.locked_key`(那条 veto 正是让「说 yes ⟺ 路真能用」
3926
4006
  * 在这一形上仍成立的东西)。 */
3927
4007
  a2aInjection?: boolean;
3928
- /** server-as-peer 半场的**旋钮实况**(server `routes/capabilities.ts:564` =
3929
- * `deps.config.a2aServe !== undefined`;DESIGN-269 车2)—— 这台 worker 是否作为一个 A2A agent 对外存在。
3930
- * `true` ⟺ `A2A_SERVE_ENABLED` 开 ⟺ `GET /.well-known/agent-card.json` 与 `POST /v1/a2a` 两条路由存在;
3931
- * `false` ⟺ 两条都 **404**(设计稿 §3.3「卡都不发 = 对外不存在」)。缺席即关。
3932
- * ⚠️ **辖域 = 路由在不在,不是「每个方法都能跑」**:`message/send` / `tasks/get` 还需要 durable run store
3933
- * (缺它时两个方法回具名 JSON-RPC `-32004`,不是静默降级)。server 刻意不把 runStore 折进本位 ——
3934
- * 那会造出「卡还在发、位却是 false」这种更糟的谎。 */
4008
+ /** server-as-peer 半场的**能否对外存在**(DESIGN-269 车2;server ≥7.116.0 谓词 = **`A2A_SERVE_ENABLED` 旋钮 ∧ 有 durable run store**,契约附录 B.1「设施 + config」;
4009
+ * ≤7.115.x 只看旋钮 = `deps.config.a2aServe !== undefined`)—— 这台 worker 是否作为一个 A2A agent 对外存在。
4010
+ * `true` ⟺ 旋钮开 ∧ 有 run 店 ⟺ `GET /.well-known/agent-card.json` 与 `POST /v1/a2a` 两条路由存在;
4011
+ * `false` ⟺ 两条都 **404**(`not_found.route`,反指纹:「卡都不发 = 对外不存在」,**唯一**登记在 404 而非 501 的「不可用」例外)。缺席即关。
4012
+ * 🔴 **7.116.0 的位值变化**:`A2A_SERVE_ENABLED=true` 而**没有 durable run store** 的部署(`DB_BACKEND=memory`、多租户裸起)上,本位由 `true` 变 `false`
4013
+ * —— 那里它广告的两条路由本来就恒拒(7.115.x:卡照发 200,`message/send` / `tasks/get` 恒答 JSON-RPC `-32004`);现在卡与 RPC 都 404,起服日志一行 warn
4014
+ * `a2a_serve_not_served`(`reason` 点名成因)。对端 orchestrator 对这种部署拉卡由 200 变 404(与旋钮关同一形)。出路:`DB_BACKEND=mysql|pg|local`,或关掉 `A2A_SERVE_ENABLED`。
4015
+ * 旧注「server 刻意不把 runStore 折进本位」**作废**(位与路由门现读同一只事实,「位说有而端点恒拒」结构上不可能)。 */
3935
4016
  a2aServe?: boolean;
3936
4017
  /** 后台 agent **名册读面** `GET /v1/agents/roster` 的位(server `routes/capabilities.ts:640` =
3937
4018
  * `Boolean(deps.backgroundAgentStore)`;#A1)。谓词**逐字**是那条路由的 501 门 ⇒「说 yes ⟺ 路由真能用」
@@ -4113,6 +4194,14 @@ export interface Capabilities {
4113
4194
  * ⚠️ **缺席 = 老 server(≤7.108.x)**:那台对请求键答 400 `request.body_shape`(`unknownKeys` 逐字列名)⇒ 别发那个键,如实告诉用户
4114
4195
  * 「这台 server 上出厂技能照装」(CC `--disable-slash-commands` 在那台上兑现不了)。位为真**只**说「认这个键」,不说这台部署有没有出厂技能。 */
4115
4196
  disableSkills?: boolean;
4197
+ /** **请求键 {@link TaskRequest.userInvokedSkills} 的事先读数**(server ≥7.116.0;恒真位,铸点字面 `userInvokedSkills: true`,不挂谓词、无租户门)—— 这台 server 认不认
4198
+ * 顶层 `userInvokedSkills`(人用名字点过的技能,开跑即生效、不出 `Skill` 卡)。位名与请求键**同一个词**。
4199
+ * ⚠️ **缺席 = 老 server(≤7.115.x)**:那台对这个键答 400 `request.body_shape`(`unknownKeys` 逐字列名)⇒ **别发那个键**。位为真**只**说「认这个键」。 */
4200
+ userInvokedSkills?: boolean;
4201
+ /** **技能两只清单 `allowedTools` / `disallowedTools` 的事先读数**(server ≥7.116.0;恒真位):技能上的两只清单**生效**(allow / deny 规则来源,读法见 {@link SkillSpec.allowedTools})。
4202
+ * ⚠️ **缺席 = 老 server(≤7.115.x)**:顶层技能上的两只清单**照收但引擎不读**(静默不生效,**没有 400 可探**)—— 别指望清单拦得住工具,圈工具用 deny 规则
4203
+ * (请求 `settings.permissions.deny`);子代技能(`agents[].skills[]`)上两只清单是未知键 ⇒ 整条技能拒。 */
4204
+ skillToolLists?: boolean;
4116
4205
  [k: string]: unknown;
4117
4206
  }
4118
4207
  /**
@@ -4333,6 +4422,9 @@ export interface LivePendingRow {
4333
4422
  sessionId?: string;
4334
4423
  requiresRealApproval?: true;
4335
4424
  governanceForced?: true;
4425
+ /** server ≥7.116.0:这张卡上「本会话放行」不会被记住(真才带、永不 `false`;缺席 = 记得住 **或** 老 server)。与 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.rememberRefused}
4426
+ * **同一位**(`livePending` 行顶层与其内 {@link frame} 同投)。 */
4427
+ rememberRefused?: true;
4336
4428
  /** server ≥7.101.0(T4① / 车OC;sdk 11.4.0 追平)—— 强制位(`AskRequest.mandated`),与上两位**同层同形**(真才带,
4337
4429
  * 缺席不编 false);值 = 条目上那一位(server `askBroadcast` 铸条目时取自这一次过闸的 `req.mandated`,与 {@link frame}
4338
4430
  * 上同名键同源)。此前只在 `frame` 里。 */
@@ -4447,6 +4539,9 @@ export interface PendingCheckpoint {
4447
4539
  * 以 stream 重发帧为准。additive,**只在为真时在场**,恒不写 false;缺席 ≠「非治理门」,是「无治理
4448
4540
  * 来源证据」。 */
4449
4541
  governanceForced?: true;
4542
+ /** server ≥7.116.0:这张卡上「本会话放行」不会被记住(真才带、永不 `false`;缺席 = 记得住 **或** 老 server;`/v1/approvals` 的 `pending[]` 行与 `/stream` 的 `pending` 帧同投)。
4543
+ * 与 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.rememberRefused} **同一位**。 */
4544
+ rememberRefused?: true;
4450
4545
  /** server ≥7.100.0(S-700)—— 这只 park 住的 ask **只有真人能清**(core park 行孪生座,`=== true` 严判才铸)。
4451
4546
  * 与 inbox 行 / 活卡帧同名位同一件事。缺席 = 「没打这个标」,**不是**「不用人也能清」。 */
4452
4547
  requiresRealApproval?: true;
@@ -4951,6 +5046,39 @@ export interface SyncSnapshot {
4951
5046
  key: string;
4952
5047
  manifest: Array<[string, string]>;
4953
5048
  }
5049
+ /** core `FileHistoryExport`(`formatVersion: "file-history/1"`)的**镜像** —— server ≥7.52(S-15 / design/381)起会话同步搬运文件历史的信封,**取代**已退役的 E19 整树快照
5050
+ * {@link SyncSnapshot}:per-edited-file 的版本链(tracked)+ 边界(boundaries);**blob 字节不在信封里**(按 hash 寻址,经 history blob 两口搬运,见
5051
+ * {@link import("./resources/session-sync.js").SessionSyncResource.getHistoryBlob} / `putBlob`)。SDK 只读 `tracked[].versions[].blobHash`(决定要搬哪些 blob),其余**逐字透传**
5052
+ * (server 的 import 门按 `formatVersion` refuse-not-coerce、复核 `keyKind` / `keyFamily` 闭集 —— SDK 不替它判,也不复制那两张闭集词表:二者按 `string` 读)。
5053
+ * 键集对拍 core `dist/core/file-history-store.d.ts` 的 `FileHistoryExport`。 */
5054
+ export interface FileHistoryExport {
5055
+ /** 今天唯一值 `"file-history/1"`;server 对别的值拒(不是 SDK 的判)。 */
5056
+ formatVersion: string;
5057
+ tracked: Array<{
5058
+ /** 任务根下捕获 ⇒ 相对路径,否则逐字绝对路径。 */
5059
+ relOrAbsPath: string;
5060
+ /** 键的自描述(core 闭集;本包不复制词表)。 */
5061
+ keyKind: string;
5062
+ keyFamily: string;
5063
+ /** `false` ⇒ pristine base 没能捕获(链从 v1 之上起);随图走、不推断。 */
5064
+ baseAvailable: boolean;
5065
+ /** 完整保留链(v1 在先当且仅当 `baseAvailable`)。`blobHash: null` = 「当时不存在」标记(不用搬 blob)。 */
5066
+ versions: Array<{
5067
+ version: number;
5068
+ blobHash: string | null;
5069
+ mode?: number;
5070
+ parentIdent?: string;
5071
+ backupTime: string;
5072
+ }>;
5073
+ }>;
5074
+ boundaries: Array<{
5075
+ entryId: string;
5076
+ files: Array<{
5077
+ relOrAbsPath: string;
5078
+ version: number;
5079
+ }>;
5080
+ }>;
5081
+ }
4954
5082
  /** One E18 resume-at anchor (eventId→entryId + its source owner). `owner` is RE-KEYED to the importing principal
4955
5083
  * on a PUSH (§9) — the local peer sends what it has; the cloud overwrites it. */
4956
5084
  export interface SyncAnchor {
@@ -4970,7 +5098,14 @@ export interface SessionManifest {
4970
5098
  entryCount: number;
4971
5099
  /** The session's current leaf entry id, or null. */
4972
5100
  leafId: string | null;
5101
+ /** 🔴 **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()` 的填充**。 */
4973
5105
  snapshots: SyncSnapshot[];
5106
+ /** server ≥7.52:per-edited-file 文件历史信封({@link FileHistoryExport});`null` = 没有历史 / 源店导不出;**键缺席 = ≤7.51 老 server**(那一代走 {@link snapshots})。
5107
+ * 搬 blob 前先读两端的 {@link Capabilities.sessionSyncFileHistory}(server ≥7.116.0)。 */
5108
+ fileHistory?: FileHistoryExport | null;
4974
5109
  policy: SessionRulesRecord[];
4975
5110
  anchors: SyncAnchor[];
4976
5111
  }
@@ -4982,6 +5117,8 @@ export interface SessionBundle {
4982
5117
  /** The FULL durable conversation log, verbatim ids/parents/payload (oldest-first). */
4983
5118
  entries: SyncEntry[];
4984
5119
  snapshots: SyncSnapshot[];
5120
+ /** 同 {@link SessionManifest.fileHistory}(server ≥7.52 的文件历史信封;键缺席 = 源是 ≤7.51 老 server)。 */
5121
+ fileHistory?: FileHistoryExport | null;
4985
5122
  policy: SessionRulesRecord[];
4986
5123
  anchors: SyncAnchor[];
4987
5124
  }
@@ -6168,6 +6305,9 @@ export interface ApprovalDecisionResult {
6168
6305
  errorCode?: string;
6169
6306
  errorMessage?: string;
6170
6307
  retriable?: boolean;
6308
+ /** 带 `remember` 的 `/decide` 才有的回执位。🔴 **server ≥7.116.0:在带授予的卡上(引擎 `Skill` 卡等,卡面位 `rememberRefused`)恒 `false`** —— 既有键,不是新键:
6309
+ * 决定照收、只放行这一次、豁免店零写;同一条件也使 {@link import("./resources/tool-approvals.js").ToolApprovalFrame.rememberRefused} 在场。
6310
+ * 普通卡上仍是「按请求记」(`true` ⇒ 之后同工具零卡)。 */
6171
6311
  rememberApplied?: boolean;
6172
6312
  /** #368 幂等回放形的判别式(同一份 decide 体重发、命中已决行);回放形**不带** `taskId`/`status:"resuming"`。 */
6173
6313
  idempotent?: true;
@@ -6219,6 +6359,7 @@ export interface ServerWiringGates {
6219
6359
  * **非空 ∨ `REQUIRE_PRINCIPAL`**:满足任一,调用方就必须是名单里的 principal,否则 403
6220
6360
  * `auth.operator_only`。**「没开 REQUIRE_PRINCIPAL」不等于开放** —— 列了名单的部署上匿名/非名单一样 403;
6221
6361
  * 唯一开放的姿势是空名单 ∧ 非多租户(单租户 turnkey,唯一的用户就是 operator)。
6362
+ * 🔴 server ≥7.116.0:**多租户形 + 空名单 ⇒ 501 `capability.operator_principals_required`**(对任何身份,先于授权;≤7.115.x 是 403)—— 按 `errorCode` 分支。
6222
6363
  *
6223
6364
  * 🔴 **不含 per-leg 历史**:治理段只出现在 live 帧的 operator 投影里,durable 账本恒存剥后形(账本写的
6224
6365
  * 那一刻不知道未来读者是谁)。要某条历史腿的治理面,只能在它跑的时候以 operator 身份订阅。