@epoch-agent/core 0.13.0 → 0.15.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.
package/dist/index.d.ts CHANGED
@@ -1342,9 +1342,12 @@ interface GoalToolDeps {
1342
1342
  declare function createGoalTool(deps: GoalToolDeps): EpochTool;
1343
1343
 
1344
1344
  /**
1345
- * 记忆系统类型 — 对齐 docs/design/memory-system.md
1345
+ * 记忆系统类型。
1346
1346
  *
1347
- * 参考 Hermes tools/memory_tool.py + memory_provider.py
1347
+ * 参考 Hermes tools/memory_tool.py + memory_provider.py。
1348
+ * (原来这里写着「对齐 `docs/design/memory-system.md`」,而那整个目录已随
1349
+ * `5bbf3c8c` 删掉 —— 今天面向用户那半边在
1350
+ * [TOOLS.md](../../../../docs/TOOLS.md) 的「待办、目标、记忆、沙箱、委托」一节。)
1348
1351
  */
1349
1352
  type MemoryTarget = 'memory' | 'user';
1350
1353
  /** 配额信息 */
@@ -1980,7 +1983,7 @@ declare function createScheduleDraftTool(deps: ScheduleDraftDeps): EpochTool;
1980
1983
  *
1981
1984
  * 方案 48 §七 挂着「归档会话搜不到符不符合用户预期」,而 PR-1 之后的落地被记成了
1982
1985
  * **一处不对称**(`session_search` 过滤 `archived`,`session_messages_search`
1983
- * 给了 id 就搜得到)。逐处核过八个入口之后的结论是:**那不是不对称,
1986
+ * 给了 id 就搜得到)。逐处核过九个入口之后的结论是:**那不是不对称,
1984
1987
  * 是同一条规则的两侧。**
1985
1988
  *
1986
1989
  * | 入口 | 提问方式 | 归档会话 | 落点 |
@@ -1989,12 +1992,13 @@ declare function createScheduleDraftTool(deps: ScheduleDraftDeps): EpochTool;
1989
1992
  * | `session_messages_search` | 必须给 sessionId | **搜得到** | `query.ts` `searchMessages` |
1990
1993
  * | `session_messages_read` | 给 sessionId + messageId | **读得到** | `query.ts` `readMessages` |
1991
1994
  * | `session_trace` | 必须给 sessionId | **列得出,标 `archived`** | `trace.ts`(判据在那个文件头) |
1995
+ * | `session_list`(开给模型) | 不指名 | **不列**,可显式要 | `query.ts` `listSessions` |
1992
1996
  * | `@:` 补全面板(方案 53) | 边打边列,不指名 | **不列** | `reference.ts` `listSessionCandidates` |
1993
1997
  * | `@:` 完整 sessionId | 指名道姓 | **引用得到** | `reference.ts` `resolveSessionReference` |
1994
1998
  * | `@:` id 前缀 / 标题子串 | 模糊搜 | **引用不到** | `reference.ts` `uniqueOf` |
1995
1999
  * | TUI / CLI 的会话列表(给人) | 不指名 | **不列**,可显式要 | `db.ts` `listSessions` |
1996
2000
  *
1997
- * 八处合起来是一句话:
2001
+ * 九处合起来是一句话:
1998
2002
  *
1999
2003
  * > **归档 = 从列表和模糊搜里收起来,不是不许读。**
2000
2004
  * > 手上没有那段会话的 id 就碰不到它;明确给了 id 就是明确指名,照旧读得到。
@@ -2014,15 +2018,29 @@ declare function createScheduleDraftTool(deps: ScheduleDraftDeps): EpochTool;
2014
2018
  * 等于把标题一个字一个字探出来。**归档走的是同一条线、同一个理由**,
2015
2019
  * 两个方案(48 / 53)因此不需要各判一次
2016
2020
  *
2017
- * ⚠️ 于是模型仍然有一条路走到归档会话:`session_trace` 会把它列在血缘链上并标
2018
- * `archived`,拿着那个 id 就能进去搜 / 读。**这是刻意的** ——「它在不在链上」
2019
- * 和「能不能进去看」是两个问题(判据全文在 `trace.ts` 文件头)。反过来说,
2020
- * 一个**没有**血缘关系、又不在链上的归档会话,模型没有办法凭检索发现它。
2021
+ * ⚠️ 于是模型有两条路走到归档会话,**两条都是刻意的**:
2022
+ *
2023
+ * - `session_trace` 会把它列在血缘链上并标 `archived`,拿着那个 id 就能进去搜 / 读
2024
+ * ——「它在不在链上」和「能不能进去看」是两个问题(判据全文在 `trace.ts` 文件头)
2025
+ * - `session_list` 传 `archived: 'only'` / `'all'` 就列得出来。**这一档是显式要的**
2026
+ * (默认那一档不列),和人那一侧 `db.ts listSessions` 的 `archived` 开关逐字同形
2027
+ *
2028
+ * ### ⚠️ 2026-09-20:「模型发现不了归档会话」这条性质没有了
2029
+ *
2030
+ * `session_list` 之前这里写的是「一个**没有**血缘关系、又不在链上的归档会话,模型
2031
+ * 没有办法凭检索发现它」。那句话现在**不成立**了 —— 传一个 `archived` 就列得出来。
2032
+ *
2033
+ * 这不是把上面那条规则改松了,是那条规则本来就没管这件事:它说的是「模糊搜够不着」,
2034
+ * 而 `session_list` 不是模糊搜,它是**指名要归档那一档**(同一个工具的默认档照旧
2035
+ * 不列)。真正变的是**那条性质从此不该再被人当成安全保证引用** —— 它当初是
2036
+ * 「没人给模型开列表工具」的副产物,不是任何一处刻意守的东西。要那条保证的话,
2037
+ * 唯一的实现方式是让归档参与 `resolveSessionVisibility`,而那就是「归档 = 不许读」,
2038
+ * 上面三条理由逐条反对它。
2021
2039
  *
2022
2040
  * ### 这条判据只有这一个家
2023
2041
  *
2024
- * 别在四个工具的描述、八处 SQL 的行内注释里各抄一遍 —— 那种抄写不会变红,
2025
- * 只会在有人改了一处之后变成七句错的话。上面那张表由
2042
+ * 别在五个工具的描述、九处 SQL 的行内注释里各抄一遍 —— 那种抄写不会变红,
2043
+ * 只会在有人改了一处之后变成八句错的话。上面那张表由
2026
2044
  * `core/__tests__/session-archived-scope.test.ts` **两层**钉住:行为层逐个入口
2027
2045
  * 断两个方向(归档的搜不到 / 给了 id 就搜得到),结构层扫源码,
2028
2046
  * 保证**新加的查询必须先在那份表里登记立场**。
@@ -2334,6 +2352,59 @@ interface ReadMessagesOutput {
2334
2352
  /** 这段会话一共多少条。让模型知道自己这个窗口在整段里占多少 */
2335
2353
  total: number;
2336
2354
  }
2355
+ /**
2356
+ * 归档那一档怎么列。**三个值,不是布尔**。
2357
+ *
2358
+ * 人那一侧(`SessionDB.listSessions`)用的是 `boolean | 'any'`,而那个形状有两个
2359
+ * 毛病落到模型这一侧会变成真缺陷:`true` 的意思是「**只**列归档的」(不是「也列」),
2360
+ * 而 JSON Schema 表达不了 `boolean | 'any'` —— 写成 `type: 'boolean'` 就永远够不着
2361
+ * 第三档。所以这一层换成显式三值,映射在 {@link SessionQueries.listSessions} 里。
2362
+ */
2363
+ type ArchivedScope = 'exclude' | 'only' | 'all';
2364
+ /**
2365
+ * 列表里的一段会话。**比 `SessionMeta` 窄得多**,那是刻意的。
2366
+ *
2367
+ * `SessionMeta` 有 25 个字段(token 分项、gitBranch、rewindCount…),而这个工具
2368
+ * 回答的是「我都有哪些会话、哪段值得进去看」。多给的每一个字段都要占工具输出的
2369
+ * 字符预算,而模型在这一步一个都用不上。
2370
+ *
2371
+ * ⚠️ **`preview` 不在这里,而且不许加**:`manager.ts` 那条「`tags` / `preview`
2372
+ * 恒空」说的是全仓没有任何一处会写这两列。加进来等于每段会话多一个恒空字段,
2373
+ * 然后模型据此以为「这段会话没内容」。
2374
+ */
2375
+ interface SessionListEntry {
2376
+ sessionId: string;
2377
+ /** 用户改过名就是那个名,否则是自动标题(首条消息前 50 字) */
2378
+ title: string;
2379
+ cwd?: string | undefined;
2380
+ /**
2381
+ * 最后活动时间(毫秒)。取 `COALESCE(updated_at, started_at)` 而不是裸列 ——
2382
+ * 读侧的 `rowToMeta` 就是这么兜的,裸取会让一行 `updated_at` 是 NULL 的会话
2383
+ * 排到 1970 年去。
2384
+ */
2385
+ updatedAt: number;
2386
+ messageCount: number;
2387
+ archived: boolean;
2388
+ /** 这段会话是不是「你自己」。渲染那一侧要标出来 */
2389
+ isCurrent: boolean;
2390
+ }
2391
+ interface SessionListInput extends Omit<SessionVisibilityInput, 'db'> {
2392
+ /** 回几段。调用方负责夹紧上下限 */
2393
+ limit: number;
2394
+ /** 默认 `'exclude'`(不列归档的),判据见 `authorization.ts` 那张表 */
2395
+ archived?: ArchivedScope;
2396
+ }
2397
+ interface SessionListOutput {
2398
+ sessions: SessionListEntry[];
2399
+ /**
2400
+ * 这个范围里**一共**多少段(不受 `limit` 影响)。
2401
+ *
2402
+ * 少了它,一份被 `limit` 截过的列表和一份本来就这么短的列表长得一模一样,
2403
+ * 而模型会据此下结论(「我一共就这 10 段会话」)。同 `session_trace` 的
2404
+ * `truncated` 那条判据。
2405
+ */
2406
+ total: number;
2407
+ }
2337
2408
  /**
2338
2409
  * 会话检索。**这一层只查库,不管权限级别、不管工具协议** —— 那些在工具那一侧。
2339
2410
  */
@@ -2386,6 +2457,31 @@ declare class SessionQueries {
2386
2457
  * 库连接和授权判定接上去 —— 让工具那一侧只认识 `SessionQueries` 一个门面。
2387
2458
  */
2388
2459
  trace(input: TraceInput): SessionTrace;
2460
+ /**
2461
+ * 列出可读范围内的会话 —— **这一族里唯一不要检索词的那个**。
2462
+ *
2463
+ * ## 为什么不复用 `SessionDB.listSessions`
2464
+ *
2465
+ * 同文件头那条「这一层为什么不长在 db.ts 里」:那一份服务的是人,**没有授权层**
2466
+ * (人本来就有权看自己机器上全部会话),它只认 `cwd` 不认血缘链。把 `visClause`
2467
+ * 塞进 `ListSessionsInput` 等于把鉴权概念漏进人那一侧的 API,而那个接口还开给了
2468
+ * 增量备份、TUI、REST 三个调用方 —— 它们谁都不该被迫理解「血缘」。
2469
+ *
2470
+ * 于是这里是第二份 SQL,但**判定只有一份**(`resolveSessionVisibility`),
2471
+ * 那才是会走散的那一半。
2472
+ *
2473
+ * ## 排序固定「最后活动倒序」
2474
+ *
2475
+ * 不开 `sortKey`、不开游标:模型问的是「我最近在干什么」,而翻页是人那一侧的
2476
+ * 需求(那边有游标、有四个排序键)。少一个参数就少一条模型会猜错的路。
2477
+ *
2478
+ * ## 归档:默认不列,显式要才给
2479
+ *
2480
+ * 和人那一侧逐字同形。判据**一个字都不在这儿**,在
2481
+ * [authorization.ts](./authorization.js) 文件头那张入口表上 —— 这里只是那张表的
2482
+ * 一个落点,别在这儿再写一遍理由(那种抄写不会变红,只会变成一句错的话)。
2483
+ */
2484
+ listSessions(input: SessionListInput): SessionListOutput;
2389
2485
  /**
2390
2486
  * 正文命中。`archived = 0` 与人那一侧保持一致 —— 归档是「用户把它收起来了」,
2391
2487
  * 模型不该从收起来的地方翻东西出来。
@@ -2510,7 +2606,7 @@ declare function createSessionMessagesSearchTool(deps: SessionSearchDeps): Epoch
2510
2606
  * 对外这一族就叫「会话检索」([docs/TOOLS.md](../../../../../docs/TOOLS.md)
2511
2607
  * 的「翻历史会话」那一节)。
2512
2608
  *
2513
- * 这四个名字的真源是 `session/query.ts` 的 `SESSION_QUERY_TOOLS`,
2609
+ * 这五个名字的真源是 `session/query.ts` 的 `SESSION_QUERY_TOOLS`,
2514
2610
  * `__tests__/session-query-sites.test.ts` 对着它比这里的返回值。
2515
2611
  */
2516
2612
  declare function createSessionSearchTools(deps: SessionSearchDeps): EpochTool[];
@@ -2569,7 +2665,7 @@ declare function createSessionTraceTool(deps: SessionSearchDeps): EpochTool;
2569
2665
  *
2570
2666
  * 两条,第二条是硬的:
2571
2667
  *
2572
- * 1. [manager.ts](./manager.ts) 那时已经 501 行,压着 CLAUDE.md 铁律 3 的 500 行线。
2668
+ * 1. [manager.ts](./manager.ts) 那时已经 501 行,压着 AGENTS.md 铁律 3 的 500 行线。
2573
2669
  * 往里再塞封顶和收窄是把违规做实,搬出来是**减**不是加;
2574
2670
  * 2. **`agent/` 不许 import 这一族**(技能索引接线那一轮的决定 2.2):`agent/` 收的是
2575
2671
  * 拼好的成品串,不是技能列表。而 web 能力页那句「界面上显示的那一行 = 真进上下文
@@ -3314,19 +3410,14 @@ declare class TrackerDB {
3314
3410
  * 所以这个文件里加一个属性,`evals/*.eval.ts` 里**每一条**录像都会对不上 ——
3315
3411
  * 不是只有跟 todo 有关的那几条。这一轮改完 17 条全红,逐条按新值更新过了。
3316
3412
  *
3317
- * ✅ 那张 📮 2026-08-17 合并那一轮照办了,原文留着 —— 它**下一次还成立**,
3318
- * 所以从「给合并的人」改写成一条常驻规矩:
3413
+ * ⚠️ **合并时那些 `fingerprint:` 行的值一个都别手挑。** 它们是**天然的冲突面**
3414
+ * —— 任何一条也动了 prompt 或工具定义的分支,改的是同样那批行。冲突时合完之后
3415
+ * 跑一次 `pnpm eval`,拿它打出来的当前值统一覆盖一遍(诊断里会逐条打印
3416
+ * 「旧 → 新」)。手挑等于赌两边的改动恰好互不影响,而那正是这个安全阀要防的事。
3319
3417
  *
3320
- * > 那 17 行 `fingerprint:` 是**天然的冲突面** —— 任何一条也动了 prompt 或
3321
- * > 工具定义的分支,改的是同样这 17 行。冲突时**两边的值都别手挑**:合完之后
3322
- * > 跑一次 `pnpm eval`,拿它打出来的当前值统一覆盖一遍(诊断里会逐条打印
3323
- * > 「旧 → 新」)。手挑等于赌两边的改动恰好互不影响,而那正是这个安全阀要防的事。
3324
- *
3325
- * 那一轮四条分支里只有这一条动了指纹,**四次合并零冲突**,合完 `pnpm eval` 全绿
3326
- * (10 个测试文件 51 条),所以一个值都没有手动挑过。⚠️ 同一轮还纠正了一处
3327
- * 口口相传的错话:**指纹是 `evals/*.eval.ts` 里的内联字符串字面量** ——
3328
- * 19 处、摊在 7 个 `.eval.ts` 里,全仓**没有** `.eval-recordings/` 这个目录,
3329
- * 别照着那个名字去找(找不到就以为「录像不在仓里」,那是这条规矩最容易断的地方)。
3418
+ * ⚠️ **指纹是 `evals/*.eval.ts` 里的内联字符串字面量**,全仓**没有**
3419
+ * `.eval-recordings/` 这个目录 —— 别照那个名字去找。找不到就会以为「录像不在仓里」,
3420
+ * 那是这条规矩最容易断的地方。
3330
3421
  */
3331
3422
 
3332
3423
  declare function createTodoTool(db: TrackerDB): EpochTool;
@@ -5634,6 +5725,9 @@ declare function updatePlugin(name: string, opts: InstallOptions): Promise<Insta
5634
5725
  * "name": "acme",
5635
5726
  * "owner": { "name": "Acme Inc." },
5636
5727
  * "display": { "fields": ["status", "downloads", "author"] },
5728
+ * "categories": [
5729
+ * { "id": "dev", "label": "开发", "children": [{ "id": "lint", "label": "静态检查" }] }
5730
+ * ],
5637
5731
  * "plugins": [
5638
5732
  * {
5639
5733
  * "name": "toolkit",
@@ -5662,6 +5756,17 @@ declare function updatePlugin(name: string, opts: InstallOptions): Promise<Insta
5662
5756
  * ⚠️ **整格不写 = 照旧「填了就画」** —— 存量目录一个字都不用改,
5663
5757
  * 判据在 `DisplaySchema.fields` 上那张三行的表。
5664
5758
  *
5759
+ * ## 顶上那格 `categories`:**市场自己声明分类的层级**(2026-09-21)
5760
+ *
5761
+ * 在它之前分类只有一层 —— `category` 是一个自由字符串,界面把出现过的那些一字排开。
5762
+ * 一份分得细的目录(「办公 → 表格 / 文档 / 幻灯」)表达不出那个「→」。
5763
+ *
5764
+ * 这一格是一棵树,而**条目那一侧引用的仍旧是裸 id**(`category: "sheet"`),
5765
+ * 不是路径。于是存量目录补一棵树**不用动任何一条插件**,判据全文和另一条理由
5766
+ * (「分类名里本来就能有 `/`」)在 {@link CategoryNodeSchema} 上。
5767
+ * ⚠️ **整格不写 = 没有层级**,界面退回 2026-09-17 那一档(每个出现过的分类各一行),
5768
+ * 而一棵**写坏的**树同样退回那一档 —— 判据在 {@link CategoriesSchema} 上。
5769
+ *
5665
5770
  * ## ⚠️ 「没有上传接口」这句话 2026-09-08 改了半句
5666
5771
  *
5667
5772
  * 原话是「没有服务端、没有账号、**没有上传接口**、没有审核」。改的是第三句 ——
@@ -5752,6 +5857,33 @@ type MarketplaceDisplayField = (typeof MARKETPLACE_DISPLAY_FIELDS)[number];
5752
5857
  declare const DisplaySchema: z.ZodObject<{
5753
5858
  fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
5754
5859
  }, z.core.$strip>;
5860
+ /**
5861
+ * 分类树里的一个节点(2026-09-21)。
5862
+ *
5863
+ * ## ⚠️ 条目那一侧引用的是**裸 id**,不是一条 `办公/表格` 那样的路径
5864
+ *
5865
+ * 也就是说 {@link EntrySchema} 的 `category` **一个字都没改** —— 它今天是什么形状
5866
+ * 明天还是什么形状,变的只是「那串字符现在可以被这棵树放进层级里」。两条判据:
5867
+ *
5868
+ * 1. **存量目录加一棵树不用动任何一条插件。** 一份写着 `category: "dev"` 的目录,
5869
+ * 只要在顶上补一个 `{ "id": "dev", "label": "开发" }`,那一批条目当场归位。
5870
+ * 换成路径引用的话,加一层层级 = 把每一条 `category` 都重写一遍;
5871
+ * 2. **不必再定义「分类名里出现 `/` 怎么办」。** 分类是自由字符串(那一格从落地起
5872
+ * 就是 `z.string().min(1)`),一份目录里真的能有一条 `category: "a/b"`,
5873
+ * 而路径引用会把它和「a 下面的 b」撞成同一个东西,且类型上一点问题都没有。
5874
+ *
5875
+ * 代价是 **id 必须全树唯一** —— 由 {@link CategoriesSchema} 那道 `superRefine` 管。
5876
+ *
5877
+ * ⚠️ `label` 可缺省,缺省就是 `id` 本身(补齐那一下在网线那一层做,判据在
5878
+ * protocol 的 `WirePluginCategory.label` 上:界面要的是结论,不是「缺了自己兜着」)。
5879
+ * ⚠️ **`label` 不翻译**,口径逐字同 `plug_cat_*` 那三句文案上的 ⚠️:一份中文目录里
5880
+ * 那个词本来就是中文,翻了的话用户搜到的和看到的对不上。
5881
+ */
5882
+ interface MarketplaceCategoryInput {
5883
+ id: string;
5884
+ label?: string;
5885
+ children?: MarketplaceCategoryInput[];
5886
+ }
5755
5887
  declare const CatalogSchema: z.ZodObject<{
5756
5888
  name: z.ZodString;
5757
5889
  description: z.ZodOptional<z.ZodString>;
@@ -5762,6 +5894,7 @@ declare const CatalogSchema: z.ZodObject<{
5762
5894
  display: z.ZodOptional<z.ZodObject<{
5763
5895
  fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
5764
5896
  }, z.core.$strip>>;
5897
+ categories: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodType<MarketplaceCategoryInput, unknown, z.core.$ZodTypeInternals<MarketplaceCategoryInput, unknown>>>>>;
5765
5898
  plugins: z.ZodArray<z.ZodObject<{
5766
5899
  name: z.ZodString;
5767
5900
  description: z.ZodOptional<z.ZodString>;
@@ -5807,6 +5940,7 @@ declare const RecordSchema: z.ZodObject<{
5807
5940
  display: z.ZodOptional<z.ZodObject<{
5808
5941
  fields: z.ZodOptional<z.ZodArray<z.ZodString>>;
5809
5942
  }, z.core.$strip>>;
5943
+ categories: z.ZodCatch<z.ZodOptional<z.ZodArray<z.ZodType<MarketplaceCategoryInput, unknown, z.core.$ZodTypeInternals<MarketplaceCategoryInput, unknown>>>>>;
5810
5944
  plugins: z.ZodArray<z.ZodObject<{
5811
5945
  name: z.ZodString;
5812
5946
  description: z.ZodOptional<z.ZodString>;
@@ -5841,6 +5975,8 @@ declare const RecordSchema: z.ZodObject<{
5841
5975
  }, z.core.$strip>;
5842
5976
  type MarketplaceEntry = z.infer<typeof EntrySchema>;
5843
5977
  type MarketplaceCatalog = z.infer<typeof CatalogSchema>;
5978
+ /** 分类树里的一个节点(2026-09-21)。判据在 {@link CategoryNodeSchema} 上 */
5979
+ type MarketplaceCategory = MarketplaceCategoryInput;
5844
5980
  type MarketplaceRecord = z.infer<typeof RecordSchema>;
5845
5981
  /** 这一条在市场那一侧的档口,见 `EntrySchema.status` 上那张四行的表 */
5846
5982
  type MarketplaceStatus = NonNullable<MarketplaceEntry['status']>;
@@ -5865,6 +6001,29 @@ type MarketplaceDisplay = z.infer<typeof DisplaySchema>;
5865
6001
  * 那张表上。
5866
6002
  */
5867
6003
  declare function projectEntryForDisplay(entry: MarketplaceEntry, display: MarketplaceDisplay | undefined): MarketplaceEntry;
6004
+ /**
6005
+ * 这个市场允许印这一格吗(2026-09-21 从 {@link projectEntryForDisplay} 里提出来的)。
6006
+ *
6007
+ * ## 为什么要提出来:**分类树不是条目上的一格,但它吃同一条规矩**
6008
+ *
6009
+ * `display.fields` 里没有 `category` 的时候,上面那个函数会把每一条的 `category`
6010
+ * 抹掉 —— 而 2026-09-21 新加的那棵 `categories` 树挂在**目录顶上**,不经过它。
6011
+ * 于是会出现一个自相矛盾的界面:一棵画出来的分类树,每一枝都是 0,
6012
+ * 全部插件挤在「未分类」里 —— **一棵永远匹配不到任何东西的导航树**。
6013
+ *
6014
+ * 那一档在这一格之前是**画都不画**的(可筛的桶只剩「未分类」一个,
6015
+ * 少于 2 就整个不画),所以这是一次真实的倒退,不是一个新场景。
6016
+ *
6017
+ * ⚠️ **提的是「许不许」这条判断,不是又做一遍投影**:文件头那条
6018
+ * 「一个问题只该有一个答案」原样成立 —— 名单和语义(`undefined` = 全画、
6019
+ * `[]` = 一格都不画、认不得的名字不起作用)仍旧只有这一处定义,
6020
+ * 两个出口(条目那一侧、市场行那一侧)读的是同一个函数。
6021
+ *
6022
+ * ⚠️ **只认 {@link MARKETPLACE_DISPLAY_FIELDS} 里那几个名字**:`fields` 的值域是
6023
+ * `string[]`(判据在 `DisplaySchema.fields` 上:写成 enum 的话,一份用了未来版本
6024
+ * 格子名的目录会让整份清单退回 fallback),所以认不得的名字落进来也不起作用。
6025
+ */
6026
+ declare function displayAllows(display: MarketplaceDisplay | undefined, field: MarketplaceDisplayField): boolean;
5868
6027
  interface MarketplaceOptions {
5869
6028
  /** `marketplacesPath(homeDir)` */
5870
6029
  statePath: string;
@@ -10123,7 +10282,7 @@ declare function classifyProviderError(err: unknown): {
10123
10282
  *
10124
10283
  * 单独一个文件而不是塞进 `router.ts`:
10125
10284
  *
10126
- * 1. `router.ts` 已经 700 多行(CLAUDE.md 铁律 3 的上限是 500),不该再长
10285
+ * 1. `router.ts` 已经 700 多行(AGENTS.md 铁律 3 的上限是 500),不该再长
10127
10286
  * 2. 这三道检查是**纯函数** —— 给它「有没有凭据」和「模型什么能力」,
10128
10287
  * 它就能算出换不换得成。抽出来之后单测不用造一个 `ProviderRouter`
10129
10288
  * (那要真凭据、要碰 `readProviderKeyEnv()`),直接喂假事实就行
@@ -11507,6 +11666,10 @@ declare const EpochConfigSchema: z.ZodObject<{
11507
11666
  retentionDays: z.ZodDefault<z.ZodInt>;
11508
11667
  vacuumAfterPrune: z.ZodDefault<z.ZodBoolean>;
11509
11668
  }, z.core.$strip>>;
11669
+ automation: z.ZodPrefault<z.ZodObject<{
11670
+ keepRuns: z.ZodDefault<z.ZodInt>;
11671
+ maxRecordingMb: z.ZodDefault<z.ZodInt>;
11672
+ }, z.core.$strip>>;
11510
11673
  budget: z.ZodOptional<z.ZodObject<{
11511
11674
  maxCostUsd: z.ZodOptional<z.ZodNumber>;
11512
11675
  maxTokens: z.ZodOptional<z.ZodInt>;
@@ -11858,7 +12021,7 @@ declare function isSettingWriteLayer(value: string): value is SettingWriteLayer;
11858
12021
  * 安全中心指两件事(「新会话从哪一档起」vs「这个会话此刻哪一档」),
11859
12022
  * 而那正是决定 20 ④ 拆开的那个歧义 —— 记住上一次那一档没有把这个歧义请回来。
11860
12023
  */
11861
- declare const SETTING_WRITE_KEYS: readonly ["model", "maxTurns", "models.utility", "fallback.model", "contextLength", "maxOutputTokens", "compression.enabled", "compression.threshold", "memory.memoryCharLimit", "memory.userCharLimit", "memory.indexCharLimit", "budget.maxCostUsd", "budget.maxTokens", "budget.warnAtPercent", "budget.onUnknownPricing", "sessions.autoPrune", "sessions.retentionDays", "sessions.vacuumAfterPrune", "permission"];
12024
+ declare const SETTING_WRITE_KEYS: readonly ["model", "maxTurns", "models.utility", "fallback.model", "contextLength", "maxOutputTokens", "compression.enabled", "compression.threshold", "memory.memoryCharLimit", "memory.userCharLimit", "memory.indexCharLimit", "budget.maxCostUsd", "budget.maxTokens", "budget.warnAtPercent", "budget.onUnknownPricing", "sessions.autoPrune", "sessions.retentionDays", "sessions.vacuumAfterPrune", "automation.keepRuns", "automation.maxRecordingMb", "sessionSearch.allWorkspaces", "permission"];
11862
12025
  type SettingWriteKey = (typeof SETTING_WRITE_KEYS)[number];
11863
12026
  /** 这个键写得进去吗。名单就是 {@link SETTING_WRITE_KEYS} 本身,别在别处抄一份字面量 */
11864
12027
  declare function isWritableSettingKey(value: string): value is SettingWriteKey;
@@ -12503,6 +12666,23 @@ declare class MemoryManager {
12503
12666
  *
12504
12667
  * 取首行而不是前 N 字符:条目是「一条一个事实」,第一行基本就是那句结论,
12505
12668
  * 而横跨换行去截会把下一行的开头黏上来,读起来像一句破句。
12669
+ *
12670
+ * ## 🔴 按**码点**切,不是按 `.length`
12671
+ *
12672
+ * 判据全文在 infra 的 `text-slice.ts` 上(「截断不许切出半个字符」全仓只实现
12673
+ * 一次)。这里漏掉它的后果不是「显示成 `�`」那么轻:
12674
+ *
12675
+ * 首行第 79/80 个码元正好落在一个代理对中间时(首行超过 80 字、末尾带 emoji
12676
+ * 的记忆条目,中文用户写起来很容易),裸 `.slice()` 切出一个**孤立的高代理**。
12677
+ * 它随索引块进 system prompt,`JSON.stringify` 把它写成不配对的 `\ud83d`,
12678
+ * 而严格的 JSON 解析器(serde_json)拒收 —— DeepSeek 回 400
12679
+ * 「unexpected end of hex escape」,这一轮 0 token、**首次模型请求直接挂**。
12680
+ * 一条记忆就能让整个会话开不了口,而且报错指向的是「网络/供应商」,
12681
+ * 没人会想到是记忆索引切坏了。2026-09-20 复现确认。
12682
+ *
12683
+ * ⚠️ 长度那一比也要按码点。按 `.length`(码元)比的话,一条 41 个 emoji 的
12684
+ * 首行会被判「超过 80」,然后 `headCodePoints` 原样还回来 —— 末尾多一个
12685
+ * 没有截断任何东西的省略号。
12506
12686
  */
12507
12687
  private indexEntries;
12508
12688
  /**
@@ -13039,6 +13219,41 @@ interface RestorePartsOptions {
13039
13219
  }
13040
13220
  /** 落盘部件 → 内存部件。文件没了就退化成占位文本,不抛 */
13041
13221
  declare function restoreParts(parts: readonly PersistedPart[], opts: RestorePartsOptions): EpochContentPart[];
13222
+ /** {@link importParts} 的结果。带 base64 的部件会让整条走不通,所以不是「尽力而为」 */
13223
+ type ImportPartsResult = {
13224
+ ok: true;
13225
+ parts: PersistedPart[];
13226
+ }
13227
+ /** `detail` 是**机器可读**的定位串(`image:base64` 之类),不是给人看的文案 */
13228
+ | {
13229
+ ok: false;
13230
+ detail: string;
13231
+ };
13232
+ /**
13233
+ * 内存部件 → 落盘部件,**给导入用**:`restoreParts(..., {inlineImages:false})` 的真逆。
13234
+ *
13235
+ * ## 为什么不能直接用 `persistParts()`
13236
+ *
13237
+ * 因为那两个函数在图片上**不是一对逆运算**,而类型系统看不出来(两边都是
13238
+ * `string`)。`restoreParts` 在 `inlineImages:false` 这一支吐的是**绝对路径**
13239
+ * (上面第 243 行),而 `persistParts` 见到一个不带 `https?:` 的字符串就当它是
13240
+ * **base64**(第 174 行)—— 把读出来的路径原样喂回去,`Buffer.from(路径,'base64')`
13241
+ * 会把那串路径当乱码解出来几十个字节写进 artifact 目录,得到一张坏图,
13242
+ * 而且**全程不抛**。所以搬运必须走这条单独的路。
13243
+ *
13244
+ * ## 见到 base64 一律拒,不是「尽力落盘」
13245
+ *
13246
+ * 落盘要写文件,而导入是在一个事务里搬一整段会话 —— 半路去写磁盘意味着事务
13247
+ * 回滚之后 artifact 目录里留着一堆没人引用的文件。更根本的是:带 base64 的部件
13248
+ * 说明上游拿错了形态(该给 `loadMessages()` 的输出,给成了喂模型那一份),
13249
+ * 这时候闷头把它写下来只会让错误更晚才暴露。
13250
+ *
13251
+ * ⚠️ 路径判定用 `isAbsolute()`,**跟着本机平台走**。跨系统搬(macOS 的
13252
+ * `/Users/…` 导进 Windows)时路径判定过得去,但那个文件在本机并不存在 ——
13253
+ * 这一层不去 `stat` 它:图片丢了是 `restoreParts` 早就处理好的一档
13254
+ * (退化成「图片已不可用」占位),而为了它多一次磁盘往返不值。
13255
+ */
13256
+ declare function importParts(parts: readonly EpochContentPart[]): ImportPartsResult;
13042
13257
  /**
13043
13258
  * 剥掉 artifact 的 `data`,只留 `path` 引用。
13044
13259
  *
@@ -13051,7 +13266,10 @@ declare function stripArtifactData(artifacts: readonly ToolArtifact[]): ToolArti
13051
13266
  declare function persistToolResults(results: readonly EpochToolResult[]): EpochToolResult[];
13052
13267
 
13053
13268
  /**
13054
- * 会话管理类型 — 对齐 docs/design/session-manager.md
13269
+ * 会话管理类型。
13270
+ *
13271
+ * (原来这里写着「对齐 `docs/design/session-manager.md`」,而那整个目录已随
13272
+ * `5bbf3c8c` 删掉,这条指针一直悬着。)
13055
13273
  *
13056
13274
  * 参考来源:
13057
13275
  * - [Hermes] ~/.hermes/state.db schema
@@ -13224,7 +13442,30 @@ interface SessionMeta {
13224
13442
  * 缺席 = 这段会话没有开着的轮(正常态),以及 v13 之前的所有老库。
13225
13443
  */
13226
13444
  openTurnFrom?: number | null;
13445
+ /**
13446
+ * 这一段**这次运行**结束的时刻。缺席 = 还开着。
13447
+ *
13448
+ * ⚠️ **它不是「这段会话完了」** —— 会话是可恢复的,resume 回到一段已经关掉的
13449
+ * 会话时这一格会被擦掉(`SessionManager.reopen()`)。语义同 `openTurnFrom`
13450
+ * 那一对「开始写下、收尾擦掉」,只是尺度从一轮放大到一次运行。
13451
+ *
13452
+ * ⚠️ **打这一格不算活动**,所以它不推动 {@link updatedAt}(判据在那一格上)。
13453
+ * 保留期清理同时看两格,判据在 `SessionDB.pruneCandidates` 的 ① / ①b。
13454
+ */
13227
13455
  endedAt?: Date;
13456
+ /**
13457
+ * 为什么结束的。
13458
+ *
13459
+ * | 值 | 谁写的 |
13460
+ * | --------------- | -------------------------------------------------------- |
13461
+ * | `user_stop` | 用户显式停止 |
13462
+ * | `max_turns` | 撞上轮数上限 |
13463
+ * | `error` | 出错收尾 |
13464
+ * | `process_exit` | 进程干净退出时统一打的(`SessionStore.endOpenSessions()`)|
13465
+ * | `orphan_sweep` | 维护扫除超期孤儿(`SessionDB.sweepOrphanedSessions()`) |
13466
+ *
13467
+ * 后两个 2026-09-17 加的,判据见那两个方法。
13468
+ */
13228
13469
  endReason?: string;
13229
13470
  }
13230
13471
  /**
@@ -13354,9 +13595,32 @@ interface ListSessionsInput {
13354
13595
  */
13355
13596
  sortKey?: 'startedAt' | 'updatedAt' | 'messageCount' | 'title';
13356
13597
  direction?: 'asc' | 'desc';
13357
- archived?: boolean;
13598
+ /**
13599
+ * **三态,不是二态** —— `undefined` 和 `false` 是同一个意思(只列没归档的),
13600
+ * 所以在 `'any'` 之前,「归档的和没归档的一起列」这句话**没有任何写法能表达**。
13601
+ * 判据在 `SessionDB.listSessions` 的 `archived` 分支上:`!== undefined` 才拼
13602
+ * `AND archived = @archived`,`undefined` 走的 `else` 拼的是 `AND archived = 0`。
13603
+ *
13604
+ * | 值 | 列哪些 |
13605
+ * | --- | --- |
13606
+ * | `undefined` / `false` | 只列没归档的 |
13607
+ * | `true` | **只**列归档的 |
13608
+ * | `'any'` | 两边都列 |
13609
+ *
13610
+ * 要「一次列全」的是增量备份这类调用方:它问的是「这台机器上现在有哪些会话」,
13611
+ * 归没归档是会话自己的一个属性,漏掉归档的那批等于备份缺行。
13612
+ */
13613
+ archived?: boolean | 'any';
13358
13614
  pinnedOnly?: boolean;
13359
13615
  cwd?: string;
13616
+ /**
13617
+ * 只列 `updatedAt` **严格晚于**这个时刻的(ms 时间戳)。给增量拉取用。
13618
+ *
13619
+ * ⚠️ 严格 `>` 意味着**同毫秒的行会漏** —— 把上一趟拿到的最大 `updatedAt` 原样
13620
+ * 当下一趟的水位线,会漏掉和它同一毫秒落下的那些行。调用方要自己往回退一点
13621
+ * 再传进来(我们这边的同步层退 2s),代价只是重复拉几行、而那是幂等的。
13622
+ */
13623
+ updatedSince?: number;
13360
13624
  }
13361
13625
  interface ListSessionsOutput {
13362
13626
  sessions: SessionMeta[];
@@ -13398,9 +13662,126 @@ interface SessionStats {
13398
13662
  totalCostUsd: number;
13399
13663
  avgMessagesPerSession: number;
13400
13664
  }
13665
+ /**
13666
+ * 导入一条消息。
13667
+ *
13668
+ * **和 {@link AppendMessageInput} 差在 `id` / `timestamp` 由调用方给** —— 这正是
13669
+ * 「导入」和「追加」的分界:追加是此刻发生的事,时刻由库说了算;导入是搬运已经
13670
+ * 发生过的事,时刻由来源说了算,库把它逐字收下。
13671
+ *
13672
+ * ⚠️ `parts` 收的是 **{@link EpochContentPart},不是 `PersistedPart`** —— 因为
13673
+ * 导入的上游是 `SessionStore.loadMessages()` 读出来的内存形态。两者的图片格式
13674
+ * 不通:读侧吐的是绝对路径字符串,而 `persistParts()` 会把任何不带协议头的
13675
+ * 字符串当 base64 写进磁盘。转换走 `importParts()`,判据写在那个函数上。
13676
+ */
13677
+ interface ImportMessage extends Omit<AppendMessageInput, 'parts'> {
13678
+ /**
13679
+ * 这条消息在**来源库**里的 id。
13680
+ *
13681
+ * ⚠️ **本机不会用这个号。** `messages.id` 是 `INTEGER PRIMARY KEY AUTOINCREMENT`,
13682
+ * 全库共享一条序列,两台机器的号段必然撞,所以导入一律重新发号。传它进来是为了
13683
+ * 拿回 {@link ImportSessionResult.idMap} —— 调用方那边(同步水位线、去重表)
13684
+ * 记的是来源的号,得有个东西把两边接上。
13685
+ *
13686
+ * **{@link timestamp} 和这一批的先后次序一个都不动**:会话读回来是按
13687
+ * `(timestamp, id)` 排的,次序才是语义,号只是句柄。
13688
+ */
13689
+ id: number;
13690
+ /** 这条消息原本发生的时刻(ms)。**逐字落库**,不拿挂钟顶替 */
13691
+ timestamp: number;
13692
+ /** 多模态部件的**内存**形态(图片是绝对路径或 http(s) URL,**不许是 base64**) */
13693
+ parts?: EpochContentPart[];
13694
+ }
13695
+ /**
13696
+ * 导入一段会话的元数据。
13697
+ *
13698
+ * 时刻一律用 ms 数字而不是 `Date`:这些值是跨进程/跨机器搬过来的,
13699
+ * 路上只会是数字,在这一层收 `Date` 等于逼每个调用方先 `new Date()` 再被
13700
+ * 实现 `.getTime()` 回去。
13701
+ */
13702
+ interface ImportSessionMeta {
13703
+ /** 由调用方指定,**不是**库发的。已经存在时导入会被拒,见 `ImportSessionResult` */
13704
+ id: string;
13705
+ title: string;
13706
+ model: string;
13707
+ startedAt: number;
13708
+ /** 最后活动时刻。语义逐字见 {@link SessionMeta.updatedAt}(动 = 产生内容或花掉钱) */
13709
+ updatedAt: number;
13710
+ endedAt?: number;
13711
+ endReason?: string;
13712
+ source?: string;
13713
+ cwd?: string;
13714
+ workspaceState?: SessionMeta['workspaceState'];
13715
+ workspaceRoot?: string;
13716
+ gitBranch?: string;
13717
+ gitRepoRoot?: string;
13718
+ /**
13719
+ * ⚠️ **这里没有 `systemPrompt`**,和 {@link CreateSessionInput} 不一样。
13720
+ * 那边的 `systemPrompt` 不是一列,是一条 `role: 'system'` 的消息
13721
+ * (`SessionManager.create()` 收到它就 `appendMessage`),所以搬运时它**已经在
13722
+ * {@link ImportSessionInput.messages} 里**了 —— 再开一格就会导进去两份。
13723
+ */
13724
+ displayName?: string;
13725
+ pinned?: boolean;
13726
+ archived?: boolean;
13727
+ /**
13728
+ * 父会话。**本机没有这一行时会被静默丢掉**,不是报错 —— `sessions.parent_id`
13729
+ * 是真外键(`REFERENCES sessions(id)`,且 `foreign_keys = ON`),留着会让整条
13730
+ * 导入事务失败。丢了父指针的会话本身是完整的,为一个装饰性的指针把整段会话
13731
+ * 挡在门外不划算。丢没丢由 {@link ImportSessionResult.droppedParentId} 报出来。
13732
+ */
13733
+ parentId?: string;
13734
+ }
13735
+ interface ImportSessionInput {
13736
+ meta: ImportSessionMeta;
13737
+ /** 按时间正序。空数组合法(一段还没说话的会话也是会话) */
13738
+ messages: ImportMessage[];
13739
+ }
13740
+ /**
13741
+ * 导入的结果。
13742
+ *
13743
+ * **失败不抛,用 `ok: false` 回**:导入是批量搬运,调用方要的是「这一批里哪几段
13744
+ * 没进去、为什么」,而不是第一段出问题就整批断掉。
13745
+ *
13746
+ * `reason` 是**机器可读的标识符**,不是给人看的文案 —— 文案归调用方那层的 i18n。
13747
+ */
13748
+ type ImportSessionResult = {
13749
+ ok: true;
13750
+ id: string;
13751
+ /** 真写进去几条消息 */
13752
+ messageCount: number;
13753
+ /**
13754
+ * `来源 id -> 本机 id`。消息 id **一律重发**(理由见 {@link ImportMessage.id}),
13755
+ * 所以这一格总是在,空会话时是个空对象。
13756
+ */
13757
+ idMap: Record<number, number>;
13758
+ /** 父指针被丢掉了的话,这里是被丢掉的那个 id。见 `ImportSessionMeta.parentId` */
13759
+ droppedParentId?: string;
13760
+ } | {
13761
+ ok: false;
13762
+ id: string;
13763
+ /**
13764
+ * | 值 | 意思 |
13765
+ * | --- | --- |
13766
+ * | `exists` | 本机已经有这个 id 了。**不合并、不覆盖** —— 两边都是用户的数据,这一层没有判断谁新谁旧的依据 |
13767
+ * | `invalid` | 入参自己不成立(空 id、时刻不是有限数、`parts` 里带 base64 …) |
13768
+ * | `failed` | 写库时抛了。事务已回滚,库里没有半段会话 |
13769
+ */
13770
+ reason: 'exists' | 'invalid' | 'failed';
13771
+ /** 机器可读的补充定位(字段名 / 消息 id 之类),**不是文案** */
13772
+ detail?: string;
13773
+ };
13401
13774
  interface SessionManager$1 {
13402
13775
  create(input?: CreateSessionInput): Session;
13403
13776
  get(id: string): Session | undefined;
13777
+ /**
13778
+ * 库里有没有这一行。**和 `get()` 不是一回事**:那个会把整段消息读出来,
13779
+ * 而问「在不在」的调用方(`SessionStore.ensure()`)一条消息都不需要。
13780
+ *
13781
+ * 判据全文在 `SessionDB.hasSession` 上 —— 一句话:它是用来把「已经存在」
13782
+ * 和「写不进去」分开的,而那两件事在 `catch` 里长得一模一样。
13783
+ */
13784
+ has(id: string): boolean;
13404
13785
  updateMeta(id: string, patch: Partial<SessionMeta>): void;
13405
13786
  archive(id: string): void;
13406
13787
  unarchive(id: string): void;
@@ -13410,7 +13791,32 @@ interface SessionManager$1 {
13410
13791
  */
13411
13792
  delete(id: string): boolean;
13412
13793
  endSession(id: string, reason?: string): void;
13794
+ /** 擦掉结束标记(resume 回到一段已关闭的会话)。见 `SessionMeta.endedAt` */
13795
+ reopen(id: string): void;
13796
+ /** 退出时给本进程碰过的会话统一打结束标记。返回打了几段,**从不抛** */
13797
+ endTouchedSessions(reason?: string): number;
13413
13798
  list(input?: ListSessionsInput): ListSessionsOutput;
13799
+ /**
13800
+ * 把别处的一整段会话原样搬进本机库(2026-09-20,给跨机同步用)。
13801
+ *
13802
+ * 和 `create()` + N 次 `appendMessage()` 的差别,三条都是刻意的:
13803
+ *
13804
+ * 1. **不跑智能体、不切当前会话、不发任何事件** —— 它是一次纯写库
13805
+ * 2. **id 和每条消息的 `timestamp` 由调用方给**,库不拿挂钟顶替
13806
+ * 3. **撞 id 就拒**(`reason: 'exists'`),不悄悄合并也不覆盖 ——
13807
+ * 两边都是用户的数据,这一层没有判断谁该赢的依据
13808
+ *
13809
+ * 整段会话 + 全部消息在**一个事务**里落地:要么整段进去,要么一行都不留。
13810
+ *
13811
+ * **不搬**两样东西,都是因为搬过来就是撒谎:
13812
+ * - `estimatedCostUsd` —— 它靠 `priced_call_count` 区分「零」和「不知道」,
13813
+ * 搬一个数过来会把「这台机器从没给它算过钱」变成「算过,是这个数」
13814
+ * - 压缩状态(`summary` 和消息的 `active`/`compacted` 标记)—— 落库的消息
13815
+ * 一律 `active=1, compacted=0`,只搬摘要不搬标记会让同一段内容喂给模型两遍
13816
+ *
13817
+ * 这两条不是缺口,是这一版的口径;要改得连着各自的伴生列一起改。
13818
+ */
13819
+ importSession(input: ImportSessionInput): ImportSessionResult;
13414
13820
  search(input: SearchInput): SearchOutput;
13415
13821
  /** @returns 这条消息的 DB id(按步增量落盘要它,见实现处) */
13416
13822
  appendMessage(sessionId: string, msg: AppendMessageInput): number;
@@ -13445,6 +13851,20 @@ interface SessionManager$1 {
13445
13851
 
13446
13852
  declare class SessionManager implements SessionManager$1 {
13447
13853
  private db;
13854
+ /**
13855
+ * 这个进程**碰过**的会话 id —— {@link endTouchedSessions} 退出时照着它打标记。
13856
+ *
13857
+ * ## 口径:和 `SessionMeta.updatedAt` 那条「什么算活动」对齐
13858
+ *
13859
+ * 只有 {@link create}(建出来了)/ {@link appendMessage}(产生内容)/
13860
+ * {@link recordUsage}(花掉钱)这三处往里加。**读不算**:`epoch sessions list`
13861
+ * 逐个 `get()` 一遍之后,不该把全库都判成「这个进程开着的」,那样退出时会
13862
+ * 给一百段陈年会话统统盖上今天的 `ended_at`,等于把它们的清理倒计时集体重置。
13863
+ *
13864
+ * ⚠️ 只活在内存里,也只该活在内存里:它回答的是「**本进程**手上有谁」,
13865
+ * 而进程没了这个问题就不存在了 —— 那时该问的是库里那格 `ended_at`。
13866
+ */
13867
+ private readonly touched;
13448
13868
  /**
13449
13869
  * 开给**模型**那一侧的检索层(方案 48)。
13450
13870
  *
@@ -13504,6 +13924,8 @@ declare class SessionManager implements SessionManager$1 {
13504
13924
  private generateId;
13505
13925
  create(input?: CreateSessionInput): Session;
13506
13926
  get(id: string): Session | undefined;
13927
+ /** 判据全文在 {@link SessionDB.hasSession} 上 */
13928
+ has(id: string): boolean;
13507
13929
  /**
13508
13930
  * 最近的一个会话(`epoch -r` / `sessions resume` 不带 id 时落到这里)。
13509
13931
  *
@@ -13539,6 +13961,12 @@ declare class SessionManager implements SessionManager$1 {
13539
13961
  */
13540
13962
  getLatestByCwd(cwd: string): Session | undefined;
13541
13963
  list(input?: ListSessionsInput): ListSessionsOutput;
13964
+ /**
13965
+ * 把别处的一整段会话搬进本机库。语义、口径、以及两样**刻意不搬**的东西
13966
+ * (花费和压缩状态)逐字见 {@link ISessionManager.importSession} —— 这里只记
13967
+ * 实现上的三处判断。
13968
+ */
13969
+ importSession(input: ImportSessionInput): ImportSessionResult;
13542
13970
  updateMeta(id: string, patch: Partial<SessionMeta>): void;
13543
13971
  archive(id: string): void;
13544
13972
  unarchive(id: string): void;
@@ -13559,6 +13987,18 @@ declare class SessionManager implements SessionManager$1 {
13559
13987
  olderThanMs: number;
13560
13988
  includePinned?: boolean;
13561
13989
  }): number;
13990
+ /**
13991
+ * 关掉超期还开着的会话(崩溃残留)。判据全文在
13992
+ * {@link SessionDB.sweepOrphanedSessions} 上 —— 尤其「凭什么敢关」那一节。
13993
+ *
13994
+ * @returns 关掉了几段
13995
+ */
13996
+ sweepOrphans(input: {
13997
+ olderThanMs: number;
13998
+ now: number;
13999
+ }): number;
14000
+ /** 擦掉结束标记(resume 回到一段已关闭的会话)。见 {@link SessionDB.reopenSession} */
14001
+ reopen(id: string): void;
13562
14002
  /** `VACUUM` 能还回来的比例。判据在 {@link SessionDB.freelistRatio} 上 */
13563
14003
  freelistRatio(): number;
13564
14004
  /**
@@ -13583,6 +14023,11 @@ declare class SessionManager implements SessionManager$1 {
13583
14023
  * ⚠️ **第一道和后两道不是一回事**:关掉 `autoPrune` 之后手动那条
13584
14024
  * (`epoch sessions prune`)照常能用,那条路上一道节流都没有 ——
13585
14025
  * 给用户亲手敲的命令加「你上周刚跑过」说不通。
14026
+ *
14027
+ * ## 它做两件事,不是一件(2026-09-17)
14028
+ *
14029
+ * 先**扫孤儿**({@link SessionDB.sweepOrphanedSessions})再**选候选**。
14030
+ * 顺序和「为什么这一轮扫到的这一轮删不掉」写在底下那段块注释上。
13586
14031
  */
13587
14032
  maybeAutoPrune(opts: {
13588
14033
  enabled: boolean;
@@ -13596,10 +14041,48 @@ declare class SessionManager implements SessionManager$1 {
13596
14041
  now?: () => number;
13597
14042
  }): {
13598
14043
  skipped: boolean;
14044
+ swept: number;
13599
14045
  pruned: number;
13600
14046
  vacuumed: boolean;
13601
14047
  error?: string;
13602
14048
  };
14049
+ /**
14050
+ * attachment 的保留期兜底(2026-09-21)。**从不抛**,同 {@link maybeAutoPrune}。
14051
+ *
14052
+ * ## 它补的是一条「写了却执行不到」的保留期
14053
+ *
14054
+ * `ATTACHMENT_RETENTION_DEFAULTS` 写着 7 天 / 512MB,而在这之前,全仓**唯一**
14055
+ * 调到 `pruneAttachments` 的地方是附件上传那个 HTTP handler
14056
+ * (`server/src/attachments.ts`)。于是那条保留期挂在一个用户可能再也不做的
14057
+ * 动作上:**传过一次、之后不再传,那批附件就永远留着**。
14058
+ *
14059
+ * 实测(2026-09-21):一个 9 月 11 日的会话目录,1.0G / 52 个文件,10 天后
14060
+ * 还在盘上 —— 两条线都破了,就因为那之后没人再传过附件。
14061
+ *
14062
+ * ## ⚠️ 为什么不挂在启动上
14063
+ *
14064
+ * 那条路被否过,理由在 `runtime/src/build.ts` 的 `buildAttachmentControl` 上:
14065
+ * 一个开着不关的 `epoch web` 永远不清。但被选中的那条有一个对称的洞(上面
14066
+ * 那段),而「不再传附件」比「不重启」常见得多。所以这一条挂在**开新会话**
14067
+ * 那一刻(`SessionStore.ensure()`):不传附件照样开新会话,开着不关也照样
14068
+ * 开新会话,两个洞同时堵上。
14069
+ *
14070
+ * 上传那条路上的 prune **保留**,不替换:它便宜,而且在频繁上传时比一天
14071
+ * 一次及时。这一条是兜底。
14072
+ *
14073
+ * ## ⚠️ `root` 由调用方给
14074
+ *
14075
+ * 同 {@link deleteSession} 那条:**core 不认识家目录布局**,`attachmentsDir()`
14076
+ * 是 infra 的事。这一层只负责「节流 + 调清理」。
14077
+ *
14078
+ * @param root attachments 根目录(不带 sessionId 的那一层)
14079
+ * @param keepSession 当前会话,永不清
14080
+ * @returns 删掉的会话目录数;被节流挡下或失败时 0
14081
+ */
14082
+ maybePruneAttachments(root: string, keepSession: string, opts?: {
14083
+ minIntervalMs?: number;
14084
+ now?: () => number;
14085
+ }): number;
13603
14086
  /**
13604
14087
  * 真删一段会话(方案 30 §2.2)。**不可撤销**,调用方要先跟用户确认过。
13605
14088
  *
@@ -13628,6 +14111,38 @@ declare class SessionManager implements SessionManager$1 {
13628
14111
  delete(id: string): boolean;
13629
14112
  /** 标记会话结束,记录结束时间和原因 */
13630
14113
  endSession(id: string, reason?: SessionMeta['endReason']): void;
14114
+ /**
14115
+ * 进程干净退出时,把**本进程碰过的**会话全部打上结束标记(2026-09-17)。
14116
+ *
14117
+ * ## 它补的是一条断链,而那条断链让整个保留期清理成了空转
14118
+ *
14119
+ * {@link endSession} 从写下来那天起**一个生产调用点都没有** —— 2026-09-17
14120
+ * 全仓 grep 只有用例在调,真库实测 **100 段会话里 `ended_at` 非空 0 段**。
14121
+ * 而 {@link SessionDB.pruneCandidates} 的第一道硬闸是 `ended_at IS NOT NULL`,
14122
+ * 于是 `epoch sessions prune` 和开机自动清理**恒选中 0 段**:方案 64 PR-4
14123
+ * 那三格配置接是接上了,却一格都推不动任何东西。
14124
+ *
14125
+ * ⚠️ 这和方案 64 自己要修的那条是**同一个形状**(「读侧全在岗、
14126
+ * 写侧零生产调用点」),只是换了一列 —— 那一份的 §零 逐字写着这句话。
14127
+ *
14128
+ * ## 为什么尺度是「进程退出」,不是「这轮完了」也不是「用户说删」
14129
+ *
14130
+ * 会话是可恢复的,所以 `ended_at` 只能记「**这次运行**结束了」。
14131
+ * 再细一档(每轮收尾就写)会让它退化成 `updatedAt` 的冗余副本,「结束」这个词
14132
+ * 失去含义;再粗一档(只有显式操作才写)等于要求用户手动收工,而没人会做 ——
14133
+ * 那道闸就照旧近似永远关着。接回来的那一下由
14134
+ * `SessionStore.ensure()` 擦掉标记(判据在那儿)。
14135
+ *
14136
+ * ## ⚠️ 它**从不抛**,而且挡不住 `kill -9`
14137
+ *
14138
+ * 它跑在退出路径上:一段会话没打上标记的代价只是「它晚一个保留期才被清理」,
14139
+ * 而抛出去的代价是进程退不干净。所以逐个 try,坏一个不碍着其余。
14140
+ * 强杀 / 崩溃那一档这里一行都跑不到 —— 那是 {@link sweepOrphans} 的差事,
14141
+ * **两者合起来才盖得全**,缺哪一半都会让一批会话永远留在库里。
14142
+ *
14143
+ * @returns 打上标记的会话数
14144
+ */
14145
+ endTouchedSessions(reason?: SessionMeta['endReason']): number;
13631
14146
  /**
13632
14147
  * @returns 这条消息的 DB id。按步增量落盘(2026-09-16)之后两处要它:
13633
14148
  * 「在飞那一轮从哪条起」的水位线,以及收尾时把这一轮的账挂到**最后一条
@@ -13758,6 +14273,48 @@ declare function buildFtsMatchQuery(safeQuery: string): string;
13758
14273
  */
13759
14274
  declare function buildTrigramMatchQuery(safeQuery: string): string;
13760
14275
 
14276
+ /**
14277
+ * 落盘失败的**分档**(2026-09-21)。
14278
+ *
14279
+ * ## 为什么需要它
14280
+ *
14281
+ * `SessionStore` 那一排 `catch` 把所有写失败都吞成同一个 `false`,而用户侧只有
14282
+ * 一句固定文案:「磁盘满了、或者会话库正被另一个程序占着」。那句话是**猜的** ——
14283
+ * 代码从来没有看过错误码。代价在 2026-09-21 那次排查上付清了:真实原因是
14284
+ * `SQLITE_CONSTRAINT_PRIMARYKEY`(消息 id 撞号,判据在 `SessionDB.insertMessage`
14285
+ * 上),而照着文案去查磁盘和文件锁,`df` / `lsof` 全是干净的,方向整个是错的。
14286
+ *
14287
+ * ## ⚠️ 这和 `SessionDB.hasSession` 上那条「别按错误码分档」不冲突
14288
+ *
14289
+ * 那一条针对的是**「这行在不在」**:它有真源可问(`SELECT 1`),去猜驱动怎么
14290
+ * 编码约束冲突是舍近求远。这里问的是**「为什么写不进去」**,没有任何一处可以
14291
+ * 事后问出来 —— 驱动给的那个码就是唯一的证据。两者的判据正相反。
14292
+ *
14293
+ * 分档只用来**选一句话说给用户**和**决定值不值得重试**,不参与任何数据判断;
14294
+ * 认不出来的一律落 `unknown`,原始错误照旧原样进日志。
14295
+ */
14296
+ /**
14297
+ * 写不进去的原因,按**用户能做什么**分,不按驱动的错误码分。
14298
+ *
14299
+ * - `disk-full`:腾空间,能当场好
14300
+ * - `locked`:别的进程占着,**多半是暂时的** —— 唯一值得重试的一档
14301
+ * - `io-error`:库所在的位置本身写不稳 —— 云同步目录 / 网络盘 / 被实时扫描
14302
+ * - `read-only`:权限 / 只读挂载,要人去改
14303
+ * - `corrupt`:库坏了,要恢复或重建
14304
+ * - `unknown`:认不出来。**包括 `SQLITE_CONSTRAINT`** —— 那不是环境问题而是
14305
+ * 我们自己的 bug(id 撞号那一档就长这样),文案里会把原始错误码带出来
14306
+ */
14307
+ type PersistFailureKind = 'disk-full' | 'locked' | 'io-error' | 'read-only' | 'corrupt' | 'unknown';
14308
+ /**
14309
+ * 认码分档。前缀匹配 —— SQLite 的扩展码是 `SQLITE_BUSY_SNAPSHOT` 这种
14310
+ * 「基础码_细分」的形状,按前缀收就不用把细分码一个个列出来。
14311
+ */
14312
+ declare function classifyPersistFailure(cause: unknown): PersistFailureKind;
14313
+ /** 值不值得再试一次。判据(以及为什么只有这一档)在 `SessionStore.retrying` 上 */
14314
+ declare function isTransientPersistFailure(kind: PersistFailureKind): boolean;
14315
+ /** 原始错误码,进不了分档时原样带给用户。认不出来时空串 */
14316
+ declare function persistFailureCode(cause: unknown): string;
14317
+
13761
14318
  /**
13762
14319
  * 把 `<current_goal>` 接到发出去那份 system prompt 的末尾(方案 52 PR-2)。
13763
14320
  *
@@ -15384,7 +15941,13 @@ type ScheduleIssueCode =
15384
15941
  | 'date-range-on-once'
15385
15942
  /** 清单里有一条规则写错了(`detail` 是 `rule-validate` 给的位置与原因) */
15386
15943
  | 'rule-invalid'
15387
- /** 「跳过全部检查」+ 空工作区。`bypass` + 不确定的 cwd 就是「无边界」的字面意思 */
15944
+ /**
15945
+ * 「跳过全部检查」+ 空工作区。
15946
+ *
15947
+ * ⚠️ **2026-09-18 起没有产出点了** —— 空着落到的是 `~/.epoch/automation/<id>/`,
15948
+ * 一个确定、专属、隔离的目录,不是「不确定的 cwd」。判据全文在
15949
+ * `validate.ts` 的 `bypassIssues()` 第 1 条上。保留这条 code 是为了不破坏协议。
15950
+ */
15388
15951
  | 'bypass-needs-workdir'
15389
15952
  /** 「跳过全部检查」的工作区指到了家目录本身 —— 那和不绑定没有区别 */
15390
15953
  | 'bypass-workdir-too-broad'
@@ -15415,6 +15978,15 @@ interface CreateScheduleInput {
15415
15978
  /** 不给就落到 `~/.epoch/automation/<id>/`(协议上 `workDir` 那段写了理由) */
15416
15979
  workDir?: string;
15417
15980
  model?: string;
15981
+ /**
15982
+ * 「召唤专家」——这条任务用哪个身份跑(2026-09-17 接通)。
15983
+ *
15984
+ * ⚠️ **这一格以前不在这个类型上,而 `ScheduleDefinition.role` 一直在** ——
15985
+ * 于是调用方用展开语法(`...(x ? { role: x } : {})`)写进来时 TS **不报**
15986
+ * (多余属性检查对展开不生效),值走到这儿被**静默丢掉**。
15987
+ * 那正是这一格「库里有列、类型里有位、就是永远没有值」的最后一段。
15988
+ */
15989
+ role?: string;
15418
15990
  permission: PermissionLevel;
15419
15991
  allowTools?: readonly string[];
15420
15992
  allowOperations?: readonly OperationType[];
@@ -15423,6 +15995,15 @@ interface CreateScheduleInput {
15423
15995
  /** **必填**,没有默认值 */
15424
15996
  maxBudgetUsd: number;
15425
15997
  timeoutMs?: number;
15998
+ /**
15999
+ * 跑完的会话直接进会话列表吗。缺省 `false` = 收起来(归档),
16000
+ * 判据全文在 `ScheduleDefinition.showInSessionList` 上。
16001
+ *
16002
+ * ⚠️ **这一格必须在这个类型上**,不能只在 `ScheduleDefinition` 上有位 ——
16003
+ * 判据逐字同上面 `role` 那段:调用方用展开语法写进来时 TS 不报,
16004
+ * 值会被静默丢掉,而表现是「勾了没用」。
16005
+ */
16006
+ showInSessionList?: boolean;
15426
16007
  trigger: ScheduleTrigger;
15427
16008
  startDate?: string;
15428
16009
  endDate?: string;
@@ -15459,18 +16040,28 @@ interface CreateScheduleInput {
15459
16040
  * `ScheduleControl.update` 解析掉;**`ScheduleStore.update` 的入参不收它**
15460
16041
  * (同 `create(input & { workDir: string })` 那条契约,收窄在编译期)。
15461
16042
  */
15462
- type UpdateScheduleInput = Partial<Omit<CreateScheduleInput, 'maxBudgetUsd' | 'workDir' | 'model' | 'startDate' | 'endDate'>> & {
16043
+ type UpdateScheduleInput = Partial<Omit<CreateScheduleInput, 'maxBudgetUsd' | 'workDir' | 'model' | 'role' | 'startDate' | 'endDate'>> & {
15463
16044
  maxBudgetUsd?: number;
15464
16045
  /** `null` = 不绑工作区了 → 落回 `~/.epoch/automation/<id>/`,**不是**删掉这一格 */
15465
16046
  workDir?: string | null;
15466
16047
  model?: string | null;
16048
+ /** `null` = 回到默认 agent */
16049
+ role?: string | null;
15467
16050
  startDate?: string | null;
15468
16051
  endDate?: string | null;
15469
16052
  };
15470
16053
  /**
15471
- * 三把尺子的缺省值。
16054
+ * 三把尺子的缺省值 —— **「调 API / CLI 没给这一格时引擎用什么」**。
16055
+ *
16056
+ * ## ⚠️ `maxBudgetUsd` **不在这里**,而 2026-09-18 之后这句话更要紧了
16057
+ *
16058
+ * 它没有引擎兜底:没给就是一条 `budget-required`(网线上 400,CLI 上必给 `--budget`)。
15472
16059
  *
15473
- * `maxBudgetUsd` **不在这里**,那是刻意的 —— 它没有缺省值。
16060
+ * 那一天新建**表单**上它开始预填 200 了,而那是**另一份缺省**
16061
+ * (protocol 的 `WireScheduleDefaults.maxBudgetUsd`,判据全文在那个接口上):
16062
+ * 一份说「表单打开时格子里印什么」,一份说「没给值时引擎用什么」。
16063
+ * 把 200 抄进这一份的表现是**网线那一道闸整个消失** —— 任何一个不经表单的调用方
16064
+ * 从此都能建出一条没人想过预算的任务,而那正是这一格的缺席拦着的事。
15474
16065
  */
15475
16066
  declare const SCHEDULE_DEFAULTS: {
15476
16067
  /**
@@ -15494,9 +16085,40 @@ declare const SCHEDULE_DEFAULTS: {
15494
16085
  * 那一格自己填一个数。
15495
16086
  */
15496
16087
  readonly maxTurns: 0;
15497
- /** 15 分钟。唯一能拦住「一条命令挂住了」的那把尺子 */
16088
+ /**
16089
+ * 墙钟超时。唯一能拦住「一条命令挂住了」的那把尺子 —— 前两把在那种情形下
16090
+ * 都不增长(轮次不动、花费不动)。
16091
+ *
16092
+ * ⚠️ **2026-09-18 从 15 分钟抬到 60 分钟**(用户定的)。15 分钟那条线当初是
16093
+ * 照着「一次巡检」估的,而它砍掉的不是跑飞,是**本来就要跑久的那种任务**:
16094
+ * 一条被这把尺子掐断的运行和跑飞长得一模一样(都是 `timeout`),
16095
+ * 而定时任务的反馈回路按天算 —— 第二天早上看到的只有「超时了」三个字。
16096
+ *
16097
+ * 兜住真正跑飞的是必填的 `maxBudgetUsd`(钱是比时间准的尺子),
16098
+ * 判据同上面 `maxTurns` 那一段。
16099
+ *
16100
+ * ⚠️ 这个数**两条路共用**(CLI 不给 `--timeout`、表单预填,都读它)——
16101
+ * 在服务端那侧另写一份的表现,`runtime/schedule/control.ts` 那段注释记着:
16102
+ * 「表单预填 200、直接调这个 API 却得到 20」。
16103
+ */
15498
16104
  readonly timeoutMs: number;
15499
16105
  };
16106
+ /**
16107
+ * 新建**表单**里预算那一格印什么(2026-09-18,用户定的 200 美元)。
16108
+ *
16109
+ * ## ⚠️ 它**刻意不在** {@link SCHEDULE_DEFAULTS} 里,这一条是承重的
16110
+ *
16111
+ * 那一份答的是「调 API / CLI 没给这一格时引擎用什么」,而这一格**没有**那种兜底:
16112
+ * 网线上没给预算就是 400(`budget-required`),CLI 上 `--budget` 照旧必给。
16113
+ *
16114
+ * 这一份答的是另一个问题:「表单打开时那个格子里印着什么」。两者混成一份的表现是
16115
+ * 网线那道闸整个消失 —— 任何一个不经表单的调用方从此都能建出一条没人想过预算的
16116
+ * 任务,而定时任务是没人看着的(一觉醒来那笔账已经花完了)。
16117
+ *
16118
+ * 判据全文、以及这个数撤掉了方案 45 §3.5 的哪一半,写在 protocol 的
16119
+ * `WireScheduleDefaults` 上。
16120
+ */
16121
+ declare const SCHEDULE_FORM_BUDGET_USD = 200;
15500
16122
  /**
15501
16123
  * 新建任务时预填的最小清单(方案 45 §3.2 的落点)。
15502
16124
  *
@@ -15615,6 +16237,22 @@ declare class ScheduleStore {
15615
16237
  recordRun(input: RecordRunInput): ScheduleRun;
15616
16238
  /** 最近 N 次运行,最新的在前 */
15617
16239
  listRuns(scheduleId: string, limit?: number): ScheduleRun[];
16240
+ /**
16241
+ * 这个任务**最近 N 次运行留下的会话 id**,最新的在前。
16242
+ *
16243
+ * 执行器收尾时拿它去删(缺省不留会话,判据在 runtime 的 `dropSessions` 上)。
16244
+ *
16245
+ * ## 三件刻意的事
16246
+ *
16247
+ * 1. **只回有会话的那几次**(`session_id IS NOT NULL`):三种 `skipped-*` 和
16248
+ * `missed` 压根没起过会话,让它们占掉名额的话,`limit: 2` 会在「昨天跳过
16249
+ * 两次」之后**一条真会话都翻不到**,而那正是要收的残骸。
16250
+ * 2. **回的是 id 不是整行**:调用方只拿它去 `delete()`,交出整行等于多给它
16251
+ * 一堆用不着的字段(以及一个「顺手改点别的」的机会)。
16252
+ * 3. **`schedule_runs` 那一行本身不删**:状态 / 花费 / 欠条永远留着 ——
16253
+ * 被清掉的只是「点开能看的内容」。
16254
+ */
16255
+ recordedSessions(scheduleId: string, limit?: number): string[];
15618
16256
  /**
15619
16257
  * 全部任务的最近运行,最新的在前(运行记录那个 tab / TUI 启动提示要的那份)。
15620
16258
  */
@@ -18713,46 +19351,21 @@ declare function pendingImageTokens(messages: readonly EpochMessage[]): number;
18713
19351
  *
18714
19352
  * ---
18715
19353
  *
18716
- * # ✅ 2026-08-16 合并时收掉了(原文是一张 📮,留着当判据)
18717
- *
18718
- * 那一行接上了:`runtime/src/services.ts` 的 `new ContextCompressor()` 现在带着
18719
- * `...compressionOptions(config)`,收的那一笔在那儿的注释里点名回指了这张 📮。
18720
- * **下面这一整段原文一个字没改** —— 它是判据(「不收的后果是一句谎话」),
18721
- * 不是待办;哪天有人重构那个装配点,该重读的就是它。
18722
- *
18723
- * ---
18724
- *
18725
- * **写这张 📮 的那一轮的禁区是 `packages/runtime/**`,而这个类的装配点正在那儿。**
18726
- * 所以「配置真的接到压缩器上」这最后一根线,我只做到了给它一个够不错的接头
18727
- * ({@link compressionOptions}),没能接上去。
18728
- *
18729
- * ## 要收的是一处,一行
18730
- *
18731
- * [runtime/src/services.ts](../../../runtime/src/services.ts) 里那个
18732
- * `new ContextCompressor({ summarize })`(`// ---- 上下文压缩 ----` 那一段):
18733
- *
18734
- * ```ts
18735
- * new ContextCompressor({
18736
- * ...compressionOptions(config), // ← 加这一行
18737
- * summarize: async (prompt) => { … },
18738
- * })
18739
- * ```
18740
- *
18741
- * ## 为什么不能绕过去
18742
- *
18743
- * 三条路(方案 30 §12.1):**绕过去**等于在 core 里自己读一遍配置 ——
18744
- * 而 core 拿不到 `config`,`ContextCompressor` 的构造函数是它唯一的入口;
18745
- * **伸手改**是直接动 runtime,合并必冲突。所以走第三条。
19354
+ * ## ⚠️ 配置必须在装配点接上来,否则那两个开关是**一句谎话**
18746
19355
  *
18747
- * ## ⚠️ 不收的后果是**一句谎话**,不是少一个功能
19356
+ * `ContextCompressor` 的构造函数是配置进来的唯一入口(core 拿不到 `config`),
19357
+ * 接头是 {@link compressionOptions},装配点在
19358
+ * [runtime/src/services.ts](../../../runtime/src/services.ts):
19359
+ * `new ContextCompressor({ ...compressionOptions(config), summarize })`。
19360
+ * **别把那一行摘掉。**
18748
19361
  *
18749
- * 不收的话:schema 认这两个键、`epoch config set compression.enabled false` 写得进去、
18750
- * 设置页那一行也会把它印出来并标上「② 用户级」—— 而压缩**照压不误**。
19362
+ * 摘掉之后:schema 照认这两个键、`epoch config set compression.enabled false`
19363
+ * 照样写得进去、设置页那一行也会把它印出来并标上「② 用户级」—— 而压缩**照压不误**。
18751
19364
  * 一个配了、界面确认了、却不生效的开关,比压根没有这个开关坏得多:
18752
19365
  * 后者用户会去问,前者他会以为自己已经关掉了。
18753
19366
  *
18754
19367
  * 这正是设计稿连着两轮记「只记不改」时说的那个空壳(判据逐字:「没有配置项就别画
18755
- * 开关」)—— 收掉这一行之前,它只是从「稿子上的空壳」搬成了「配置里的空壳」。
19368
+ * 开关」)—— 那一行没接上之前,它只是从「稿子上的空壳」搬成了「配置里的空壳」。
18756
19369
  */
18757
19370
 
18758
19371
  interface ContextCompressorOptions {
@@ -19504,4 +20117,4 @@ declare function resolveCodeModeWorker(baseDir: string, exists?: typeof existsSy
19504
20117
  */
19505
20118
  declare function codeModeWorkerPath(): string | undefined;
19506
20119
 
19507
- export { AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, type AcquireResult, type AgentConfig, AgentLoop, type AgentProvider, type AgentSite, type AgentSiteRef, type AppendMessageInput, ApprovalCache, type ApprovalDecision, type ApprovalScope, type ArtifactOpenRefusal, type ArtifactRetention, type AskQuestionDeps, type AttachmentRetention, BLOCKED_TOOLS, type BackendOptions, type BackendOutcome, type BackgroundTaskSource, type BaseOrigin, type BaseSlot, type BeginTurnInput, type BreakdownInput, BudgetGuard, type BudgetGuardOptions, type BudgetInfo, type BudgetLevel, type BudgetOptions, type BudgetStatus, BudgetStore, type BudgetStoreOptions, type BuildFireArgvInput, type BuildIndexOptions, CHECKPOINT_MAX_TOTAL_BYTES, CLAUDE_EVENT_NAMES, CLAUDE_TOOL_NAMES, CODE_MODE_LIMITS, CODE_MODE_SDK_TAG, CONFIG_KEYS, CURRENT_CONFIG_VERSION, type CachedApproval, type CachedDecision, type CheckpointCapture, type CheckpointFile, CheckpointManager, type CheckpointManagerOptions, type CheckpointManifest, CheckpointStore, type CheckpointStoreOptions, type CheckpointSummary, type ClaudeHooksParseOptions, type CodeModeLimits, type CodeRequest, type CodeResult, CodeSandbox, type CommandHookConfig, type CommandHookResult, type CommandLoadOutcome, type CommandLoadSummary, type CommandResult, type CommandRunner, type CompactionResult, type CompiledRules, type ComplianceDirSpec, type ComplianceDirsSummary, ComplianceEngine, type ComplianceEngineInput, type ComplianceGate, type ComplianceHit, type ComplianceRule, type ComplianceRuleSource, type ComplianceSettings, type ComplianceVerdict, type CompressConfig, type CompressResult, type ConfigMigration, type ConfigOrigins, ContextCompressor, type ContextEngine, type CreateScheduleInput, type CreateSessionInput, DEFAULT_COMPLIANCE_ACTIONS, DEFAULT_COMPLIANCE_SETTINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_GOAL_MAX_ROUNDS, DEFAULT_MAX_HOLD_CHARS, type DelegateArgs, type DelegateConfig, DelegateManager, type DelegateTaskResult, type DiagnoseOptions, type DiscoverOutcome, type DiscoveredFile, type DoctorReport, type DraftParse, EMPTY_RULES, EPOCH_DISK_LEDGER, EpochConfigSchema, type ExpandOptions, type ExtractOutcome, FTS_TABLES, FTS_TRIGGERS, type FallbackEvent, type FileSlots, type FileSourceKind, type ForkInput, type FrontmatterParse, type FrontmatterSplit, type FtsHealth, type FtsReclaim, type FtsSpace, type FtsTableHealth, GOAL_BLOCK_CODES, type GateAxis, type GateVerdict, type GenerateInput, type GenerateOutput, type Goal, type GoalBlockReason, type GoalClear, type GoalPhase, type GoalPromptView, type GoalRefusal, type GoalRoundResult, GoalService, GoalStore, type GoalToolDeps, type GoalWrite, HEADLESS_AUDIT_CODES, type HeadlessPolicy, type HookConfigEntry, HookManager, type HookManagerOptions, type HookMatcher, type HookSourceKind, type HookSourceStatus, type HookSourcesOptions, type HookSourcesSummary, type HooksParseOutcome, type MemoryManager$1 as IMemoryManager, INSTRUCTION_BUDGET_CHARS, INSTRUCTION_FILES, type SessionManager$1 as ISessionManager, type SkillSystem$1 as ISkillSystem, ImageLoadError, type ImageSize, type ImportDecision, type ImportGate, type ImportNode, type ImportSkipReason, ImportTrustStore, type InstallOptions, type InstallOutcome, type InstallPreview, type InstructionScan, type InstructionSource, type IsolationReason, type IsolationReport, type JsonSchemaDocument, LAUNCHD_LABEL_PREFIX, LOCK_HEARTBEAT_MS, LOCK_STALE_MS, type LastOpenSession, LastOpenSessions, type LayerOutcome, type LayerScalars, type LayerStatus, type LearningContext, type LearningResult, type LearningSkipReason, type LexiconLoadOutcome, type LifecycleOutcome, type ListCandidatesInput, type ListSessionsInput, type ListSessionsOutput, type LoadCommandsOptions, type LoadConfigOptions, type LoadKeybindingsOptions, type LoadKeybindingsResult, type LoadRolesOptions, type LoadedPlugin, type LockHolder, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_LAST_OPEN_SESSIONS, MAX_OBJECTIVE_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, type ManagedPolicy, ManagedPolicyError, type ManagedSettings, ManagedSettingsSchema, type MarketplaceCatalog, type MarketplaceDisplay, type MarketplaceDisplayField, type MarketplaceEntry, type MarketplaceOutcome, type MarketplaceRecord, type MarketplaceStatus, type MemoryConfig, type MemoryEntry, MemoryManager, MemoryReviewer, type MemorySearchResult, type MemoryTarget, type MemoryWriteResult, type MentionPart, type MentionResolution, type Message, type MessageHit, type MessageRecord, type MessageSurface, type ModelCapability, ModelFailureTracker, type ModelMetaEntry, type ModelPricing, type MultimodalPolicy, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, type NonInteractiveProbe, type OsTaskSnapshot, type OutputGuard, PACK_EXCLUDES, PACK_MAX_BYTES, PACK_MAX_FILES, PERMISSION_AUDIT_CODES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_MANIFEST_KEYS, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, PLUGIN_VISIBILITY, POLICY_DECISIONS, PROBE_VERSION, PROJECT_AGENTS_SUBDIR, PROVIDER_NO_CREDENTIAL, type PackFile, type PackLimits, type PackOutcome, type PackPlan, type PackPlanOutcome, type PermissionAuditCode, type PermissionAuditEntry, type PermissionAuditOutcome, type PermissionAuditScope, type PermissionAuditSnapshot, PermissionManager, type PersistedBudget, type PersistedPart, type PlanApprovalFn, type PlanEnterResult, type PlanModeDeps, PlanModeState, type PlanSettlement, type PluginArtifacts, type PluginAuthor, PluginAuthorSchema, type PluginCommandDir, type PluginCounts, type PluginHookFile, type PluginInventory, type PluginLoadOptions, type PluginManifest, type PluginPathRef, type PluginRecord, type PluginSettingsFile, type PluginSourceType, type PluginStateReadOutcome, PluginStore, type PluginVisibility, type PolicyDirSpec, type PolicyDirsSummary, type PolicyLoadOutcome, type PolicyRule, PolicyRuleSchema, type PricingAt, type PricingOverride, type ProjectContext, type ProjectExtensionInventory, ProviderError, ProviderRouter, type ProviderStreamChunk, type ProviderToolCall$1 as ProviderToolCall, type ProviderWarning, type PruneResult, type QuestionAskFn, RECORDING_KEEP_RUNS, RECORDING_MAX_BYTES, ROLE_FRONTMATTER_SCHEMA, RUN_CODE_TOOL, type ReadMessagesInput, type ReadMessagesOutput, type RecentWorkspace, RecentWorkspaces, type RecordRunInput, type RecorderOptions, type RecoveryAction, type RegisterInput, type RegisterOutcome, type RegistrarOptions, type RegistrationPatch, type RepairOutcome, type ResolveMentionsOptions, type ResolveReferenceInput, type ResolveSettingsOptions, type ResolvedCompression, type ResolvedReference, type ResolvedSource, type ResponseFormat, type RestorePartsOptions, type ReviewIssue, type RewindAction, type RewindDrift, type RewindFilePlan, type RewindOptions, type RewindOutcome, type RewindPreview, type RoleCreateFailure, type RoleCreateInput, type RoleCreateOptions, type RoleCreateOutcome, type RoleLoadOutcome, type RoleLoadSummary, type RoleMergeNotice, type RoleMergeResult, type RoleRemoveFailure, type RoleRemoveOptions, type RoleRemoveOutcome, type RoleScope, type RuleMatch, type RuleSuggestion, type RuleVerdict, type RunCodeFailure, type RunCodeInput, type RunCodeOutcome, type RunCodeToolDeps, type RunEstimateInput, type RunInput, type RunResult, type RunningSchedule, SANDBOX_COVERS, SANDBOX_EXCLUDES, SCALAR_KEYS, SCHEDULE_DEFAULTS, SCHEDULE_DEFAULT_ALLOWLIST, SCHEDULE_ISSUE_CODES, SCHTASKS_FOLDER, SESSION_MESSAGES_READ_TOOL, SESSION_MESSAGES_SEARCH_TOOL, SESSION_QUERY_TOOLS, SESSION_SEARCH_TOOL, SESSION_TRACE_TOOL, SETTINGS_LAYER_ORDER, SETTING_WRITE_KEYS, SETTING_WRITE_LAYERS, SKILL_CREATE_TOOL, SKILL_EDIT_TOOL, SKILL_PATCH_TOOL, SKILL_VIEW_TOOL, SKILL_WRITE_FILE_TOOL, SLASH_COMMANDS_DIAG_MODULE, type ScalarKey, type ScanInstructionsOptions, type ScheduleArgvRefusal, type ScheduleArgvResult, type ScheduleArgvWarning, type ScheduleBackend, type ScheduleCliEntry, type ScheduleDraftDeps, type ScheduleDrift, type ScheduleDriftKind, type ScheduleInstallForm, type ScheduleIssue, type ScheduleIssueCode, type ScheduleLock, ScheduleRecorder, ScheduleRegistrar, ScheduleStore, type ScheduleValidation, type SchemaExport, type SearchHit, type SearchInput, type SearchMessagesInput, type SearchMessagesOutput, type SearchOutput, type SearchSessionsInput, type SelectionDeps, type SelfConnector, type SelfIndexInput, type SelfSettings, type Session, type SessionCandidate, type SessionHit, SessionManager, type SessionMentionDeps, type SessionMeta, SessionQueries, SessionReferences, type SessionSearchDeps, type SessionStats, type SessionSurface, type SessionTrace, type SessionVisibility, type SessionVisibilityInput, type SettingApply, type SettingApplyFacts, type SettingChain, type SettingFutile, type SettingLayer, type SettingStep, type SettingValue, type SettingValueKind, type SettingWriteFailure, type SettingWriteKey, type SettingWriteLayer, type SettingWriteOutcome, type SettingWriteRequest, type SettingWriteTarget, type SettingWriteTargetsOptions, type SettingsFile, SettingsFileError, SettingsFileSchema, type SettingsLayer, type SettingsResolution, type ShadowFinding, type ShadowKind, type Skill, type SkillDirSource, type SkillDirSpec, type SkillDirsSummary, type SkillImportConflict, type SkillImportDone, type SkillImportEntry, type SkillImportFailure, type SkillImportForm, type SkillImportOptions, type SkillImportPreview, type SkillImportResult, type SkillIndexEntry, type SkillIndexOptions, type SkillIndexResidency, type SkillIndexStats, SkillLearner, type SkillLearningProvider, type SkillMeta, type SkillStats, SkillSystem, type SkillSystemOptions, type SkillViewDeps, type SkillWriteDeps, type SteerSource, type SubAgentRunner, type SubTask, type SubToolCaller, type SummarizeOutput, type SurfaceMessage, type SystemPromptParams, type SystemPromptSegments, TOOL_SEARCH_TOOL, TaskNoticeTracker, type TodoItem, type ToolCall, type ToolConflict, type ToolGate, type ToolNameFidelity, type ToolNameLookup, ToolRegistry, type ToolRevealState, type ToolScope, type ToolSearchDeps, type ToolTableCost, type TraceInput, type TraceNode, TrackerDB, type TrustDecision, type TrustGate, type TrustGateOptions, TrustManager, type TurnRecord, type TurnTiming, type UpdateScheduleInput, type UtilityModelInfo, type ValidateScheduleInput, type VersionCheck, Workspace, type WorkspaceFiles, type WorkspaceIssue, type WorkspaceIssueKind, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, checkEpochVersion, checkFtsHealth, checkShadowing, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, defaultModelOf, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, imageFromBase64, imageFromPath, imagePartTokens, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelListCandidates, needsAllowlist, nextFallbackModel, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readImageSize, readMarketplaces, readPluginManifest, readPluginRecords, readProviderKeyEnv, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, resolveArtifactRetention, resolveCodeModeWorker, resolveComplianceDirs, resolveEntrySource, resolveInWorkspace, resolveMarketplaceRef, resolveMentions, resolveMultimodalPolicy, resolvePolicyDirs, resolvePricingAt, resolveProjectRoot, resolveScheduleBackend, resolveSessionReference, resolveSessionVisibility, resolveSettings, resolveSkillDirs, resolveSource, resolveTar, resolveWorkspace, restoreParts, revealScopedProvider, roleScopedProvider, roleSourceLabel, ruleCovers, ruleFromString, ruleToString, runCode, runCommand, sanitizeArgNames, sanitizeCommand, sanitizeFtsQuery, sanitizePath, sanitizeToolOutput, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writeSettingValue };
20120
+ export { AGENT_ROLE_DIAG_MODULE, ARTIFACT_MAX_TOTAL_BYTES, ARTIFACT_RETENTION_DEFAULTS, ATTACHMENT_MAX_TOTAL_BYTES, ATTACHMENT_RETENTION_DEFAULTS, type AcquireResult, type AgentConfig, AgentLoop, type AgentProvider, type AgentSite, type AgentSiteRef, type AppendMessageInput, ApprovalCache, type ApprovalDecision, type ApprovalScope, type ArtifactOpenRefusal, type ArtifactRetention, type AskQuestionDeps, type AttachmentRetention, BLOCKED_TOOLS, type BackendOptions, type BackendOutcome, type BackgroundTaskSource, type BaseOrigin, type BaseSlot, type BeginTurnInput, type BreakdownInput, BudgetGuard, type BudgetGuardOptions, type BudgetInfo, type BudgetLevel, type BudgetOptions, type BudgetStatus, BudgetStore, type BudgetStoreOptions, type BuildFireArgvInput, type BuildIndexOptions, CHECKPOINT_MAX_TOTAL_BYTES, CLAUDE_EVENT_NAMES, CLAUDE_TOOL_NAMES, CODE_MODE_LIMITS, CODE_MODE_SDK_TAG, CONFIG_KEYS, CURRENT_CONFIG_VERSION, type CachedApproval, type CachedDecision, type CheckpointCapture, type CheckpointFile, CheckpointManager, type CheckpointManagerOptions, type CheckpointManifest, CheckpointStore, type CheckpointStoreOptions, type CheckpointSummary, type ClaudeHooksParseOptions, type CodeModeLimits, type CodeRequest, type CodeResult, CodeSandbox, type CommandHookConfig, type CommandHookResult, type CommandLoadOutcome, type CommandLoadSummary, type CommandResult, type CommandRunner, type CompactionResult, type CompiledRules, type ComplianceDirSpec, type ComplianceDirsSummary, ComplianceEngine, type ComplianceEngineInput, type ComplianceGate, type ComplianceHit, type ComplianceRule, type ComplianceRuleSource, type ComplianceSettings, type ComplianceVerdict, type CompressConfig, type CompressResult, type ConfigMigration, type ConfigOrigins, ContextCompressor, type ContextEngine, type CreateScheduleInput, type CreateSessionInput, DEFAULT_COMPLIANCE_ACTIONS, DEFAULT_COMPLIANCE_SETTINGS, DEFAULT_COMPRESSION_THRESHOLD, DEFAULT_GOAL_MAX_ROUNDS, DEFAULT_MAX_HOLD_CHARS, type DelegateArgs, type DelegateConfig, DelegateManager, type DelegateTaskResult, type DiagnoseOptions, type DiscoverOutcome, type DiscoveredFile, type DoctorReport, type DraftParse, EMPTY_RULES, EPOCH_DISK_LEDGER, EpochConfigSchema, type ExpandOptions, type ExtractOutcome, FTS_TABLES, FTS_TRIGGERS, type FallbackEvent, type FileSlots, type FileSourceKind, type ForkInput, type FrontmatterParse, type FrontmatterSplit, type FtsHealth, type FtsReclaim, type FtsSpace, type FtsTableHealth, GOAL_BLOCK_CODES, type GateAxis, type GateVerdict, type GenerateInput, type GenerateOutput, type Goal, type GoalBlockReason, type GoalClear, type GoalPhase, type GoalPromptView, type GoalRefusal, type GoalRoundResult, GoalService, GoalStore, type GoalToolDeps, type GoalWrite, HEADLESS_AUDIT_CODES, type HeadlessPolicy, type HookConfigEntry, HookManager, type HookManagerOptions, type HookMatcher, type HookSourceKind, type HookSourceStatus, type HookSourcesOptions, type HookSourcesSummary, type HooksParseOutcome, type MemoryManager$1 as IMemoryManager, INSTRUCTION_BUDGET_CHARS, INSTRUCTION_FILES, type SessionManager$1 as ISessionManager, type SkillSystem$1 as ISkillSystem, ImageLoadError, type ImageSize, type ImportDecision, type ImportGate, type ImportMessage, type ImportNode, type ImportPartsResult, type ImportSessionInput, type ImportSessionMeta, type ImportSessionResult, type ImportSkipReason, ImportTrustStore, type InstallOptions, type InstallOutcome, type InstallPreview, type InstructionScan, type InstructionSource, type IsolationReason, type IsolationReport, type JsonSchemaDocument, LAUNCHD_LABEL_PREFIX, LOCK_HEARTBEAT_MS, LOCK_STALE_MS, type LastOpenSession, LastOpenSessions, type LayerOutcome, type LayerScalars, type LayerStatus, type LearningContext, type LearningResult, type LearningSkipReason, type LexiconLoadOutcome, type LifecycleOutcome, type ListCandidatesInput, type ListSessionsInput, type ListSessionsOutput, type LoadCommandsOptions, type LoadConfigOptions, type LoadKeybindingsOptions, type LoadKeybindingsResult, type LoadRolesOptions, type LoadedPlugin, type LockHolder, MARKETPLACE_DISPLAY_FIELDS, MARKETPLACE_FILE, MAX_AUDIT_ENTRIES, MAX_COMMAND_DEPTH, MAX_GOAL_MAX_ROUNDS, MAX_IMPORT_DEPTH, MAX_LAST_OPEN_SESSIONS, MAX_OBJECTIVE_CHARS, MAX_REASON_CHARS, MAX_RECENT_WORKSPACES, MODEL_GIVE_UP_THRESHOLD, MULTIMODAL_DEFAULTS, type ManagedPolicy, ManagedPolicyError, type ManagedSettings, ManagedSettingsSchema, type MarketplaceCatalog, type MarketplaceCategory, type MarketplaceDisplay, type MarketplaceDisplayField, type MarketplaceEntry, type MarketplaceOutcome, type MarketplaceRecord, type MarketplaceStatus, type MemoryConfig, type MemoryEntry, MemoryManager, MemoryReviewer, type MemorySearchResult, type MemoryTarget, type MemoryWriteResult, type MentionPart, type MentionResolution, type Message, type MessageHit, type MessageRecord, type MessageSurface, type ModelCapability, ModelFailureTracker, type ModelMetaEntry, type ModelPricing, type MultimodalPolicy, NOMINAL_TOTAL_BYTES, NO_REVEALED_TOOLS, type NonInteractiveProbe, type OsTaskSnapshot, type OutputGuard, PACK_EXCLUDES, PACK_MAX_BYTES, PACK_MAX_FILES, PERMISSION_AUDIT_CODES, PLUGIN_LAYOUT, PLUGIN_MANIFEST_FILE, PLUGIN_MANIFEST_KEYS, PLUGIN_NAME_PATTERN, PLUGIN_ROOT_ENV, PLUGIN_ROOT_TOKEN, PLUGIN_VISIBILITY, POLICY_DECISIONS, PROBE_VERSION, PROJECT_AGENTS_SUBDIR, PROVIDER_NO_CREDENTIAL, type PackFile, type PackLimits, type PackOutcome, type PackPlan, type PackPlanOutcome, type PermissionAuditCode, type PermissionAuditEntry, type PermissionAuditOutcome, type PermissionAuditScope, type PermissionAuditSnapshot, PermissionManager, type PersistFailureKind, type PersistedBudget, type PersistedPart, type PlanApprovalFn, type PlanEnterResult, type PlanModeDeps, PlanModeState, type PlanSettlement, type PluginArtifacts, type PluginAuthor, PluginAuthorSchema, type PluginCommandDir, type PluginCounts, type PluginHookFile, type PluginInventory, type PluginLoadOptions, type PluginManifest, type PluginPathRef, type PluginRecord, type PluginSettingsFile, type PluginSourceType, type PluginStateReadOutcome, PluginStore, type PluginVisibility, type PolicyDirSpec, type PolicyDirsSummary, type PolicyLoadOutcome, type PolicyRule, PolicyRuleSchema, type PricingAt, type PricingOverride, type ProjectContext, type ProjectExtensionInventory, ProviderError, ProviderRouter, type ProviderStreamChunk, type ProviderToolCall$1 as ProviderToolCall, type ProviderWarning, type PruneResult, type QuestionAskFn, RECORDING_KEEP_RUNS, RECORDING_MAX_BYTES, ROLE_FRONTMATTER_SCHEMA, RUN_CODE_TOOL, type ReadMessagesInput, type ReadMessagesOutput, type RecentWorkspace, RecentWorkspaces, type RecordRunInput, type RecorderOptions, type RecoveryAction, type RegisterInput, type RegisterOutcome, type RegistrarOptions, type RegistrationPatch, type RepairOutcome, type ResolveMentionsOptions, type ResolveReferenceInput, type ResolveSettingsOptions, type ResolvedCompression, type ResolvedReference, type ResolvedSource, type ResponseFormat, type RestorePartsOptions, type ReviewIssue, type RewindAction, type RewindDrift, type RewindFilePlan, type RewindOptions, type RewindOutcome, type RewindPreview, type RoleCreateFailure, type RoleCreateInput, type RoleCreateOptions, type RoleCreateOutcome, type RoleLoadOutcome, type RoleLoadSummary, type RoleMergeNotice, type RoleMergeResult, type RoleRemoveFailure, type RoleRemoveOptions, type RoleRemoveOutcome, type RoleScope, type RuleMatch, type RuleSuggestion, type RuleVerdict, type RunCodeFailure, type RunCodeInput, type RunCodeOutcome, type RunCodeToolDeps, type RunEstimateInput, type RunInput, type RunResult, type RunningSchedule, SANDBOX_COVERS, SANDBOX_EXCLUDES, SCALAR_KEYS, SCHEDULE_DEFAULTS, SCHEDULE_DEFAULT_ALLOWLIST, SCHEDULE_FORM_BUDGET_USD, SCHEDULE_ISSUE_CODES, SCHTASKS_FOLDER, SESSION_MESSAGES_READ_TOOL, SESSION_MESSAGES_SEARCH_TOOL, SESSION_QUERY_TOOLS, SESSION_SEARCH_TOOL, SESSION_TRACE_TOOL, SETTINGS_LAYER_ORDER, SETTING_WRITE_KEYS, SETTING_WRITE_LAYERS, SKILL_CREATE_TOOL, SKILL_EDIT_TOOL, SKILL_PATCH_TOOL, SKILL_VIEW_TOOL, SKILL_WRITE_FILE_TOOL, SLASH_COMMANDS_DIAG_MODULE, type ScalarKey, type ScanInstructionsOptions, type ScheduleArgvRefusal, type ScheduleArgvResult, type ScheduleArgvWarning, type ScheduleBackend, type ScheduleCliEntry, type ScheduleDraftDeps, type ScheduleDrift, type ScheduleDriftKind, type ScheduleInstallForm, type ScheduleIssue, type ScheduleIssueCode, type ScheduleLock, ScheduleRecorder, ScheduleRegistrar, ScheduleStore, type ScheduleValidation, type SchemaExport, type SearchHit, type SearchInput, type SearchMessagesInput, type SearchMessagesOutput, type SearchOutput, type SearchSessionsInput, type SelectionDeps, type SelfConnector, type SelfIndexInput, type SelfSettings, type Session, type SessionCandidate, type SessionHit, SessionManager, type SessionMentionDeps, type SessionMeta, SessionQueries, SessionReferences, type SessionSearchDeps, type SessionStats, type SessionSurface, type SessionTrace, type SessionVisibility, type SessionVisibilityInput, type SettingApply, type SettingApplyFacts, type SettingChain, type SettingFutile, type SettingLayer, type SettingStep, type SettingValue, type SettingValueKind, type SettingWriteFailure, type SettingWriteKey, type SettingWriteLayer, type SettingWriteOutcome, type SettingWriteRequest, type SettingWriteTarget, type SettingWriteTargetsOptions, type SettingsFile, SettingsFileError, SettingsFileSchema, type SettingsLayer, type SettingsResolution, type ShadowFinding, type ShadowKind, type Skill, type SkillDirSource, type SkillDirSpec, type SkillDirsSummary, type SkillImportConflict, type SkillImportDone, type SkillImportEntry, type SkillImportFailure, type SkillImportForm, type SkillImportOptions, type SkillImportPreview, type SkillImportResult, type SkillIndexEntry, type SkillIndexOptions, type SkillIndexResidency, type SkillIndexStats, SkillLearner, type SkillLearningProvider, type SkillMeta, type SkillStats, SkillSystem, type SkillSystemOptions, type SkillViewDeps, type SkillWriteDeps, type SteerSource, type SubAgentRunner, type SubTask, type SubToolCaller, type SummarizeOutput, type SurfaceMessage, type SystemPromptParams, type SystemPromptSegments, TOOL_SEARCH_TOOL, TaskNoticeTracker, type TodoItem, type ToolCall, type ToolConflict, type ToolGate, type ToolNameFidelity, type ToolNameLookup, ToolRegistry, type ToolRevealState, type ToolScope, type ToolSearchDeps, type ToolTableCost, type TraceInput, type TraceNode, TrackerDB, type TrustDecision, type TrustGate, type TrustGateOptions, TrustManager, type TurnRecord, type TurnTiming, type UpdateScheduleInput, type UtilityModelInfo, type ValidateScheduleInput, type VersionCheck, Workspace, type WorkspaceFiles, type WorkspaceIssue, type WorkspaceIssueKind, acquireScheduleLock, addMarketplace, addUsage, admitArtifact, admitArtifacts, affectedPaths, artifactLaunchArgv, artifactOpenRefusal, assertLevelAllowed, blockedRoleTools, buildContextBreakdown, buildFireArgv, buildFtsMatchQuery, buildSchemaExports, buildSystemPrompt, buildTrigramMatchQuery, builtinRoles, checkEpochVersion, checkFtsHealth, checkShadowing, classifyPersistFailure, classifyProviderError, clearModelCache, coalesceRecording, codeModeWorkerPath, commandNameFromRelPath, compileRuleLists, compressionOptions, computeCost, computeCostMicros, computeExecHash, countRules, createAllowAllGate, createAllowAllImportGate, createAskQuestionTool, createCodeExecTool, createDelegateTool, createDenyAllGate, createDenyAllImportGate, createGoalTool, createImportGate, createMemoryTool, createPlanModeTools, createRoleFile, createRoleScope, createRunCodeTool, createScheduleDraftTool, createSessionMessagesReadTool, createSessionMessagesSearchTool, createSessionSearchTool, createSessionSearchTools, createSessionTraceTool, createSkillViewTool, createSkillWriteTools, createTodoTool, createToolRevealState, createToolScope, createToolSearchTool, createTrustGate, currentEpochVersion, decideImport, decideTrust, defaultConfig, defaultModelOf, describeArtifactRefusal, describeBackgroundTask, describeHeadlessPolicy, describeIsolation, describeJsonError, diagnoseSchedules, discoverMarkdown, discoverModels, discoverProject, displayAllows, displayCurrency, draftCommandLine, draftWidening, escapeRuleContent, estimateImageTokens, estimateRunTokens, estimateTokens, evaluateSelection, expandCommand, expandImports, explainSetting, extractArchive, findInstructionFiles, findProjectInstructions, findRole, formatBytes, formatSkillIndex, formatUsd, gateForTool, getCapability, getConfigIssues, getConfigOrigins, getImportGate, getTrustGate, hasDedicatedExecContent, hasExecTierContent, hasPromptCaching, hasProviderCredentials, hasReadTierContent, imageFromBase64, imageFromPath, imagePartTokens, importParts, importSkills, installPlugin, instructionDirs, instructionNotices, intervalSlots, inventoryProjectExtensions, inventoryTotal, isBlockCode, isCodeModeDeferred, isEmptyRules, isGoalPhase, isNonInteractive, isReadOnlySubCall, isSettingWriteLayer, isTransientPersistFailure, isValidPluginName, isWithinWindow, isWritableSettingKey, labelSlug, layerRank, listRunningSchedules, listSessionCandidates, listWorkspaceFiles, loadCommandDefinitions, loadCommandFile, loadCommands, loadConfig, loadHookSources, loadKeybindings, loadLexiconDir, loadLexiconFiles, loadPlugins, loadPolicyFiles, loadPolicyRules, loadRoleDefinitions, loadRoleDir, loadedImports, localDateString, managedSwitchNotes, mapClaudeToolName, mapEpochToolName, mapOperationType, matchPreauthorization, matchRuleLists, matchesHook, mentionsPluginRoot, mergeHeadlessPolicy, mergeRoles, mergeSchedulePatch, microsToUsd, modelListCandidates, needsAllowlist, nextFallbackModel, nextRunAt, noConfigOrigins, noManagedPolicy, noPlugins, openArtifact, originOf, packFileName, packPlugin, parseClaudeSettingsHooks, parseClock, parseDate, parseFrontmatter, parseHooksConfig, parseHooksConfigVerbose, parseImportLine, parseModelList, parseRoleDefinition, parseScheduleDraft, parseSkillFrontmatter, parseTrigger, pendingImageTokens, persistFailureCode, persistParts, persistToolResults, persistedUsage, planPack, previewSkillImport, pricingFor, projectEntryForDisplay, pruneArtifacts, pruneAttachments, pruneRecordings, pruneSchedules, readImageSize, readMarketplaces, readPluginManifest, readPluginRecords, readProviderKeyEnv, readRecording, readSessionSurface, reclaimFtsSpace, redactLine, refreshOpenRouterMetadata, removeMarketplace, removeRecordings, removeRoleFile, removeSessionArtifacts, removeSessionAttachments, renderImportTree, renderProjectContext, renderSdkDeclaration, renderSelfIndex, repairSchedules, resolveArtifactRetention, resolveCodeModeWorker, resolveComplianceDirs, resolveEntrySource, resolveInWorkspace, resolveMarketplaceRef, resolveMentions, resolveMultimodalPolicy, resolvePolicyDirs, resolvePricingAt, resolveProjectRoot, resolveScheduleBackend, resolveSessionReference, resolveSessionVisibility, resolveSettings, resolveSkillDirs, resolveSource, resolveTar, resolveWorkspace, restoreParts, revealScopedProvider, roleScopedProvider, roleSourceLabel, ruleCovers, ruleFromString, ruleToString, runCode, runCommand, sanitizeArgNames, sanitizeCommand, sanitizeFtsQuery, sanitizePath, sanitizeToolOutput, scanInstructions, scanPluginDir, scanSkillDirs, searchMarketplaces, setDisplayCurrency, setImportGate, setPluginEnabled, setTrustGate, settingValueChoices, settingValueKind, settingWriteApply, settingWriteLayers, settingWriteTargets, skillIndexDescription, skillIndexResidency, skillIndexStats, sniffMediaType, splitFrontmatter, staticToolProvider, stripArtifactData, substitutePluginRoot, suggestRuleFromApproval, systemOpenArgv, systemPromptSegments, toPosix, toolDefinitionTokens, toolMatches, toolTableTokens, totalTokens, traceSession, triggerPeriodMs, unescapeRuleContent, uninstallPlugin, unknownRoleSkills, unknownRoleTools, unloadedInstructionFiles, updateMarketplace, updatePlugin, usdToMicros, validateSchedule, validateTrigger, validateWindow, withGoalCompression, withGoalPrompt, workspaceDisplayPath, writeSettingValue };