@sema-agent/sdk 12.0.1 → 13.1.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 (82) hide show
  1. package/README.md +109 -0
  2. package/dist/control-types.d.ts +2 -1
  3. package/dist/control-types.d.ts.map +1 -1
  4. package/dist/control-types.js.map +1 -1
  5. package/dist/errors.d.ts +121 -9
  6. package/dist/errors.d.ts.map +1 -1
  7. package/dist/errors.js +116 -14
  8. package/dist/errors.js.map +1 -1
  9. package/dist/events.d.ts +21 -1
  10. package/dist/events.d.ts.map +1 -1
  11. package/dist/events.js.map +1 -1
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +1 -1
  15. package/dist/index.js.map +1 -1
  16. package/dist/registry/client.d.ts +1 -0
  17. package/dist/registry/client.d.ts.map +1 -1
  18. package/dist/registry/client.js +3 -3
  19. package/dist/registry/client.js.map +1 -1
  20. package/dist/registry/errors.d.ts +27 -4
  21. package/dist/registry/errors.d.ts.map +1 -1
  22. package/dist/registry/errors.js +41 -1
  23. package/dist/registry/errors.js.map +1 -1
  24. package/dist/registry/index.d.ts +7 -1
  25. package/dist/registry/index.d.ts.map +1 -1
  26. package/dist/registry/index.js +7 -1
  27. package/dist/registry/index.js.map +1 -1
  28. package/dist/registry/me-config.d.ts +5 -2
  29. package/dist/registry/me-config.d.ts.map +1 -1
  30. package/dist/registry/me-config.js +21 -14
  31. package/dist/registry/me-config.js.map +1 -1
  32. package/dist/registry/scope-config-feedback.d.ts +6 -2
  33. package/dist/registry/scope-config-feedback.d.ts.map +1 -1
  34. package/dist/registry/scope-config-feedback.js +18 -9
  35. package/dist/registry/scope-config-feedback.js.map +1 -1
  36. package/dist/registry/scopes-effective.d.ts.map +1 -1
  37. package/dist/registry/scopes-effective.js +2 -3
  38. package/dist/registry/scopes-effective.js.map +1 -1
  39. package/dist/registry-conflict.d.ts +32 -0
  40. package/dist/registry-conflict.d.ts.map +1 -0
  41. package/dist/registry-conflict.js +37 -0
  42. package/dist/registry-conflict.js.map +1 -0
  43. package/dist/resources/control/config.d.ts +12 -6
  44. package/dist/resources/control/config.d.ts.map +1 -1
  45. package/dist/resources/control/config.js +10 -4
  46. package/dist/resources/control/config.js.map +1 -1
  47. package/dist/resources/control/versioning.d.ts +6 -2
  48. package/dist/resources/control/versioning.d.ts.map +1 -1
  49. package/dist/resources/control/versioning.js +4 -1
  50. package/dist/resources/control/versioning.js.map +1 -1
  51. package/dist/resources/runs.d.ts +2 -1
  52. package/dist/resources/runs.d.ts.map +1 -1
  53. package/dist/resources/runs.js +2 -1
  54. package/dist/resources/runs.js.map +1 -1
  55. package/dist/resources/session-sync.d.ts +9 -0
  56. package/dist/resources/session-sync.d.ts.map +1 -1
  57. package/dist/resources/session-sync.js.map +1 -1
  58. package/dist/resources/sessions.d.ts +11 -1
  59. package/dist/resources/sessions.d.ts.map +1 -1
  60. package/dist/resources/sessions.js +11 -1
  61. package/dist/resources/sessions.js.map +1 -1
  62. package/dist/resources/tasks.d.ts +18 -3
  63. package/dist/resources/tasks.d.ts.map +1 -1
  64. package/dist/resources/tasks.js +16 -1
  65. package/dist/resources/tasks.js.map +1 -1
  66. package/dist/resources/tool-approvals.d.ts +24 -2
  67. package/dist/resources/tool-approvals.d.ts.map +1 -1
  68. package/dist/resources/tool-approvals.js.map +1 -1
  69. package/dist/sse.d.ts.map +1 -1
  70. package/dist/sse.js +3 -0
  71. package/dist/sse.js.map +1 -1
  72. package/dist/transport.d.ts +20 -0
  73. package/dist/transport.d.ts.map +1 -1
  74. package/dist/transport.js +35 -3
  75. package/dist/transport.js.map +1 -1
  76. package/dist/types.d.ts +159 -32
  77. package/dist/types.d.ts.map +1 -1
  78. package/dist/types.js +22 -1
  79. package/dist/types.js.map +1 -1
  80. package/openapi.yaml +293 -31
  81. package/package.json +2 -2
  82. package/registry-openapi.yaml +17 -4
package/dist/types.d.ts CHANGED
@@ -61,18 +61,30 @@ import type { AskOrigin, ClassifierUnavailable, DenialLimitFallback, PersistedRu
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;
64
- /** The scenarios a stock `@sema-agent/server` ships today — the builtin table in its
65
- * `src/capabilities/scenarios.ts`, **five** names. `code` is the factory default ([891]); `default` is the
66
- * domain-neutral assistant face; `scan` is the neutral read-only repo lane; `code-review` / `team` are the
67
- * multi-lens and round-table lanes.
68
- * 🔴 Two RETIRED names are deliberately NOT here, and neither left a transition alias:
64
+ /** Builtin scenarios of a stock `@sema-agent/server` that this SDK offers as known names — **four**, all in the table its
65
+ * `buildScenarios()` returns (`src/capabilities/scenarios.ts`). `code` is the factory default ([891]); `default` is the
66
+ * domain-neutral assistant face; `scan` is the neutral read-only repo lane; `code-review` is the multi-lens review lane.
67
+ * ⚠️ The server's table has ONE more name today, `discuss` (the multi-agent discussion round-table), and it is still
68
+ * accepted — it is deliberately NOT listed here: it sits inside core #1056's (7.35.0) retirement sweep (server S-630 ②), and
69
+ * listing it now only to delete it at 7.35.0 would be two hard breaking changes on one type surface. Its fate is decided
70
+ * by that wave, and this list changes once, then. (`Scenario` is open, so `scenario: "discuss"` compiles today.)
71
+ * 🔴 CHECKED AGAINST THE SERVER, not hand-kept (K-20): `test/scenario-capabilities.test.ts` ① reads the builtin table out of
72
+ * the PUBLISHED `@sema-agent/server` bytes (devDep dist; `SEMA_SERVER_SRC=` reads an unpublished checkout) and requires it
73
+ * to equal this list plus the one closed, dated hold-out (`SCENARIO_SERVER_ONLY_PENDING` in `test/_keyset-divergence.ts`) —
74
+ * a server rename or retirement turns that cell red on the next pin bump.
75
+ * 🔴 Three RETIRED names are deliberately NOT here, and none left a transition alias:
69
76
  * - `oa` — server 5.0.0 deleted it whole ([2354]; its `OA_*` env names are now boot-refusing tombstones).
70
77
  * - `autonomous` — retired by [2400] CAPS-OPS-11 (clay 2026-08-03, 不留任何过渡). It used to be `code` with
71
78
  * finalVerification pinned on; final verification is now a pure caller-side knob, so the migration shape is
72
- * `scenario:"code"` + `body.finalVerification:true`. Sending `scenario:"autonomous"` to a ≥5.1.0 server is a
73
- * LOUD typed 400 `scenario_unknown` (the response carries the deployment's live vocabulary), not a silent
74
- * fold to `default`. */
75
- export type KnownScenario = "code" | "default" | "code-review" | "scan" | "team";
79
+ * `scenario:"code"` + `body.finalVerification:true`.
80
+ * - `team` — renamed `discuss` (server #273 / C-R14), and the old name's alias was withdrawn (#342), so a server
81
+ * answers it 400 today. Removed here in K-20. (The discuss scenario's body key `team`, which picks the roster
82
+ * template, kept its historical name — that is a request key, not this union.)
83
+ * Sending a retired name to a ≥5.1.0 server is a LOUD typed 400 `scenario_unknown` (the response carries the
84
+ * deployment's live vocabulary), not a silent fold to `default`. */
85
+ export declare const KNOWN_SCENARIOS: readonly ["code", "default", "code-review", "scan"];
86
+ /** One of {@link KNOWN_SCENARIOS} — derived from the value (one list, no second hand-written union). */
87
+ export type KnownScenario = (typeof KNOWN_SCENARIOS)[number];
76
88
  /** Service scenario = the primary routing axis (one image serves many).
77
89
  *
78
90
  * 🔴 Deliberately OPEN (`KnownScenario | (string & {})`, 4.0.1): a deployment can register its own
@@ -509,8 +521,10 @@ export interface TaskRequest {
509
521
  * taskId 为键记 user-message 锚,值 = 该 user message 的 entryId;`http/durable-run-leg.ts` / `routes/tasks.ts` 的锚捕获)。
510
522
  * server `src/boot/resolve-spec.ts:686-697`:`resumeAnchorStore.resolve(sessionId, <手柄>, principal)` → entry id;未知手柄 ⇒ 404
511
523
  * `rewind_files_to.unknown_event`;没带会话 ⇒ 422 `rewind_files_to.no_session`;worker 无锚店 / 无 `getLeafId` ⇒ 501。
512
- * ⚠️ 501 **不是**能力位的全部谓词(车OV 对抗复审 [low] 订正):{@link Capabilities.rewindFilesTo} 还合取文件历史店(捕获脸);
513
- * 那一半缺席时 server **不** 501,而是 core 在 run 里响亮拒 `rewind.store_unconfigured`(`prepare-file-history.js`)⇒ 先探能力位。
524
+ * ⚠️ 501 **不是**能力位的全部谓词(车OV 对抗复审 [low] 订正):{@link Capabilities.rewindFilesTo} 还合取文件历史店;
525
+ * 那一半缺席时 server **不** 501,而是 core 在 prepare 里拒 `rewind.store_unconfigured`(`prepare-file-history.js`)⇒ 先探能力位。
526
+ * (server ≥7.104.0 / S-724:同步 `POST /v1/tasks` 零工作时那一拒答 **409** 错误体 —— 见 {@link ConflictError};异步 / 活流腿仍是终态
527
+ * run 行同码。`FILE_HISTORY_CAPTURE=false` 自 7.104.0 **不再**触发它:旋钮只关捕获、店照接。)与 {@link fileHistory} 同体 ⇒ 400。
514
528
  * **只在 `resumeAt` 缺席时受理**(两模式互斥:带了 `resumeAt` 就是那条分叉腿自己的
515
529
  * `restoreFiles` 说了算)。7.72.0 起是**提交那一拍的一次性动作**(续跑腿整族剥掉它);部分恢复看 {@link acceptPartialRestore}。 */
516
530
  rewindFilesTo?: string;
@@ -527,6 +541,20 @@ export interface TaskRequest {
527
541
  * 恢复**与** `rewindFilesTo` 的 code-only 恢复 —— code-only 调用方漏带本位同样吃 loud 终局。
528
542
  * 恢复动作 per-file 幂等:重跑同一恢复即收敛。 */
529
543
  acceptPartialRestore?: boolean;
544
+ /**
545
+ * 🔴 **请求级文件历史关断词**(K-24;server ≥7.104.0 / S-724;core 7.31.0 #1048 `TaskSpec.fileHistory`,型与 core 同一只 ——
546
+ * 测试里对 `@sema-agent/core` 的 `TaskSpec["fileHistory"]` 做 Equal 锚)。**唯一词 `"disabled"`**:这一条 run 不做首次触碰备份、
547
+ * 不铸回合边界(子代继承);缺席 = 按部署设置(**没有** `"enabled"` 的拼法)。
548
+ * · 拼写门(fresh / resume 两腿同判):别的任何值 ⇒ 400 `request.field_invalid`,句子以
549
+ * `fileHistory must be the string 'disabled' when present` 开头;
550
+ * · 🔴 与任一还原键**同体**(`restoreFiles` / {@link rewindFilesTo} / 退役 {@link rewindFiles})⇒ **受理时** 400
551
+ * `request.field_conflict`(`fileHistory: 'disabled' cannot ride with a file restore …`),会话与文件都不动 —— 要还原就别带它;
552
+ * · 这条腿的实际结论读 `wiring_manifest.fileHistory`(`"on"` / `"disabled"`);要不要给用户渲「本会话不捕获」开关读
553
+ * {@link Capabilities.fileHistoryCapture}(`"on-optional"` 才渲;「本会话不捕获」= 这条会话的每个提交都带本键)。
554
+ * ⚠️ 老 server:7.78.1–7.103.x 对本键答 400 `request.body_shape`(顶层体键闭集,未知键拒不丢);更老的 server 静默忽略它(那时没有
555
+ * 顶层键闭集)—— 两形都按 `fileHistoryCapture === "on-optional"` 判再发。
556
+ */
557
+ fileHistory?: "disabled";
530
558
  /** 🔴 PERMISSION MODE INTENT — the TOB-fleet server's five accepted wire values: `default` | `plan` |
531
559
  * `acceptEdits` | `bypassPermissions` | `auto` (post-[816]/[820]/[822] current state; server task-settings.ts
532
560
  * `SettingsPermissionMode` is the same closed set, same-batch aligned 2026-08-05 via server.ts submit-gate
@@ -935,6 +963,68 @@ export interface PausedCause {
935
963
  * 🔴 把「paused ⇒ 空闲且免费」当成不变量的调度器必须看得见这一位。 */
936
964
  restoreMode?: "snapshot" | "park_only";
937
965
  }
966
+ /**
967
+ * `GET /v1/capabilities` 的 `sealedKey` 段(K-24;server ≥7.104.0 / S-737)—— **恰三键**,与 server `src/sealed-key.ts` 的同名接口
968
+ * 逐键同(测试源码腿 / dist 腿对拍)。私钥、私钥文件路径、本机持有的旧钥匙 id、`createdAt` **都不上 wire**。
969
+ */
970
+ export interface SealedKeyCapability {
971
+ /** v1 唯一值 `"libsodium-sealedbox-x25519"`,与 settings-schema 的 `SEALED_BOX_ALG` **同型**(测试里 Equal 锚属主,不手抄)。
972
+ * 别的 alg 在引擎的配置应用期是逐模型的响亮拒,不是猜。 */
973
+ alg: "libsodium-sealedbox-x25519";
974
+ /** 写进 `sealedApiKey.publicKeyId` 的 id(server 缺省铸法 `exec-<sha256(公钥原字节) 前 12 位 hex>`,`sealed-key.ts:169-172`;按不透明串用,
975
+ * 别解析);引擎按它**精确**选私钥开箱(不逐把试)。 */
976
+ publicKeyId: string;
977
+ /** 32 字节 X25519 公钥的**标准** base64(44 字符)。公钥,可记日志。 */
978
+ publicKey: string;
979
+ }
980
+ /**
981
+ * S-173(K-24;server ≥7.104.0)—— 一条**停在门上**的 run 在 `GET /v1/runs/:id` 行上的 `status` 词,也是同步提交撞 park 时
982
+ * 200 体上的回执词。server 从 `RUN_STATUS_CLASS` 判 `"parked"` 的那几个词**派生**(`plugins/store-contracts.ts` 的
983
+ * `ParkedRunStatus`),本型与它逐词同(测试源码腿 / dist 腿对拍)。{@link RunStatus} 的子集。
984
+ */
985
+ export type ParkedRunStatus = "suspended" | "needs_review";
986
+ /**
987
+ * S-173(K-24;server ≥7.104.0)—— 同步提交撞 park 时叠在结果上的 **poll 回执三键**(修前 park 体的全部内容,值逐字不变;
988
+ * 与 server `http/sync-submit-body.ts` 的同名接口逐键同,测试对拍)。
989
+ */
990
+ export interface SyncParkReceipt {
991
+ /** 同步腿提交时铸的 durable run id —— `GET /v1/runs/:taskId` 的 poll 键(= 结果自带的 `taskId`)。 */
992
+ taskId: string;
993
+ /** 提交的会话(= 结果自带的 `sessionId`)。 */
994
+ sessionId: string;
995
+ /** 对外词 = `GET /v1/runs/:id` 行上的 `status`(park 两词之一)。 */
996
+ status: ParkedRunStatus;
997
+ }
998
+ /**
999
+ * `POST /v1/tasks`(非流式)的 200 体(K-24;server 名 `SyncSubmitBody`,`http/sync-submit-body.ts` `buildSyncSubmitBody` 单点铸)。
1000
+ *
1001
+ * **一条规则**(server ≥7.104.0,契约 §5.0c):200 体**恒** = 结果本身(出口封口 + 脱敏后的引擎结果,即 {@link TaskResult});run
1002
+ * **停在门上**(`terminal.kind === "paused"`)时再叠 {@link SyncParkReceipt} 三键 —— 所以在 7.104.0 上 `status` **只在 park 时在场**,
1003
+ * 终局体不带它(不给终局造 `terminal.kind` 之外的第二真源)。同一次 park 在 `/v1/tasks/stream` 的 `done.result` 上除身份键外逐字相同;
1004
+ * 恢复凭据从不在体上(`paused.token` 摘掉)。
1005
+ *
1006
+ * ⚠️ **三代同一个型,如实登记**(本包支持地板 3.0.0;与 {@link TaskResult.terminal} 同款:型面按现行代声明,老代的差别写在这里,
1007
+ * 不把 `terminal` 做成可选去逼每个现行读点处理一个不存在的缺席分支):
1008
+ * · **server ≤7.63**:平面形(见 {@link LegacyPlaneTaskResult})—— `status` 是**终局词**(`completed` / `failed` / `blocked` /
1009
+ * park 两词),**没有** `terminal`,码在退役平面键(`r["errorCode"]` 经开集索引读);
1010
+ * · **7.64–7.103**:终局体 = 现行 `terminal` 形、无 `status`;**park 体只有**回执三键 `{ taskId, sessionId, status }`(`terminal` /
1011
+ * `stats` 运行期缺席);
1012
+ * · **≥7.104**:上面那条规则。
1013
+ * ⇒ 所以 `status` 的词 = park 两词 ∪ ≤7.63 平面词(`LegacyPlaneTaskResult["status"]`,本包对那一代的既有声明,不另抄一份)。
1014
+ * **三代通用读法**(测试 `server-7104-wire` ④bis 三代样例都编译得过、读得对):
1015
+ * ```ts
1016
+ * const r = await client.tasks.submit(req);
1017
+ * if (r.status === "suspended" || r.status === "needs_review") pollLater(r.taskId); // 三代都在 park 时带回执词
1018
+ * else if (r.terminal === undefined) legacyFlat(r.status, r["errorCode"]); // ≤7.63 平面形
1019
+ * else render(r.terminal); // ≥7.64
1020
+ * ```
1021
+ * 🔴 判代用 `r.terminal === undefined`,**别用** `"terminal" in r`:`terminal` 在型上是必填,`in` 的假支会被收成 `never`
1022
+ * (那一支里 `r.status` 编译不过)。
1023
+ */
1024
+ export interface SyncSubmitResult extends TaskResult {
1025
+ /** 回执词 / ≤7.63 平面词(见上):≥7.104 只在 park 时在场(park 两词);7.64–7.103 只在 park 体上;≤7.63 恒在(平面终局词)。 */
1026
+ status?: ParkedRunStatus | LegacyPlaneTaskResult["status"];
1027
+ }
938
1028
  /** Synchronous task result (`POST /v1/tasks`). */
939
1029
  export interface TaskResult {
940
1030
  taskId: string;
@@ -1806,9 +1896,16 @@ export interface RunRecord {
1806
1896
  status: RunStatus;
1807
1897
  /** 🔴 **读盘面 ⇒ 两代字节**(server ≥7.64.0 起;见 {@link LegacyPlaneTaskResult}):server 对存储 blob 是
1808
1898
  * 逐字透传、**不补** `terminal`,所以一台跨 7.64.0 升级过的部署上,升级前的历史行读出来仍是旧的平面形。
1809
- * 判别位 `"terminal" in run.result`。 */
1899
+ * 判别位 `"terminal" in run.result`。
1900
+ *
1901
+ * 🔴 K-24 / S-173(server ≥7.104.0,契约 §5.0c):本位**恒描述当前态** —— park 中(`status` ∈ {@link ParkedRunStatus})带停下来
1902
+ * 那一份结果(`terminal.kind === "paused"`,凭据摘掉;= 同步提交 200 体去掉 `status`);`running`(含被认领续跑之后)**缺席**;终局
1903
+ * 整块替换;审批过期 / 失联收割后**缺席**。7.103.x 及以前 park 行没有本位。⚠️ **先读 `status` 再读 `result`**:`result` 在场不等于
1904
+ * 已结束。混版窗例外:≤7.103.x 的副本不清这一列,滚动升级窗内旧副本的审批过期收割可能留下 `failed` 行上的 paused 结果(MIGRATION 7.104.0)。 */
1810
1905
  result?: TaskResult | LegacyPlaneTaskResult;
1811
- /** 本**行的列**,7.64.0 未变(照旧说五词);只是数据源改成从 `result.terminal` 投影一次(旧行则直接读平面键)。 */
1906
+ /** 本**行的列**,7.64.0 未变(照旧说五词);只是数据源改成从 `result.terminal` 投影一次(旧行则直接读平面键)。
1907
+ * ⚠️ K-24 / S-173(server ≥7.104.0):`needs_review` park 行上本位 = core 的规范码 **`review.pending`**(此前缺席)——
1908
+ * **禁**把「本位在场」读成失败,先读 `status`。`suspended` park 行缺席。 */
1812
1909
  errorCode?: string;
1813
1910
  error?: string;
1814
1911
  /** Work-view correlation. Present when the run has a jobId (omitted when null). LIVE server-side
@@ -1844,7 +1941,8 @@ export interface RunRecord {
1844
1941
  suggestions?: string[];
1845
1942
  /** 🔴 facade 审计(2026-07-24,SDK 全量核查批次②-1):design/80 b item 3 的合成成本面
1846
1943
  * (src/http/routes/runs.ts,`composeSupervisorCost()`)—— 顶层字段(`result` 的**兄弟**,不在 result.stats
1847
- * 里面),只在 infra 定价已配置(`hasInfraPricing`)且 run 已终态并带 `result.stats` 时出现;否则整个
1944
+ * 里面),只在 infra 定价已配置(`hasInfraPricing`)且行上带 `result.stats` 时出现(7.103.x 及以前 = 终态行;K-24 / S-173 起
1945
+ * server ≥7.104.0 的 **park 行**也带结果 ⇒ park 中同样出现,读数 = 停下来那一刻为止的成本);否则整个
1848
1946
  * 字段 OMIT(不是伪造空对象)。此前误放进 `TaskStats`(嵌套,永远读不到)且误标量成 number(真实是
1849
1947
  * `{llm,infra,totalMicroUsd}` 富对象)——两处都改。 */
1850
1948
  supervisorCost?: SupervisorCostBreakdown;
@@ -1864,6 +1962,8 @@ export interface TaskSummary {
1864
1962
  owner?: string;
1865
1963
  startedAt: string;
1866
1964
  endedAt?: string;
1965
+ /** `turns` / `tokens` / `costMicroUsd`:读自行上的结果。K-24 / S-173(server ≥7.104.0):park 中的行也带结果 ⇒ 三位在 park 中
1966
+ * 是**停下来那一刻**的读数(下界;终局时整块替换)。7.103.x 及以前 park 行缺席。 */
1867
1967
  turns?: number;
1868
1968
  tokens?: number;
1869
1969
  costMicroUsd?: number;
@@ -3369,9 +3469,11 @@ export interface Capabilities {
3369
3469
  * `Boolean(deps.fileHistoryStore && deps.resumeAnchorStore && deps.sessionStorage?.getLeafId)` —— 要还原(文件历史店)、
3370
3470
  * 也要解析目标手柄(锚店 + `getLeafId`):「说 yes ⟺ 纯代码回卷的提交解析得出、还原得了」)。
3371
3471
  * 🔴 sdk 11.4.0 订正([8437] U3):旧注点名的是 S-15(design/381)之前的**整树快照店**,那一席早已换成
3372
- * **文件历史店** `fileHistoryStore`;且 server 7.97.0(S-589)起那一席是**捕获脸** = 后端 ∧ 部署旋钮 `FILE_HISTORY_CAPTURE`
3373
- * (`src/file-history-capture.ts` 的装配单点)⇒ 关掉捕获的部署上本位与 `rewindFiles` / `restoreFiles` / `sessionSync` 同为 false,
3374
- * {@link fileHistoryCapture} 同时报 `"off"`。 */
3472
+ * **文件历史店** `fileHistoryStore`。
3473
+ * 🔴 K-24 改真(server ≥7.104.0 / S-724):7.97.0–7.103.x 上那一席是**捕获脸**(后端 ∧ 部署旋钮 `FILE_HISTORY_CAPTURE`),关掉捕获的
3474
+ * 部署上本位与 `rewindFiles` / `restoreFiles` / `sessionSync` 同为 false;**7.104.0 起旋钮只关捕获**(店照接,已存历史照常
3475
+ * 还原 / 同步)⇒ 本位与那三位只看「有没有文件历史店」(= 有没有存储后端),与旋钮无关 —— `fileHistoryCapture: "off"` 不再意味着
3476
+ * 没有 rewind。rewind 入口看本位 / `rewindFiles`,**别**看 {@link fileHistoryCapture}。 */
3375
3477
  rewindFilesTo?: boolean;
3376
3478
  /** assistant-scheduler 面(`routes/capabilities.ts` 的能力对象 `schedulerEnabled && requirePrincipal!==true && remoteExec==="host"` 三与)。 */
3377
3479
  scheduler?: boolean;
@@ -3673,20 +3775,35 @@ export interface Capabilities {
3673
3775
  * 射程与 {@link taskWriteFaceOpen} 的托管门那一半同一只谓词(托管形 ⇒ 两位同 `false`);`AUTONOMY` 只动那一位、不动本位。
3674
3776
  * ⚠️ 缺席 = 老 worker(≤7.94)⇒ 按 `true` 兜底(契约附录 B.1:那时它原样过境)。 */
3675
3777
  taskApproverPosture?: boolean;
3676
- /** **文件历史捕获关不关得掉**(server ≥7.97.0 / S-589;铸点 `routes/capabilities.ts:847` =
3677
- * `fileHistoryCaptureOf(deps.fileHistoryStore)`,闭集属主 server `src/file-history-capture.ts` 的
3678
- * `FILE_HISTORY_CAPTURE_WORD_SET`)。从**装配结果**派生(捕获脸 = 后端 ∧ 部署旋钮 `FILE_HISTORY_CAPTURE`),
3679
- * **不是**旋钮字面回声 —— 无后端的部署同样是 `"off"`;与 `rewindFiles` / `restoreFiles` / {@link rewindFilesTo} /
3680
- * `sessionSync` 同一判定。
3681
- * · `"off"` —— 这台部署不捕获任何改动文件的首次快照,同时也没有 rewind / restore / 纯代码回卷 / session-sync
3682
- * ⇒ 不渲「关闭捕获」开关,也不渲 rewind 入口;
3683
- * · `"on-always"` —— 捕获中,且**无法按会话关闭**(core 的首次触碰捕获是进程级的)⇒ 只渲一句只读真话,
3684
- * 别渲一个关不掉的开关。
3685
- * 🔴 第三词 `"on-optional"`(本会话可以不捕获)server **刻意不声明**(要等 core 收一个单会话不捕获位)——
3686
- * 本型因此是两词闭集;将来加词是 server 的一次 additive,那时本型随之加员。消费端 switch 仍留 default 臂
3687
- * (词表外 ⇒ 按未知处理、不渲开关)。⚠️ 关掉 ≠ 删掉:翻成 `"off"` 之后已捕获的历史不批量删除。
3688
- * ⚠️ 缺席 = 老 worker(≤7.96)⇒ 按 `rewindFiles` 兜底:`true` 读作 `"on-always"`、`false` 读作 `"off"`(逐字等价)。 */
3689
- fileHistoryCapture?: "off" | "on-always";
3778
+ /** **文件历史捕获开没开、能不能按 run 关掉**(server ≥7.97.0 / S-589 立位;**7.104.0 / S-724 换词**;铸点 int-7104
3779
+ * `routes/capabilities.ts:846` = `fileHistoryCaptureOf(deps.fileHistoryStore, deps.config.fileHistoryCapture)`,闭集属主 server
3780
+ * `src/file-history-capture.ts` 的 `FILE_HISTORY_CAPTURE_WORD_SET` —— 测试对它做源码腿 / dist 腿的词表对拍)。从**装配结果**派生
3781
+ * (店在 ∧ 部署旋钮 `FILE_HISTORY_CAPTURE` 没关),**不是**旋钮字面回声 —— 无后端的部署同样是 `"off"`。穷举读:
3782
+ * · `"off"` —— 这台部署**不捕获**任何改动文件的首次快照 ⇒ 不渲「关闭捕获」开关。🔴 7.104.0 起**不再连带 rewind**:
3783
+ * 旋钮只关捕获,已存历史照常 `restoreFiles` / `rewindFilesTo` / session-sync —— rewind 入口看 `rewindFiles` / {@link rewindFilesTo},别看本位;
3784
+ * · `"on-optional"` —— 捕获中,且**可以按 run 关掉**:提交体带 {@link TaskRequest.fileHistory} `"disabled"` ⇒ 渲开关
3785
+ * (关 = 这条会话的每个提交都带它;续跑腿重放同一个体,照带);
3786
+ * · ⚰️ `"on-always"` —— **退役词**(server 7.104.0 起不再发出:请求词接线后「捕获中且关不掉」结构上不可达),7.97.0–7.103.x 的 worker
3787
+ * 仍发它 = 捕获中且**无法按会话关闭** ⇒ 只渲一句只读真话「本部署恒捕获,无法按会话关闭」(契约附录 B.1 逐臂),别渲关不掉的开关。
3788
+ * 本包支持地板(3.0.0)之内的 server 真会发它,所以它留在联合里(K-24 复审 r1 M2,偏离任务书的「硬删」,理由如实:删了 ⇒ 随包 spec
3789
+ * 判一份合法的 7.103 能力面违约、消费端写不出契约要的那一臂);登记 `_keyset-divergence.ts` `CAPABILITY_RETIRED_WORDS`,
3790
+ * 删除条件 = 支持地板抬过 7.104.0。
3791
+ * 词表外的词按未知处理(不按前缀猜,不渲开关)。⚠️ 关掉 ≠ 删掉:部署翻成 `"off"` 不做任何批量删除。
3792
+ * ⚠️ 缺席 = 老 worker(≤7.96,没有这根旋钮)⇒ 按 `rewindFiles` 兜底:`true` 读作 `"on-always"`、`false` 读作 `"off"`(那时捕获 ⟺
3793
+ * 历史店在场,逐字等价)。 */
3794
+ fileHistoryCapture?: "off" | "on-optional" | "on-always";
3795
+ /** **模型钥匙 sealed 形的公钥发现面**(K-24;server ≥7.104.0 / S-737;铸点 int-7104 `routes/capabilities.ts:969` 普通成员
3796
+ * `sealedKey: projectSealedKeyCapability(deps.sealedKeyPublic)`,段形属主 `src/sealed-key.ts` 的 `SealedKeyCapability`)——
3797
+ * 本进程模型钥匙保管店里**最新**那把 X25519 公钥,恰三键(见 {@link SealedKeyCapability})。用法:对着 `publicKey` 做
3798
+ * `crypto_box_seal`(明文 = 模型 key 的 UTF-8 字节),密文转**标准 base64**,连同 `alg` / `publicKeyId` 写进 `ModelEntry.sealedApiKey`
3799
+ * (本地车道 = `config.d/models.json`;server USAGE §9.10)。与 `apiKeyEnv` 同设 ⇒ sealed 优先;开不了 ⇒ 这只模型每次调用都失败
3800
+ * (`sealed_decrypt_failed` / `stale_ciphertext` / `no_key_store`),**不**回落 `apiKeyEnv` 也不回落网关 key。
3801
+ * 🔴 **present-iff**(能力面唯一的逐键例外,契约附录 B.1):缺席有两种含义、同一个动作 —— 老 server(< 7.104.0)/ 这台引擎今天
3802
+ * **没有保管店**(起服建店失败;同一体的 `version` 能分这两种)⇒ **不要封**,改用 `apiKeyEnv`,或修好保管目录后重启再取。
3803
+ * 缺席是**键不在**,不是 `null` / `{}`(判 `caps.sealedKey !== undefined`)。
3804
+ * 🔴 **每台宿主一份**:保管店在 `<数据根>/sealed-key/`;多副本不共享这个目录时各副本答的公钥不同,对着 A 副本公钥封的密文在
3805
+ * B 副本上是 `stale_ciphertext`(逐模型响亮失败)。出路 = 共享保管目录,或走中心形。 */
3806
+ sealedKey?: SealedKeyCapability;
3690
3807
  /** **会话后台任务两口的在场位**(server ≥7.102.0 / S-745 / core 7.32.0 #1107;铸点 `routes/capabilities.ts:308` =
3691
3808
  * `{ listFace: sessionBackgroundFacesAvailable(deps), exitFaces: sessionBackgroundFacesAvailable(deps) }`,与两口的 501
3692
3809
  * **同一只谓词**:会话属主面 `sessionStorage.ownerOf` 在场 ⇒「说 yes 但 501」结构上不可能;缺它 ⇒ 两位显式 `false`、
@@ -4998,7 +5115,7 @@ export interface AssistantTaskStatus {
4998
5115
  * 🔴 **一条规则管所有「effective 半场 only」的键**(9.7.0 立,codex 对抗复审 [high] 验真后收成这一句,
4999
5116
  * 而不是给新加的三段各写一条特例):本型**今天唯一的消费点**是 `GET /v1/diagnostics/wiring` 的 `static`
5000
5117
  * 半场,而标了「只在 effective 半场铸」的键(`leg` / `ask.effective` / `configFingerprint` / `tools` /
5001
- * `hooks` / `lsp` / `modelGate` / `autoMode` / `writeProtection` / `readDeny` / `autoConsolidation`)
5118
+ * `hooks` / `lsp` / `modelGate` / `autoMode` / `writeProtection` / `readDeny` / `autoConsolidation` / `fileHistory`)
5002
5119
  * 在这条 wire 上**恒缺席** ⇒ **它们在本面上的缺席不携带任何信息**。
5003
5120
  * 每一段顶注里写的那些「缺席 = 未武装 / 缺席 = 第三态」的读法**只对 live 帧成立**(`AgentEvent` 的
5004
5121
  * `wiring_manifest` 臂),**不许**搬到这条端点的响应上来读 —— 在这里把缺席读成「未武装」,恰恰会把一台
@@ -5126,7 +5243,17 @@ export interface WiringManifest {
5126
5243
  * 外流记忆的部署渲成没在外流)。这台部署武装没武装,租户面读
5127
5244
  * {@link SessionMemoryStatusResponse.autoConsolidationArmed}(恒在场的真布尔)。 */
5128
5245
  autoConsolidation?: WiringManifestAutoConsolidation;
5246
+ /** K-24(server ≥7.104.0 / S-724;core 7.31.0 #1048 / #1050)—— 这条腿捕不捕文件历史,词形单源 {@link WiringManifestFileHistory}。
5247
+ * 🔴 **effective 半场 only ⇒ 本面恒缺席**(见块头那一条规则):读法只对 live `wiring_manifest` 帧成立;部署形读
5248
+ * {@link Capabilities.fileHistoryCapture}。 */
5249
+ fileHistory?: WiringManifestFileHistory;
5129
5250
  }
5251
+ /**
5252
+ * `wiring_manifest.fileHistory` 的词(K-24;server ≥7.104.0 / S-724;core 7.31.0 `WiringManifest.fileHistory` = `"on" | "disabled"`,
5253
+ * 测试对 `@sema-agent/core` 做可赋锚)—— live 帧与 {@link WiringManifest} 共用这一只(段形单源,同 {@link WiringManifestReadDeny} 先例)。
5254
+ * 🔴 **开集**:server 不枚举这个词(在场却不是非空串 ⇒ 丢键),第三个词原样过境 ⇒ 按未知处理。
5255
+ */
5256
+ export type WiringManifestFileHistory = "on" | "disabled" | (string & {});
5130
5257
  /** core `ToolRoster`(design/388 B-4)—— 一条腿的工具名册。**顶层四键逐键镜像**;`entries[]` 的行只镜像身份 /
5131
5258
  * 出身 / 轴 / 面几组消费端会读的键,其余按开集读(core 给行加键不该把消费端编译炸掉;属主是 core 的 typebox
5132
5259
  * schema,server 侧零键表)。`digest` = 整只名册的指纹,**恰 16 位 hex**,任一轴/面/契约/别名变化都会移动它。 */