@epoch-agent/protocol 0.9.0 → 0.10.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 +1091 -66
- package/dist/index.js +115 -11
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1647,6 +1647,143 @@ interface HostUser {
|
|
|
1647
1647
|
icon?: string;
|
|
1648
1648
|
}
|
|
1649
1649
|
|
|
1650
|
+
/**
|
|
1651
|
+
* 金额的**展示**口径 —— 全仓唯一一处把数字变成「一串带货币符号的字」的地方。
|
|
1652
|
+
*
|
|
1653
|
+
* ## 一条贯穿全仓的分界:**算术恒为美元,展示可换币种**
|
|
1654
|
+
*
|
|
1655
|
+
* | | 单位 | 谁定的 | 换不换 |
|
|
1656
|
+
* | --- | --- | --- | --- |
|
|
1657
|
+
* | 单价表、`micro-USD` 累加、闸门比较 | **美元** | 上游 provider 的挂牌价 | **不换** |
|
|
1658
|
+
* | `costUsd` / `maxCostUsd` / `maxBudgetUsd` / DB 里那几列 | **美元** | 契约 | **不换** |
|
|
1659
|
+
* | 用户**输进来**的那几格(设置页、`--max-budget-usd`、定时任务表单) | **美元** | 标签上逐字写着「(美元)」 | **不换** |
|
|
1660
|
+
* | 屏幕上印出来的每一串金额 | `display.currency` | 用户 | **这里换** |
|
|
1661
|
+
*
|
|
1662
|
+
* 换句话说,币种在这个仓里**只是一层皮**:它进不了任何一句算术,也进不了任何一个
|
|
1663
|
+
* 落盘字段。这是刻意的,理由有三条,每一条单独都足以否掉「让币种进算术」:
|
|
1664
|
+
*
|
|
1665
|
+
* 1. **上游单价本来就是美元计价的**(`core/src/provider/model-metadata.ts` 那张静态表、
|
|
1666
|
+
* 以及 OpenRouter 抓回来的那份,都是 USD / MTok)。让内部换成别的币种,等于在
|
|
1667
|
+
* 每一笔账上多乘一次汇率再除回来 —— 多两次浮点,换不到任何东西;
|
|
1668
|
+
* 2. **落盘和网线上的字段名带着 `Usd` 后缀**(`costUsd`、`max_budget_usd`、
|
|
1669
|
+
* `microUsd`)。让它们装别的币种,字段名当场变成假话,而**没有任何一处会红**;
|
|
1670
|
+
* 3. **汇率是会变的,账是不该变的。** 用户今天把 `rate` 从 7.1 改成 7.3,
|
|
1671
|
+
* 上个月那几段会话的**历史账**不该跟着动。只在展示时乘一次,这件事自动成立 ——
|
|
1672
|
+
* 而如果换算发生在落盘前,改一次汇率就意味着整本账从此自相矛盾。
|
|
1673
|
+
*
|
|
1674
|
+
* ## ⚠️ 汇率**不印在任何界面上**,这是产品决定,不是漏了
|
|
1675
|
+
*
|
|
1676
|
+
* 用户配了 `rate` 就是认了这个数,界面上再写一句「按 7.1 折算」是把一个他自己
|
|
1677
|
+
* 填的常量念回给他听。所以这个模块**只吐金额**,一个「≈」、一个汇率脚注都没有。
|
|
1678
|
+
*
|
|
1679
|
+
* 它的代价是知道的、也是可接受的:设置页里那格上限写着「(美元)」、填 5,
|
|
1680
|
+
* 侧栏那条比值却印成 `¥35.50` 的分母 —— 两个数对不上,而屏幕上没有一句话解释。
|
|
1681
|
+
* 换来的是**分子分母同币种**(见下面那条 ⚠️),那个更要紧:一条
|
|
1682
|
+
* `¥0.86 / $5.00` 的比值是**读不出意思**的,而 `5 → ¥35.50` 只是需要用户
|
|
1683
|
+
* 想一下他自己配的汇率。
|
|
1684
|
+
*
|
|
1685
|
+
* ## ⚠️ 一条比值里的两个数,必须一起换
|
|
1686
|
+
*
|
|
1687
|
+
* 侧栏那句「约 {spent} / {limit}」的分母是**配置值**(美元),分子是**实际花费**
|
|
1688
|
+
* (美元)。展示时两个都乘同一个 `rate`,比值本身不变。漏换任何一边,屏幕上就会
|
|
1689
|
+
* 出现一条混币种的比值 —— 那不是「精度问题」,是一句假话。
|
|
1690
|
+
*
|
|
1691
|
+
* ## 没配币种时,这个模块的输出**与 2026-09-13 之前逐字节相同**
|
|
1692
|
+
*
|
|
1693
|
+
* `currency` 缺席(**绝大多数用户**)走的是 `$` + `toFixed(digits)`,和它替换掉的
|
|
1694
|
+
* 那六处手写实现一个字符不差。这条是这次改动的安全绳,也是为什么全仓那些断言
|
|
1695
|
+
* `'$0.0000'` 的既有用例一条都不用改 —— 它们从此顺带钉住了「默认路径没被改坏」。
|
|
1696
|
+
*/
|
|
1697
|
+
/**
|
|
1698
|
+
* 支持的展示币种。**唯一真源** —— {@link Currency} 类型从它派生。
|
|
1699
|
+
*
|
|
1700
|
+
* ## ⚠️ 值域是封闭的:`USD` 和 `CNY`,没有第三个
|
|
1701
|
+
*
|
|
1702
|
+
* 判据逐条借 [i18n.ts](./i18n.ts) 上 `LANGS` 那一段,它在这儿是**原样成立**的,
|
|
1703
|
+
* 不是抄一个先例 —— 这个仓的界面只有中文和英文两份 catalog,而币种是跟着
|
|
1704
|
+
* 用户在哪儿、拿什么结账走的。为一个我们连界面语言都不提供的地区先把币种铺上,
|
|
1705
|
+
* 铺的是一张**没有任何用例盖得住**的表。
|
|
1706
|
+
*
|
|
1707
|
+
* 所以加第三个币种是**一次需要重新决策的改动**,不是补一行常量:
|
|
1708
|
+
*
|
|
1709
|
+
* | 得先答的 | 为什么不能顺手 |
|
|
1710
|
+
* | --- | --- |
|
|
1711
|
+
* | 小数位怎么办 | `JPY` / `KRW` 惯例是 0 位,而这里四档位数是**逐处判过**的(见 {@link formatMoney} 那张表),不是一个能按币种改的旋钮 |
|
|
1712
|
+
* | 符号摆前面还是后面 | 欧陆多数币种是 `12,34 €`,而这里的实现和全部文案都假设**符号在前** |
|
|
1713
|
+
* | 千分位和小数点 | `1.234,56` 那一套要整套数字格式化,不是加一个符号 |
|
|
1714
|
+
*
|
|
1715
|
+
* 换句话说:**今天加的不是「CNY」这一个值,是「展示币种可以不是美元」这件事**,
|
|
1716
|
+
* 而第二个值把这件事的全部机制都落地了。第三个值要付的是上面那张表。
|
|
1717
|
+
*
|
|
1718
|
+
* 根 `__tests__/money-currency.test.ts` 里钉着 `CURRENCIES.length === 2` ——
|
|
1719
|
+
* 那条用例的全部意义就是逼下一个人先读完这一段,而不是加完就走
|
|
1720
|
+
* (手法同 `LANGS` 那条 `LANGS.length === 2`)。
|
|
1721
|
+
*/
|
|
1722
|
+
declare const CURRENCIES: readonly ["USD", "CNY"];
|
|
1723
|
+
/** 展示币种。**封闭的两个值**,见 {@link CURRENCIES} */
|
|
1724
|
+
type Currency = (typeof CURRENCIES)[number];
|
|
1725
|
+
/** 是不是我们支持的币种。用户输入(配置文件)收窄用,同 i18n 的 `isLang()` */
|
|
1726
|
+
declare function isCurrency(value: string): value is Currency;
|
|
1727
|
+
/**
|
|
1728
|
+
* 展示币种 + 汇率。**两格都必填**,因为少任何一格这一份都没有意义:
|
|
1729
|
+
* 只有 `code` 换不出数,只有 `rate` 印不出符号。
|
|
1730
|
+
*
|
|
1731
|
+
* 写成一个对象而不是两个平行可选字段,就是为了让「要么都没有、要么都有」
|
|
1732
|
+
* 由**结构本身**保证,而不是靠一条 refine 和一句注释 —— 判据同
|
|
1733
|
+
* `WireConfigResponse.maxCostUsd` 那条「没配就没有这个键」。
|
|
1734
|
+
*/
|
|
1735
|
+
interface CurrencyDisplay {
|
|
1736
|
+
readonly code: Currency;
|
|
1737
|
+
/**
|
|
1738
|
+
* **1 美元 = 多少目标币**。必须为正。
|
|
1739
|
+
*
|
|
1740
|
+
* ⚠️ 方向别反了。反了不会红,只会让所有金额小两个数量级 —— 而「成本看起来
|
|
1741
|
+
* 很便宜」是这个仓里最不想要的那一类静默错误(同 `pricing.ts` 文件头那条
|
|
1742
|
+
* 「0 意味着免费,undefined 意味着不知道」的精神)。
|
|
1743
|
+
*
|
|
1744
|
+
* ⚠️ **没有默认值,也不去联网抓。** 一个写死在代码里的 `7.1` 会在第一个月就
|
|
1745
|
+
* 开始撒谎,而抓汇率意味着这个仓要多一个外部依赖、一条离线降级路径和一份缓存 ——
|
|
1746
|
+
* 判据同方案 42 §三那条范围闸门(「要一台我们运维的服务器 → 不做」)。
|
|
1747
|
+
* 用户自己填一个他认的数,是这件事唯一诚实的形态。
|
|
1748
|
+
*/
|
|
1749
|
+
readonly rate: number;
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* 小数位。
|
|
1753
|
+
*
|
|
1754
|
+
* - 给数字 = 定死几位。调用点为什么各要各的,见 {@link formatMoney} 那张表;
|
|
1755
|
+
* - `'adaptive'` = 不到 0.01 时给四位,否则两位。
|
|
1756
|
+
*/
|
|
1757
|
+
type MoneyDigits = number | 'adaptive';
|
|
1758
|
+
interface FormatMoneyOptions {
|
|
1759
|
+
/** 缺席 = 美元原样印,**输出与这次改动之前逐字节相同**(见文件头最后一节) */
|
|
1760
|
+
currency?: CurrencyDisplay | undefined;
|
|
1761
|
+
/** 缺省 `'adaptive'` —— 那是 core 那份 `formatUsd` 的历史行为 */
|
|
1762
|
+
digits?: MoneyDigits;
|
|
1763
|
+
}
|
|
1764
|
+
/**
|
|
1765
|
+
* 把一笔**美元**金额印成给人看的一串字。
|
|
1766
|
+
*
|
|
1767
|
+
* @param usd 金额,单位恒为美元(见文件头那张表第一行)
|
|
1768
|
+
*
|
|
1769
|
+
* ## 各调用点的 `digits` 为什么不统一
|
|
1770
|
+
*
|
|
1771
|
+
* 收敛的是**符号和换算**,不是精度 —— 精度的差异是逐处判过的,收成一个数会
|
|
1772
|
+
* 当场弄坏其中几处:
|
|
1773
|
+
*
|
|
1774
|
+
* | 处 | 位数 | 判据 |
|
|
1775
|
+
* | --- | --- | --- |
|
|
1776
|
+
* | TUI `/cost`、web 花费页那一列 | 4 | 单轮成本常是 $0.003,两位会印成一个「免费」的假象 |
|
|
1777
|
+
* | 侧栏那条比值的分子 | 3 | 那一格答的是「离天花板多远」,不是「这一笔多少」 |
|
|
1778
|
+
* | TUI 状态栏「余」 | 2 | 同上,它是个余量不是账 |
|
|
1779
|
+
* | core 收尾摘要 / 闸门文案 | `'adaptive'` | 小额给四位,大额给两位 |
|
|
1780
|
+
*
|
|
1781
|
+
* ⚠️ **换币种不改位数。** `rate` 是 7 的时候「四位」印出来的有效数字确实比美元多
|
|
1782
|
+
* 一位,那是对的 —— 那一列存在的理由是让人竖着扫出哪一轮贵,而不是凑齐有效数字。
|
|
1783
|
+
* 真按币种调位数的话,同一个界面在两台机器上会有两种列宽,而没有任何用例盖得住。
|
|
1784
|
+
*/
|
|
1785
|
+
declare function formatMoney(usd: number, opts?: FormatMoneyOptions): string;
|
|
1786
|
+
|
|
1650
1787
|
/**
|
|
1651
1788
|
* 宿主自定义的侧栏菜单项(2026-09-02)—— **一个形状,两个键**(2026-09-07 拆开)。
|
|
1652
1789
|
*
|
|
@@ -2082,7 +2219,13 @@ interface EpochConfig {
|
|
|
2082
2219
|
enabled?: boolean;
|
|
2083
2220
|
/**
|
|
2084
2221
|
* 提示词占到上下文窗口的**几成**时开始压缩,`(0, 1]`。
|
|
2085
|
-
* 缺省 = core 的 `DEFAULT_COMPRESSION_THRESHOLD`(0.
|
|
2222
|
+
* 缺省 = core 的 `DEFAULT_COMPRESSION_THRESHOLD`(2026-09-11 起是 **0.8**,
|
|
2223
|
+
* 在那之前是 0.5),**默认值只有那一处** —— 这儿写出来的数只是给读文档的人,
|
|
2224
|
+
* 别照着它在代码里写第二份(判据在那个常量上)。
|
|
2225
|
+
*
|
|
2226
|
+
* ⚠️ 它是**软线**,管的是省钱:越线之后压不压还要过冷却期和熔断。
|
|
2227
|
+
* 「这一发还发得出去吗」是另一条硬线 {@link OVERSIZE_RATIO}(0.9,冷却期让路),
|
|
2228
|
+
* 两条别混成一条 —— 判据全文在 {@link isPromptOversize} 上那张表里。
|
|
2086
2229
|
*
|
|
2087
2230
|
* 判的是 {@link promptTokens}(非缓存 + 缓存命中 + 缓存写入),
|
|
2088
2231
|
* **不是** `usage.inputTokens`:缓存命中的那部分照样占窗口。
|
|
@@ -2290,6 +2433,18 @@ interface EpochConfig {
|
|
|
2290
2433
|
* warn 诊断然后回落 —— **不是报错退出**,配置写错不该让 agent 起不来。
|
|
2291
2434
|
*/
|
|
2292
2435
|
language?: Lang;
|
|
2436
|
+
/**
|
|
2437
|
+
* 屏幕上那些金额印成什么币种。**缺省 = 美元。**
|
|
2438
|
+
*
|
|
2439
|
+
* 它和 `language` 并排放在这一段是因为两者是同一类东西:**纯粹的显示偏好,
|
|
2440
|
+
* 一个字都进不了引擎**。金额的算术、落盘、闸门比较、以及用户输进来的
|
|
2441
|
+
* 每一格(`budget.maxCostUsd` 那些)**恒为美元** —— 判据全文在
|
|
2442
|
+
* [money.ts](./money.ts) 文件头那张表。
|
|
2443
|
+
*
|
|
2444
|
+
* `code` / `rate` 两格都必填(`rate` = 1 美元兑多少目标币),要么整段不配、
|
|
2445
|
+
* 要么两格都给:只给 `code` 会印出一个换了符号没换数的假读数。
|
|
2446
|
+
*/
|
|
2447
|
+
currency?: CurrencyDisplay;
|
|
2293
2448
|
};
|
|
2294
2449
|
/**
|
|
2295
2450
|
* 宿主品牌词标([决定 19](../../../design/web-ui/README.md))。**缺省 = 界面上什么都不显示。**
|
|
@@ -3605,6 +3760,19 @@ type AgentEvent =
|
|
|
3605
3760
|
* 「这一轮到底是谁答的」正是那时候用户最需要知道的一件事。
|
|
3606
3761
|
*/
|
|
3607
3762
|
model?: string;
|
|
3763
|
+
/**
|
|
3764
|
+
* 最后一次模型调用**要求**的那个模型(`GenerateOutput.requestedModel`)。
|
|
3765
|
+
*
|
|
3766
|
+
* 和上面的 {@link model} 是一对,宿主要的那个事实是**两者是否相等** ——
|
|
3767
|
+
* 不等 = 引擎降级了,相等 = 用户/命令自己挑的。
|
|
3768
|
+
*
|
|
3769
|
+
* ⚠️ **读侧不许拿 `model` 去和「当前配置/当前选择」比来代替这个判断。**
|
|
3770
|
+
* 那是一个按**此刻**的值,而这条断言是按**轮**的 —— 它会被拿去比对所有
|
|
3771
|
+
* 历史轮,于是用户在顶栏换一次模型,之前那些跑得好好的轮子集体变成
|
|
3772
|
+
* 「故障转移」。web 脚注那枚徽标栽过这一次,判据全文在
|
|
3773
|
+
* `core/src/provider/types.ts` 的 `GenerateOutput.requestedModel` 上。
|
|
3774
|
+
*/
|
|
3775
|
+
requestedModel?: string;
|
|
3608
3776
|
breach?: BudgetBreach;
|
|
3609
3777
|
}
|
|
3610
3778
|
/**
|
|
@@ -3732,7 +3900,53 @@ type NoticeCode =
|
|
|
3732
3900
|
* (硬线,见 protocol 的 `isPromptOversize`)。不给它们分两档码是因为
|
|
3733
3901
|
* 用户要知道的是同一件事,而「哪道闸判的」是我们的实现细节。
|
|
3734
3902
|
*/
|
|
3735
|
-
| 'context-compacted'
|
|
3903
|
+
| 'context-compacted'
|
|
3904
|
+
/**
|
|
3905
|
+
* 这个模型认不认图,**我们查不到,正在现问它本人**(2026-09-11)。
|
|
3906
|
+
*
|
|
3907
|
+
* ## 为什么这一次探测必须说出来
|
|
3908
|
+
*
|
|
3909
|
+
* 它是**用户没要求过的一次额外请求**:多一趟往返(约两秒)、多一笔约 225 token
|
|
3910
|
+
* 的账。屏幕上那段静默否则解释不了 —— 用户发了张图,等了两秒,什么都没有。
|
|
3911
|
+
*
|
|
3912
|
+
* 判据同上面几条:多花的钱和多等的时间,只要不是用户自己点的,就欠一句旁白。
|
|
3913
|
+
*
|
|
3914
|
+
* ⚠️ **一次探测最多两帧**(「正在问」+ 只在**认图**时补一句「确认认图」):
|
|
3915
|
+
* 不认图那一路后面紧跟着 `error` 帧,那句话已经把结论说全了,再发一帧确认
|
|
3916
|
+
* 就是同一件事说两遍。
|
|
3917
|
+
*
|
|
3918
|
+
* ⚠️ 每个型号**一辈子只探一次**(结论进 `~/.epoch/cache/model_probe.json`,
|
|
3919
|
+
* 认图存 30 天、不认图存 24 小时),所以这一帧天然罕见。要是它开始每轮都出现,
|
|
3920
|
+
* 说明缓存写不进去(只读的 home),那是个 bug,不是这一帧的问题。
|
|
3921
|
+
*/
|
|
3922
|
+
| 'image-probe'
|
|
3923
|
+
/**
|
|
3924
|
+
* **历史里**那几张图被摘掉了,因为此刻这个模型不认图(2026-09-12)。
|
|
3925
|
+
*
|
|
3926
|
+
* ## 和上面 `images-dropped`、和 `agent_run.images_unsupported` 三者的分工
|
|
3927
|
+
*
|
|
3928
|
+
* | | 图从哪来 | 谁判的 | 请求 | 钱 |
|
|
3929
|
+
* | --- | --- | --- | --- | --- |
|
|
3930
|
+
* | `images_unsupported`(`error` 帧) | **这一轮新发的** | 我们(闸门 1) | 不发 | 没花 |
|
|
3931
|
+
* | 这一条(`notice` 帧) | **历史里的** | 我们(装 history 时) | 照发 | 花了,但图不占 token |
|
|
3932
|
+
* | `images-dropped`(`notice` 帧) | 这一轮新发的 | **provider 的 warning** | 已发 | 花了 |
|
|
3933
|
+
*
|
|
3934
|
+
* 第一行是「你现在做的这件事做不了」,用户当场能改(换模型 / 去掉图);
|
|
3935
|
+
* 这一条是「你**以前**做的那件事,从现在起看不见了」—— 他此刻什么都没做,
|
|
3936
|
+
* 所以更需要一句旁白。
|
|
3937
|
+
*
|
|
3938
|
+
* ## 没有这一帧的话,这件事是彻底静默的
|
|
3939
|
+
*
|
|
3940
|
+
* 触发面是两个:`epoch --resume` 装一段贴过图的会话(启动路径上**没有任何
|
|
3941
|
+
* 能力检查**),以及 `/model` 切到一个能力**查不到**的型号
|
|
3942
|
+
* (`provider/selection.ts` 那条硬拒绝只挡查得到不认图的)。两条路上用户都
|
|
3943
|
+
* 没有再发图,于是屏幕上不会有任何东西提到图 —— 而模型接下来那句
|
|
3944
|
+
* 「你发的那张截图我看不到」会像是它在犯病。
|
|
3945
|
+
*
|
|
3946
|
+
* ⚠️ **一次 run 只发一帧**,判据逐字同 `images-dropped`:那几张历史图在这次
|
|
3947
|
+
* run 的每一轮都要重新摘一次,逐轮报的话一次多工具调用的对话会刷出十几行。
|
|
3948
|
+
*/
|
|
3949
|
+
| 'history-images-stripped';
|
|
3736
3950
|
type AgentEventType = AgentEvent['type'];
|
|
3737
3951
|
/** 取出某个具体事件的类型,例如 AgentEventOf<'tool-call'> */
|
|
3738
3952
|
type AgentEventOf<T extends AgentEventType> = Extract<AgentEvent, {
|
|
@@ -4539,6 +4753,32 @@ type TrustScope =
|
|
|
4539
4753
|
'directory'
|
|
4540
4754
|
/** 这个目录及其所有子目录 */
|
|
4541
4755
|
| 'directory-tree';
|
|
4756
|
+
/**
|
|
4757
|
+
* 一次授信授到哪一档(2026-09-11)。**两档是相加的:`exec` 蕴含 `read`。**
|
|
4758
|
+
*
|
|
4759
|
+
* ## 为什么拆
|
|
4760
|
+
*
|
|
4761
|
+
* 在它之前 `trusted` 是一个布尔,而那一个布尔后面挂着七样东西 —— 其中
|
|
4762
|
+
* `.epoch/hooks.json` 和 `.claude/settings.json` 的每一项都是一条要 spawn 子进程的
|
|
4763
|
+
* 命令(判据在 [core/hook/sources.ts](../../core/src/hook/sources.ts) 的文件头)。
|
|
4764
|
+
* 而用户被问到的那句话逐字是「本目录的项目指令会加载」(`trust_prompt.granted`),
|
|
4765
|
+
* **从来没提过 hook**。也就是说「往上下文里注入一段文本」和「在这台机器上执行
|
|
4766
|
+
* 任意命令」共用了同一次点击,而问话只描述了前者。这不是 UX 问题,是知情同意错位。
|
|
4767
|
+
*
|
|
4768
|
+
* | 档 | 放开什么 | 风险 |
|
|
4769
|
+
* | --- | --------------------------------------------------------------- | ---------- |
|
|
4770
|
+
* | `read` | 指令文件 / 技能 / 角色 / 命令 | 注入上下文 |
|
|
4771
|
+
* | `exec` | `hooks.json` / `.claude/settings*.json` / `policies/` / settings 的 allow 那一半 | 执行、放宽判定 |
|
|
4772
|
+
*
|
|
4773
|
+
* ## ⚠️ 两条边界,别把它当别的东西
|
|
4774
|
+
*
|
|
4775
|
+
* 1. **`exec` 不是权限档。** 它放开的是「这个仓库自带的 hook / policy 算不算数」,
|
|
4776
|
+
* 不是「这次操作要不要问用户」——[两套机制照旧正交](../../core/src/trust/gate.ts)。
|
|
4777
|
+
* 未授 `exec` 的目录里 agent 照样能跑 bash,只是仓库里那份 `hooks.json` 不生效;
|
|
4778
|
+
* 2. **`read` 不是「安全档」。** 一份 `AGENTS.md` 能指挥 agent 去做任何它有权限做的
|
|
4779
|
+
* 事,包括执行命令。拆开不是因为 `read` 无害,是因为**两者的问话不该合并成一次**。
|
|
4780
|
+
*/
|
|
4781
|
+
type TrustTier = 'read' | 'exec';
|
|
4542
4782
|
interface TrustRecord {
|
|
4543
4783
|
/** 绝对路径(已 resolve) */
|
|
4544
4784
|
path: string;
|
|
@@ -4553,12 +4793,77 @@ interface TrustRecord {
|
|
|
4553
4793
|
scope: TrustScope;
|
|
4554
4794
|
/** 记录时间戳(ms) */
|
|
4555
4795
|
decidedAt: number;
|
|
4796
|
+
/**
|
|
4797
|
+
* 执行类也授了吗({@link TrustTier})。`level: 'untrusted'` 时无意义。
|
|
4798
|
+
*
|
|
4799
|
+
* ⚠️ **缺省(`undefined`)= 没授**,而这一格正是存量记录的迁移:拆档之前写下的
|
|
4800
|
+
* 记录没有这一格,于是升级之后它们**只剩读类** —— 判据就是上面那张表下面那段:
|
|
4801
|
+
* 那些记录是在一句只说了「项目指令会加载」的问话下拿到的,把它们追认成执行类
|
|
4802
|
+
* 等于替用户补签一份他没看过的同意书。代价(老用户的项目 hook 会停)由
|
|
4803
|
+
* `trust_gate.exec_migrated` 那条诊断明说,不静默。
|
|
4804
|
+
*/
|
|
4805
|
+
exec?: boolean;
|
|
4806
|
+
/**
|
|
4807
|
+
* 授 `exec` 那一刻,执行类输入文件的内容指纹(见 core 的 `trust/exec-hash.ts`)。
|
|
4808
|
+
*
|
|
4809
|
+
* 对不上 = 那些文件在授信之后被改过 → `exec` 退回未授,重新问一次。
|
|
4810
|
+
* `exec` 为假时这一格不该存在。
|
|
4811
|
+
*
|
|
4812
|
+
* ## ⚠️ 这是对 [manager.ts](../../core/src/trust/manager.ts) 文件头「两条明确不做」
|
|
4813
|
+
* 第 2 条的一次**窄口推翻**,不是把它作废
|
|
4814
|
+
*
|
|
4815
|
+
* 那一条 2026-08-08 写着:记内容 hash「代价是『改一行 AGENTS.md 就被打断一次』,
|
|
4816
|
+
* 这个打断比它挡住的风险更贵」。**那个结论在读类上照旧成立,一个字不改** ——
|
|
4817
|
+
* 指令文件天天在动,为它记 hash 会把授信变成一件每天都要重做的事。
|
|
4818
|
+
*
|
|
4819
|
+
* 翻的只有执行类那一半,因为它的两项输入都变了:
|
|
4820
|
+
*
|
|
4821
|
+
* | | 读类(AGENTS.md) | 执行类(hooks.json / policies) |
|
|
4822
|
+
* | --- | ---------------------- | -------------------------------- |
|
|
4823
|
+
* | 改动频率 | 每天 | 几乎不动 |
|
|
4824
|
+
* | 改动后果 | 多一段文本 | **多一条会跑的命令** |
|
|
4825
|
+
*
|
|
4826
|
+
* 也就是说,同一个做法在这一侧的打断成本低一个量级、挡住的东西贵一个量级。
|
|
4827
|
+
* 参照物:codex 对 hook 记 `trusted_hash`(`codex-rs/config/src/hook_config.rs`),
|
|
4828
|
+
* 而它的 `AGENTS.md` 压根不过闸门 —— 同一条判据的两侧,它也是这么分的。
|
|
4829
|
+
*/
|
|
4830
|
+
execHash?: string;
|
|
4831
|
+
}
|
|
4832
|
+
/** {@link TrustManager.record} 的可选档位。不给 = 只授读类 */
|
|
4833
|
+
interface TrustGrant {
|
|
4834
|
+
/** 连执行类一起授。**调用方必须真的为这一档单独问过用户** */
|
|
4835
|
+
exec?: boolean;
|
|
4836
|
+
/** 授 `exec` 时一并记下的内容指纹 */
|
|
4837
|
+
execHash?: string;
|
|
4838
|
+
}
|
|
4839
|
+
/**
|
|
4840
|
+
* {@link TrustManager.checkExec} 的答案 —— **记录里写的,不含新鲜度校验**。
|
|
4841
|
+
*
|
|
4842
|
+
* 两格一起交出来是因为校验方(`core/src/trust/gate.ts`)需要拿 {@link hash} 去和
|
|
4843
|
+
* 现算的值比;拆成两次调用的话,两次之间可能命中**不同的记录**
|
|
4844
|
+
* (`bestRecord()` 是按最长匹配现算的),于是拿 A 记录的授信配上 B 记录的指纹。
|
|
4845
|
+
*/
|
|
4846
|
+
interface TrustExecGrant {
|
|
4847
|
+
/** 记录里授过执行类吗 */
|
|
4848
|
+
granted: boolean;
|
|
4849
|
+
/**
|
|
4850
|
+
* 授的时候记下的内容指纹。
|
|
4851
|
+
*
|
|
4852
|
+
* ⚠️ **`undefined` = 校验不了,而这一档照旧放行**(判据在 gate 的 `decide()` 上)。
|
|
4853
|
+
* 今天所有写入口都会带上它,所以这一档只可能来自手改 `trust.json`。
|
|
4854
|
+
*/
|
|
4855
|
+
hash?: string;
|
|
4556
4856
|
}
|
|
4557
4857
|
interface TrustManager {
|
|
4558
4858
|
/** 查某个目录的信任状态(含父目录的 directory-tree 继承) */
|
|
4559
4859
|
check(dir: string): TrustLevel;
|
|
4860
|
+
/**
|
|
4861
|
+
* 查某个目录的执行类授信(含继承)。**和 {@link check} 是两个问题**:
|
|
4862
|
+
* 这一个只在 `check()` 回 `'trusted'` 时才可能授过,反过来不成立。
|
|
4863
|
+
*/
|
|
4864
|
+
checkExec(dir: string): TrustExecGrant;
|
|
4560
4865
|
/** 记录一次决策 */
|
|
4561
|
-
record(dir: string, level: DecidedTrustLevel, scope: TrustScope): void;
|
|
4866
|
+
record(dir: string, level: DecidedTrustLevel, scope: TrustScope, grant?: TrustGrant): void;
|
|
4562
4867
|
list(): readonly TrustRecord[];
|
|
4563
4868
|
revoke(dir: string): void;
|
|
4564
4869
|
}
|
|
@@ -4760,6 +5065,37 @@ type EpochUserContent = string | EpochContentPart[];
|
|
|
4760
5065
|
* 那不是「用例过时了」,是你正在改模型的输入契约(判据见 {@link OMIT_LABEL})。
|
|
4761
5066
|
*/
|
|
4762
5067
|
declare function filePartSummary(part: EpochFilePart): string;
|
|
5068
|
+
/**
|
|
5069
|
+
* 历史里的图被**摘掉**之后留在原位的那一行(2026-09-12)。
|
|
5070
|
+
*
|
|
5071
|
+
* ## 它补的是一个静默的口子,不是「又一个占位符」
|
|
5072
|
+
*
|
|
5073
|
+
* 喂模型的历史里图片是 base64 部件(`session-store.loadHistory()` 把
|
|
5074
|
+
* `inlineImages` 写死成 true)。而「当前模型认不认图」那道闸门在
|
|
5075
|
+
* `core/agent/loop.ts` 上,读的是**这一轮用户新发的图**
|
|
5076
|
+
* (`imageParts(input.userMessage)`)—— 也就是说换到一个不认图的模型之后只要
|
|
5077
|
+
* 不再发新图,历史里那些图会原样发出去:provider 那侧要么 400、要么**一声不吭
|
|
5078
|
+
* 地吞掉**(后者实测存在,判据全文在 `core/provider/capability-probe.ts` 的
|
|
5079
|
+
* 文件头)。摘掉它们的是 `AgentLoop`,留下的那一行是这一个。
|
|
5080
|
+
*
|
|
5081
|
+
* ## 为什么不复用 `contentToText` 那个 `[图片 image/jpeg]`
|
|
5082
|
+
*
|
|
5083
|
+
* 那一个是**另一个消费者**的投影(`imagesCarriedAsParts: false`,喂压缩器 /
|
|
5084
|
+
* 审计 / `messages.content` 那一列),而且它有前科:图片真的送达之后,它成了
|
|
5085
|
+
* 「唯一还在撒谎的地方」(判据在 {@link ContentToTextOptions.imagesCarriedAsParts})。
|
|
5086
|
+
* 这一行要说的是另一件事 —— 图**确实没给它**,以及为什么。
|
|
5087
|
+
*
|
|
5088
|
+
* 措辞里带上「不支持」这半句,判据同 `agent/prompt.ts` 里那条
|
|
5089
|
+
* 「不支持那一档要说清后果,别笼统一句不支持」:只写「图片未附上」的话,
|
|
5090
|
+
* 模型会去猜是不是传坏了,然后建议用户重发一次 —— 而重发多少次都一样。
|
|
5091
|
+
*
|
|
5092
|
+
* ⚠️ **不给「你可以自己去读」这类下一步**,和 `OMIT_LABEL` 的 `binary` 那档
|
|
5093
|
+
* 不同:那一档有 `file_read` 真的能拿到内容,这一档模型没有任何办法看见像素。
|
|
5094
|
+
* 给一个不存在的出口,比不给更糟。
|
|
5095
|
+
*
|
|
5096
|
+
* 逐字冻住,理由同 {@link OMIT_LABEL}(进模型 prompt、进 eval 指纹、不进 catalog)。
|
|
5097
|
+
*/
|
|
5098
|
+
declare function imagePartOmittedSummary(part: EpochImagePart): string;
|
|
4763
5099
|
/**
|
|
4764
5100
|
* 引用的会话在纯文本投影里长什么样。**不吐那段会话的正文** —— 同 `filePartSummary`。
|
|
4765
5101
|
*
|
|
@@ -5117,6 +5453,46 @@ declare const MAX_SESSION_ATTACH_BYTES: number;
|
|
|
5117
5453
|
* 那时候用户其实不知道自己要哪一段,而 `session_search` 才是干这个的。
|
|
5118
5454
|
*/
|
|
5119
5455
|
declare const MAX_SESSION_REFS = 2;
|
|
5456
|
+
/**
|
|
5457
|
+
* 把一份读出来的文件收进预算,**切口落在行边界上**(2026-09-13)。
|
|
5458
|
+
*
|
|
5459
|
+
* ## 为什么两条产出路径必须共用这一个函数
|
|
5460
|
+
*
|
|
5461
|
+
* 附件有两条来路 —— 拖进输入框(`server/src/attachments.ts` 的 `readOne`)和
|
|
5462
|
+
* `@路径`(`core/src/context/mentions.ts` 的 `readOneFile`)。两边原来各写了一遍
|
|
5463
|
+
* `raw.slice(0, budget)`,注释里互相写着「判据逐字同对方」—— 那句话本身就是在说
|
|
5464
|
+
* 「这里会走散」。现在切法只有一处,两边各自只剩「读文件」和「装 part」。
|
|
5465
|
+
*
|
|
5466
|
+
* ## 为什么从字节切改成行边界
|
|
5467
|
+
*
|
|
5468
|
+
* 原来按字节硬切,代价有两个,都是**给模型的那一侧**才暴露:
|
|
5469
|
+
*
|
|
5470
|
+
* 1. **最后一行是残的。** 一份 CSV 被切在某个字段中间,模型读到的最后一条记录
|
|
5471
|
+
* 少了几列 —— 而它长得和一条完好的记录一模一样。它不会因此报错,会**把残行
|
|
5472
|
+
* 当成数据算进去**;
|
|
5473
|
+
* 2. **接不上。** 模型要接着读得调 `file_read`,而那个工具的 `offset` 单位是**行**。
|
|
5474
|
+
* 切在字节上的话,「我读到哪儿了」这个问题在两套单位之间没有答案,它只能
|
|
5475
|
+
* `offset=1` 从头再读一遍 —— 前 100 KB 在上下文里存两份。
|
|
5476
|
+
* 收在行边界之后,`filePartSummary` 数一下换行就能报出**准确的接续行号**。
|
|
5477
|
+
*
|
|
5478
|
+
* 切口**包含那个换行符**(`slice(0, at + 1)`):这样「正文里的换行数」正好等于
|
|
5479
|
+
* 「完整行数」,接续行号恒等于 `换行数 + 1`,两种分支都不用分情况讨论。
|
|
5480
|
+
*
|
|
5481
|
+
* ## 退回硬切的那一支
|
|
5482
|
+
*
|
|
5483
|
+
* 压缩过的 JSON、单行 CSV、minify 过的 js —— 前 100 KB 里可能一个换行都没有,
|
|
5484
|
+
* 或者只有很靠前的几个。退到行边界会丢掉大半,那时候硬切才是对的。
|
|
5485
|
+
* 阈值取「丢掉超过一半就不退」,判据逐字同 plugin-file 的 `truncateOutput`。
|
|
5486
|
+
*
|
|
5487
|
+
* 只解码 `budget` 这一段,不碰整个文件 —— 原来那句「比按字符数切省一次全量解码」
|
|
5488
|
+
* 说的是这件事,仍然成立(文件可能是 200 MB,这里最多摸 100 KB)。
|
|
5489
|
+
* 留下的那一段要**重新量一次字节**:退回行边界之后真正附上的比 `budget` 少,
|
|
5490
|
+
* 而 `truncatedTo` 既要印给用户看(KB)又要算占比,不能是个约数。
|
|
5491
|
+
*/
|
|
5492
|
+
declare function truncateToBudget(raw: Uint8Array, budget: number): {
|
|
5493
|
+
text: string;
|
|
5494
|
+
truncatedTo: number;
|
|
5495
|
+
};
|
|
5120
5496
|
/**
|
|
5121
5497
|
* 当前面里的一条消息。
|
|
5122
5498
|
*
|
|
@@ -5749,6 +6125,46 @@ type WireHubEvent =
|
|
|
5749
6125
|
*/
|
|
5750
6126
|
| {
|
|
5751
6127
|
type: 'session-cooled';
|
|
6128
|
+
}
|
|
6129
|
+
/**
|
|
6130
|
+
* **会话列表变了** —— 多了一段,或者少了一段(2026-09-11)。
|
|
6131
|
+
*
|
|
6132
|
+
* ## 它治的是「不是我建的那一段」
|
|
6133
|
+
*
|
|
6134
|
+
* 会话列表(`GET /api/sessions`)在这一帧之前**只在自己动手的时候才重取**:
|
|
6135
|
+
* 这个标签页建一段、删一段,它自己重拉。于是任何**别处**建出来的会话在屏幕上
|
|
6136
|
+
* 压根不存在,得刷新一次页面才出现。两种真实情况:
|
|
6137
|
+
*
|
|
6138
|
+
* - **嵌入宿主在后台建的一段**:即时通讯桥收到一条消息 → `POST /api/sessions`
|
|
6139
|
+
* → 那一段开始干活,而电脑上那个界面一无所知(2026-09-11 一个飞书宿主实测:
|
|
6140
|
+
* 用户在手机上发完消息,PC 上看不到那段对话,**重启应用才出现** ——
|
|
6141
|
+
* 「重启才出现」正是这一帧不存在的形状);
|
|
6142
|
+
* - **另一个标签页**建的一段。判据同 `approval-resolved` 那条
|
|
6143
|
+
* (「可能是另一个标签页答的」)。
|
|
6144
|
+
*
|
|
6145
|
+
* ## 纯失效信号,**不带载荷**
|
|
6146
|
+
*
|
|
6147
|
+
* 形状和理由逐字同 `tasks-changed`:收到它的客户端回去打 `GET /api/sessions`
|
|
6148
|
+
* 重取。带上那一行的话同一件事就有了两个真源(这一帧上的一份、那条端点回的
|
|
6149
|
+
* 一份),而那条端点答的是「**侧栏该列哪几段**」—— 它按 `?q=` 过滤、按 50 行
|
|
6150
|
+
* 封顶,也就是说这一帧带来的那一行**未必该出现在列表里**。
|
|
6151
|
+
*
|
|
6152
|
+
* ## ⚠️ 信封上那个 `sessionId` 是「哪一段变了」,**不是这一帧的收件人**
|
|
6153
|
+
*
|
|
6154
|
+
* 所以客户端**不许**按「是不是我正看着的那一段」把它过滤掉 —— 它说的恰好是
|
|
6155
|
+
* 一段你还不知道的会话。web 那一侧因此在分流之前就把它拦下来
|
|
6156
|
+
* (`reducer.ts` 的 `applyFrame`:别的会话的帧会进 `parked`,而 `parkFrame`
|
|
6157
|
+
* 只认 `session-state` / `session-cooled`,别的 Hub 事件在那儿被丢掉)。
|
|
6158
|
+
*
|
|
6159
|
+
* ## ⚠️ 覆盖不到的那一档:**标题改了不发这一帧**
|
|
6160
|
+
*
|
|
6161
|
+
* 它的两个产地都在「进出 Hub」这条路上(建会话、删会话那两条端点)。而改标题
|
|
6162
|
+
* (`PATCH /api/sessions/:id`)压根不经过 Hub,只动 DB —— 于是另一个标签页上
|
|
6163
|
+
* 那一行的标题仍然会过期到下一次重取。📮 那一档要治得给它自己的产地,
|
|
6164
|
+
* 别照着这一帧的名字想当然。
|
|
6165
|
+
*/
|
|
6166
|
+
| {
|
|
6167
|
+
type: 'sessions-changed';
|
|
5752
6168
|
};
|
|
5753
6169
|
/** 信封里能装的所有东西 */
|
|
5754
6170
|
type WireEvent = WireAgentEvent | WireHubEvent;
|
|
@@ -6491,6 +6907,43 @@ interface WireSessionWorkspace extends WireWorkspaceRef {
|
|
|
6491
6907
|
skippedInstructionFiles: readonly string[];
|
|
6492
6908
|
}
|
|
6493
6909
|
declare const WIRE_SESSION_WORKSPACE_FIELDS: WireFields<WireSessionWorkspace>;
|
|
6910
|
+
/**
|
|
6911
|
+
* 一个工作区里**被闸门挡着的东西有多少**(2026-09-11,方案 61 ②)。
|
|
6912
|
+
*
|
|
6913
|
+
* ## 这一份推翻了一句写在隔壁的话
|
|
6914
|
+
*
|
|
6915
|
+
* `wire-capability.ts` 的 `WireCapabilityProject.trusted` 上写着「不能写成
|
|
6916
|
+
* 『已屏蔽 N 个』—— 那个 N 根本不存在,谁也没数过」。那句话在当时是对的:
|
|
6917
|
+
* 闸门那一侧**连 `readdir` 都不做**。现在闸门的下限放宽到了「readdir 但不读
|
|
6918
|
+
* 任何文件内容」,N 真的被数出来了(core 的 `inventoryProjectExtensions`),
|
|
6919
|
+
* 而那句话的约束 —— 不许编一个没人数过的数 —— 一个字没松。
|
|
6920
|
+
*
|
|
6921
|
+
* ## ⚠️ 这份载荷里**没有一个字段装得下仓库作者写的散文**,那是故意的
|
|
6922
|
+
*
|
|
6923
|
+
* 只有个数和路径。没有技能的 `description`、没有 hook 的 `command`、
|
|
6924
|
+
* 没有角色名。判据在 core `trust/inventory.ts` 的文件头,一句话是:
|
|
6925
|
+
* 这份东西会被画在一个用户正要点「信任」的按钮旁边,而那是渲染一段攻击者
|
|
6926
|
+
* 可控的劝说词的**最坏时机**。
|
|
6927
|
+
*
|
|
6928
|
+
* 谁要往这里加一个字符串字段,先回答它是不是仓库作者能写的。
|
|
6929
|
+
*/
|
|
6930
|
+
interface WireProjectInventory {
|
|
6931
|
+
/** 读类:项目指令文件,**相对项目根**的路径 */
|
|
6932
|
+
instructionFiles: readonly string[];
|
|
6933
|
+
/** 读类:`.epoch/skills/` 下的技能个数 */
|
|
6934
|
+
skills: number;
|
|
6935
|
+
/** 读类:`.epoch/agents/` 下的角色个数 */
|
|
6936
|
+
roles: number;
|
|
6937
|
+
/** 读类:`.epoch/commands/` 下的命令个数 */
|
|
6938
|
+
commands: number;
|
|
6939
|
+
/** 执行类:存在的 hook 配置,相对路径(`.epoch/hooks.json` / `.claude/settings*.json`) */
|
|
6940
|
+
hookFiles: readonly string[];
|
|
6941
|
+
/** 执行类:`.epoch/policies/*.toml` 的份数 */
|
|
6942
|
+
policies: number;
|
|
6943
|
+
/** 执行类:存在的项目设置文件,相对路径 */
|
|
6944
|
+
settingsFiles: readonly string[];
|
|
6945
|
+
}
|
|
6946
|
+
declare const WIRE_PROJECT_INVENTORY_FIELDS: WireFields<WireProjectInventory>;
|
|
6494
6947
|
/**
|
|
6495
6948
|
* 引擎**自动压缩**的那条线 —— 三个数,决定 8 的第三个时刻(「快满了」)要的全部输入。
|
|
6496
6949
|
*
|
|
@@ -6701,6 +7154,27 @@ interface WireConfigResponse {
|
|
|
6701
7154
|
* 给一份将来会长歪的副本。
|
|
6702
7155
|
*/
|
|
6703
7156
|
maxCostUsd?: number;
|
|
7157
|
+
/**
|
|
7158
|
+
* 屏幕上那些金额印成什么币种 —— **没配就没有这个键**(2026-09-13)。
|
|
7159
|
+
*
|
|
7160
|
+
* 形状同 {@link maxCostUsd}:可选键,而「没有这个键」的语义是**用美元**
|
|
7161
|
+
* (绝大多数用户),不是「宿主没想好」。所以它也不在
|
|
7162
|
+
* `WIRE_CONFIG_RESPONSE_FIELDS` 那张必填表上。
|
|
7163
|
+
*
|
|
7164
|
+
* ## ⚠️ 下发的是 `{code, rate}`,而 `rate` **不许画到界面上**
|
|
7165
|
+
*
|
|
7166
|
+
* 浏览器要自己算(`costUsd × rate`),所以汇率必须上网线 —— 但它是**算料,
|
|
7167
|
+
* 不是读数**。界面上写一句「按 7.1 折算」是把用户自己填的常量念回给他听,
|
|
7168
|
+
* 判据全文在 [money.ts](./money.js) 文件头那一节。
|
|
7169
|
+
*
|
|
7170
|
+
* ## ⚠️ 它不改变网线上任何一个金额字段的单位
|
|
7171
|
+
*
|
|
7172
|
+
* `WireSessionSummary.costUsd`、`usage` 帧里的 `costUsd`、{@link maxCostUsd}
|
|
7173
|
+
* 本身 —— **全都还是美元**,一个都没跟着变。这一格只是告诉浏览器
|
|
7174
|
+
* 「印出来的时候乘这个数、换这个符号」。反过来(服务端先换算好再下发)
|
|
7175
|
+
* 会让 `costUsd` 这个名字当场变成假话,而**没有任何一处会红**。
|
|
7176
|
+
*/
|
|
7177
|
+
currency?: CurrencyDisplay;
|
|
6704
7178
|
/**
|
|
6705
7179
|
* 宿主品牌词标 —— **宿主没配就没有这个键**(决定 19)。
|
|
6706
7180
|
*
|
|
@@ -7471,8 +7945,30 @@ declare const WIRE_PATCH_SESSION_RESPONSE_FIELDS: WireFields<WirePatchSessionRes
|
|
|
7471
7945
|
interface EpochTurnFacts {
|
|
7472
7946
|
/** 这一轮的真实用量。provider 没上报就没有这一格 —— **不写 0** */
|
|
7473
7947
|
usage?: TokenUsage;
|
|
7474
|
-
/**
|
|
7948
|
+
/**
|
|
7949
|
+
* 这一轮**真正跑的**那个模型。
|
|
7950
|
+
*
|
|
7951
|
+
* ⚠️ 它和顶栏上那个不一样,**成因有四种,而只有后两种是故障**:
|
|
7952
|
+
* 用户 `/model` 换了、命令 frontmatter 的 `model:` 覆盖了、provider 失败降级、
|
|
7953
|
+
* 路由 404 同家换模型。
|
|
7954
|
+
*
|
|
7955
|
+
* 这句注释原来只列了后两种,而那正是一次真实缺陷的源头:web 脚注照着它
|
|
7956
|
+
* 把「这一格和配置里那个不等」读成了「降级了」,于是用户换一次模型就被告知
|
|
7957
|
+
* 出了故障。**要分辨是哪一种,看这一格和 {@link requestedModel} 这一对**,
|
|
7958
|
+
* 别拿它去和任何「当前模型」比。
|
|
7959
|
+
*/
|
|
7475
7960
|
model?: string;
|
|
7961
|
+
/**
|
|
7962
|
+
* 这一轮**开跑时要求**的那个模型 —— 和 {@link model} 是一对。
|
|
7963
|
+
*
|
|
7964
|
+
* 两格都在、且不等 = 这一轮真的降级了。两个值都**冻在这一轮里**,
|
|
7965
|
+
* 所以之后用户再换多少次模型都不影响这条断言,刷新之后也照样准。
|
|
7966
|
+
*
|
|
7967
|
+
* 缺席 = 不知道这一轮要的是谁(老库的行里没有这一列,引擎也可能一次模型
|
|
7968
|
+
* 调用都没发生)。那时读侧一律**什么都不画** —— 拿 {@link model} 自比恒相等,
|
|
7969
|
+
* 会被读成「确认没降级」,那是一个假事实。
|
|
7970
|
+
*/
|
|
7971
|
+
requestedModel?: string;
|
|
7476
7972
|
/** 这一轮从开跑到收尾的墙上时间。起点未知时没有这一格,不写 0 */
|
|
7477
7973
|
durationMs?: number;
|
|
7478
7974
|
/**
|
|
@@ -7559,8 +8055,57 @@ interface WireSendMessageRequest {
|
|
|
7559
8055
|
* 得到的交集仍然只读,用户挑了一个专家而什么都没发生。
|
|
7560
8056
|
*/
|
|
7561
8057
|
role?: string;
|
|
8058
|
+
/**
|
|
8059
|
+
* 这一条带上哪几个**已经传上去的**附件(2026-09-11)。
|
|
8060
|
+
*
|
|
8061
|
+
* ## ⚠️ 里面是**文件名**,不是路径 —— 这是这条链上最要紧的一处收窄
|
|
8062
|
+
*
|
|
8063
|
+
* 附件的字节先走 `POST /api/sessions/:id/attachments` 落进
|
|
8064
|
+
* `~/.epoch/attachments/<会话 id>/`,那一发回来一个 `name`(服务端净化 +
|
|
8065
|
+
* 去重之后的最终名字)。这里原样把那个 `name` 送回来。
|
|
8066
|
+
*
|
|
8067
|
+
* 收路径的版本得在服务端把 `..`、绝对路径、符号链接逐个挡一遍,而那是一张
|
|
8068
|
+
* **永远数不全的清单**。收名字之后路径由引擎算(`AttachmentControl.resolve`),
|
|
8069
|
+
* 浏览器就没有任何办法指向那个目录之外 —— 不是「我们挡住了已知的写法」,
|
|
8070
|
+
* 是值域里压根没有能跑出去的元素。
|
|
8071
|
+
*
|
|
8072
|
+
* 认不出来的名字**不是 400**:产出一个 `omitted: 'unreadable'` 的部件照常发出去,
|
|
8073
|
+
* 判据同下面那些失败档 —— 用户已经按了发送,为一个附件掉整条消息是更坏的交换,
|
|
8074
|
+
* 而收据会把这一条如实说出来。
|
|
8075
|
+
*
|
|
8076
|
+
* 缺席 = 这一条没有附件。**不写进下面那份必填清单**,同 `role`。
|
|
8077
|
+
*/
|
|
8078
|
+
attachments?: readonly string[];
|
|
7562
8079
|
}
|
|
7563
8080
|
declare const WIRE_SEND_MESSAGE_FIELDS: WireFields<WireSendMessageRequest>;
|
|
8081
|
+
/**
|
|
8082
|
+
* `POST /api/sessions/:id/attachments` 的回执(2026-09-11)。
|
|
8083
|
+
*
|
|
8084
|
+
* 请求体是**裸字节**(`application/octet-stream`),原始文件名走查询串
|
|
8085
|
+
* `?name=`。不用 multipart:这条路上只有一个文件、没有别的字段,
|
|
8086
|
+
* 而 multipart 要在服务端引一个解析器(或手写一个),换来的只是把一个
|
|
8087
|
+
* 查询参数搬进 body。
|
|
8088
|
+
*
|
|
8089
|
+
* ## ⚠️ 没有大小上限,这是拍过的决定
|
|
8090
|
+
*
|
|
8091
|
+
* 服务端**边收边写盘**(`streamBodyToFile`),峰值内存是一个 chunk,
|
|
8092
|
+
* 和文件多大无关。护栏是另外两道:认证(同别的 API),以及
|
|
8093
|
+
* `~/.epoch/attachments/` 那本 512MB 的总账(从最旧的会话删起)。
|
|
8094
|
+
* 判据全文在 core 的 `ATTACHMENT_MAX_TOTAL_BYTES` 和 server 的
|
|
8095
|
+
* `streamBodyToFile` 上 —— 两处都写着「这拦不住当前会话里传一个 2GB 的文件」。
|
|
8096
|
+
*/
|
|
8097
|
+
interface WireAttachmentUploadResponse {
|
|
8098
|
+
/**
|
|
8099
|
+
* 最终落盘的文件名。**可能和你传的不一样**(净化过、撞名加了 `-1`)。
|
|
8100
|
+
*
|
|
8101
|
+
* 发消息时把**这一个**放进 {@link WireSendMessageRequest.attachments},
|
|
8102
|
+
* 界面上那枚 chip 也该显示它 —— 显示原名的话,用户在会话目录里找不到那个文件。
|
|
8103
|
+
*/
|
|
8104
|
+
name: string;
|
|
8105
|
+
/** 真正落下去的字节数。界面拿它显示大小,也是「传完整了吗」的唯一凭据 */
|
|
8106
|
+
bytes: number;
|
|
8107
|
+
}
|
|
8108
|
+
declare const WIRE_ATTACHMENT_UPLOAD_FIELDS: WireFields<WireAttachmentUploadResponse>;
|
|
7564
8109
|
/**
|
|
7565
8110
|
* 立即 202,结果走 SSE。不是长轮询 —— 5 分钟的任务会撞上任何一层代理的超时。
|
|
7566
8111
|
*
|
|
@@ -8643,6 +9188,114 @@ type WirePickDirectoryResponse = {
|
|
|
8643
9188
|
} | {
|
|
8644
9189
|
canceled: true;
|
|
8645
9190
|
};
|
|
9191
|
+
/**
|
|
9192
|
+
* 「请弹一个授信对话框」——**门铃,不是开关**(方案 61)。
|
|
9193
|
+
*
|
|
9194
|
+
* ## ⚠️ 先读这一段:信任的写入口**没有**上网线
|
|
9195
|
+
*
|
|
9196
|
+
* 全仓最贵的那条纪律逐字还在(方案 42 PR-3,判据在 `wire-security.ts` 文件头):
|
|
9197
|
+
* 把信任的写入口搬到 HTTP 上,等于让浏览器决定「哪个目录里的文件能当指令读」。
|
|
9198
|
+
*
|
|
9199
|
+
* 这条端点**不是**那个写入口,两件事把它和写入口分开:
|
|
9200
|
+
*
|
|
9201
|
+
* 1. **载荷里没有 `level`,也没有 `scope`。** 浏览器表达不出「把 X 设成已信任」,
|
|
9202
|
+
* 它只能说「我想解锁 X,去问问用户」。档位和作用域由宿主的对话框决定;
|
|
9203
|
+
* 2. **服务端自己不落盘。** 它只调宿主注入的那个回调
|
|
9204
|
+
* (`CreateWebServerOptions.onTrustRequest`),落盘发生在宿主主进程里的
|
|
9205
|
+
* `runtime.trust.record()` —— 而那儿是可信代码,和 CLI 同一档。
|
|
9206
|
+
*
|
|
9207
|
+
* 形状照抄 `POST /api/workspaces/pick`:浏览器发起一个**它自己答不了**的请求,
|
|
9208
|
+
* 答案来自一个人在别处按的那一下。
|
|
9209
|
+
*
|
|
9210
|
+
* ## 200 不代表授信了
|
|
9211
|
+
*
|
|
9212
|
+
* 响应里**没有** `granted` 那一格,这是刻意的:这条端点在宿主把对话框**弹出来**
|
|
9213
|
+
* 之后(或者干脆在 resolve 时)就回 200,它不报告用户选了什么。
|
|
9214
|
+
* 要知道结果就重新取一次 `GET /api/sessions/:id/security`(或 capabilities)——
|
|
9215
|
+
* 那两份载荷里的 `trusted` / `execTrusted` 是唯一真源。
|
|
9216
|
+
*
|
|
9217
|
+
* 回一个 `granted` 的代价很具体:那个布尔和盘上的记录会各自演化(宿主的框可能
|
|
9218
|
+
* 开着不关、用户可能在 CLI 里同时改),而两者分叉时界面会信错的那一个。
|
|
9219
|
+
*/
|
|
9220
|
+
interface WireTrustRequestRequest {
|
|
9221
|
+
/**
|
|
9222
|
+
* 要解锁的目录(服务端绝对路径)。
|
|
9223
|
+
*
|
|
9224
|
+
* ⚠️ **服务端必须校验它**:只接受这个会话绑着的根、或者「已知工作区」清单里
|
|
9225
|
+
* 的某一行。不校验的话,一个页面就能让宿主弹出一个「要不要信任 `/`」的框 ——
|
|
9226
|
+
* 而对话框本身是可信的,被滥用的是「让谁出现在框里」这件事。
|
|
9227
|
+
*/
|
|
9228
|
+
root: string;
|
|
9229
|
+
/**
|
|
9230
|
+
* 想解锁哪一档 —— **提示,不是命令**(缺省 `read`)。
|
|
9231
|
+
*
|
|
9232
|
+
* 它只影响宿主对话框的默认落点:用户从技能页点进来那一下多半只想要读类,
|
|
9233
|
+
* 从「hook 没生效」那一处点进来才是执行类。宿主可以无视它。
|
|
9234
|
+
*/
|
|
9235
|
+
want?: 'read' | 'exec';
|
|
9236
|
+
}
|
|
9237
|
+
declare const WIRE_TRUST_REQUEST_FIELDS: WireFields<WireTrustRequestRequest>;
|
|
9238
|
+
/**
|
|
9239
|
+
* `POST /api/workspaces/trust-request` 的响应。
|
|
9240
|
+
*
|
|
9241
|
+
* **只有一格,而且它只说「问出去了」。** 别在这里加 `granted` —— 判据在上面。
|
|
9242
|
+
*/
|
|
9243
|
+
interface WireTrustRequestResponse {
|
|
9244
|
+
/** 宿主的回调被调起来了(对话框弹没弹、用户选了什么,这一格都不知道) */
|
|
9245
|
+
asked: true;
|
|
9246
|
+
}
|
|
9247
|
+
declare const WIRE_TRUST_REQUEST_RESPONSE_FIELDS: WireFields<WireTrustRequestResponse>;
|
|
9248
|
+
/**
|
|
9249
|
+
* 划掉一行**使用记录**。
|
|
9250
|
+
*
|
|
9251
|
+
* ## ⚠️ 它和信任没有关系,这一条是这条端点唯一容易读错的地方
|
|
9252
|
+
*
|
|
9253
|
+
* 划掉的只是「我最近在这儿干过活」。那个目录的信任判定一个字都不动 ——
|
|
9254
|
+
* 下次再绑回去,它照旧是已信任 / 已拒绝 / 未决定里原来那一档。
|
|
9255
|
+
* 撤销信任是**另一条路**(`epoch trust rm`,刻意不上网线)。
|
|
9256
|
+
*
|
|
9257
|
+
* 两件事在界面上挨着,但把它们串起来的代价很具体:用户清理一张堆满临时目录的
|
|
9258
|
+
* 列表时,会顺手把一个仓库的授信也删掉,而他以为自己只是在扫地。
|
|
9259
|
+
*
|
|
9260
|
+
* ## 所以它**可以**上网线,而信任不行
|
|
9261
|
+
*
|
|
9262
|
+
* 判据是「这一下最坏能造成什么」:信任的写入口决定「哪个目录里的文件能当指令读」,
|
|
9263
|
+
* 而这一条最坏就是让一行从一份「最近用过」的列表里消失 —— 那份列表本身
|
|
9264
|
+
* 不参与任何判定。
|
|
9265
|
+
*/
|
|
9266
|
+
interface WireForgetWorkspaceRequest {
|
|
9267
|
+
/** 要划掉的那一行(服务端绝对路径,逐字取自清单里的 `root`) */
|
|
9268
|
+
root: string;
|
|
9269
|
+
}
|
|
9270
|
+
declare const WIRE_FORGET_WORKSPACE_FIELDS: WireFields<WireForgetWorkspaceRequest>;
|
|
9271
|
+
/**
|
|
9272
|
+
* 划完之后的**整张清单**,而不是一个 `{ok:true}`。
|
|
9273
|
+
*
|
|
9274
|
+
* 回全量是刻意的:这一屏上那张卡的计数(「已知 N 个」)和表格是同一份数据的两处
|
|
9275
|
+
* 投影,让浏览器自己从本地数组里删一行再重算,等于把那个算术抄第二遍 ——
|
|
9276
|
+
* 而抄错的表现是删完之后卡上的数和表里的行数对不上,刷新一下又好了。
|
|
9277
|
+
*/
|
|
9278
|
+
interface WireForgetWorkspaceResponse {
|
|
9279
|
+
/** 划完之后剩下的行,顺序同 `GET /api/sessions/:id/security` 里那一份 */
|
|
9280
|
+
known: readonly WireKnownWorkspaceRef[];
|
|
9281
|
+
}
|
|
9282
|
+
/**
|
|
9283
|
+
* 上面那份响应里的一行。
|
|
9284
|
+
*
|
|
9285
|
+
* ⚠️ **它就是 `WireKnownWorkspace`**,只是 protocol 里这两个文件的依赖方向是
|
|
9286
|
+
* 单向的(`wire-security.ts` import 这儿,不反过来)。写成一个结构相同的别名
|
|
9287
|
+
* 而不是把类型搬过来:搬过去的话,安全中心那份载荷的定义会散在两个文件里。
|
|
9288
|
+
*/
|
|
9289
|
+
interface WireKnownWorkspaceRef {
|
|
9290
|
+
root: string;
|
|
9291
|
+
name: string;
|
|
9292
|
+
level: 'trusted' | 'untrusted' | 'unknown';
|
|
9293
|
+
trusted: boolean;
|
|
9294
|
+
current: boolean;
|
|
9295
|
+
exists: boolean;
|
|
9296
|
+
execTrusted: boolean;
|
|
9297
|
+
}
|
|
9298
|
+
declare const WIRE_FORGET_WORKSPACE_RESPONSE_FIELDS: WireFields<WireForgetWorkspaceResponse>;
|
|
8646
9299
|
/**
|
|
8647
9300
|
* `GET /api/sessions/:id/context` —— **这一段会话**此刻的预算构成。
|
|
8648
9301
|
*
|
|
@@ -8707,31 +9360,6 @@ interface WireCompactResponse {
|
|
|
8707
9360
|
}
|
|
8708
9361
|
declare const WIRE_COMPACT_FIELDS: WireFields<WireCompactResponse>;
|
|
8709
9362
|
|
|
8710
|
-
/**
|
|
8711
|
-
* 能力页的载荷契约 —— `GET /api/sessions/:id/capabilities`(方案 42 PR-1)。
|
|
8712
|
-
*
|
|
8713
|
-
* ## 为什么单开一个文件而不是塞进 `wire-rest.ts`
|
|
8714
|
-
*
|
|
8715
|
-
* 那个文件已经 788 行,早就压过了 CLAUDE.md 铁律 3 的 500 行线。往一个已经超标
|
|
8716
|
-
* 的文件里再加一百多行,等于把违规做实。这一份是**一个端点**的契约,边界清楚,
|
|
8717
|
-
* 单独成文件天然成立 —— 规矩、`wireFields` 那套工具、导出位置全部照 `wire-rest.ts`
|
|
8718
|
-
* 来,只是住在隔壁。
|
|
8719
|
-
*
|
|
8720
|
-
* ## 三屏为什么是**一个**端点
|
|
8721
|
-
*
|
|
8722
|
-
* 专家 / 技能 / 连接器在界面上是三个分栏,但它们是**同一次「我现在有什么」**:
|
|
8723
|
-
* 用户点进能力页就要看到全部三栏的计数(导航那一列上就印着数字),拆成三个端点
|
|
8724
|
-
* 的结果是首屏必然并发三发、而且三份数据可能来自三个不同的瞬间。
|
|
8725
|
-
*
|
|
8726
|
-
* ## 为什么挂在 `/sessions/:id/` 底下
|
|
8727
|
-
*
|
|
8728
|
-
* 今天这个进程里只有一个会话,所以「进程有哪些角色 / 技能」和「这个会话有哪些
|
|
8729
|
-
* 角色 / 技能」是同一份东西。**但它们不是同一个概念**:角色和技能里的「项目」
|
|
8730
|
-
* 那一层来自工作区(`<root>/.epoch/agents/`、`<root>/.epoch/skills/`),而工作区
|
|
8731
|
-
* 是**按会话**绑的(决定 18)。等方案 30 §6.3 的多会话工厂落地,同一个进程里的
|
|
8732
|
-
* 两个会话会看到两份不同的项目层 —— 那时候要改的是服务端的取数,**不是 URL**。
|
|
8733
|
-
* 现在就把 URL 定成会话作用域,是为了那一天不用再动一次前端。
|
|
8734
|
-
*/
|
|
8735
9363
|
/**
|
|
8736
9364
|
* 一个角色在网线上的样子。
|
|
8737
9365
|
*
|
|
@@ -8978,18 +9606,67 @@ interface WireMcpConnector {
|
|
|
8978
9606
|
source: 'user' | 'host' | 'plugin';
|
|
8979
9607
|
}
|
|
8980
9608
|
declare const WIRE_MCP_CONNECTOR_FIELDS: WireFields<WireMcpConnector>;
|
|
9609
|
+
/**
|
|
9610
|
+
* 两个布尔 → 三档 {@link WireMcpConnector.state}。**判序的唯一产地。**
|
|
9611
|
+
*
|
|
9612
|
+
* ⚠️ `needsLogin` **排在 `connected` 前面**:认证过不去的 server 也可能是
|
|
9613
|
+
* connected(连上了,但工具调用会被拒),那时该说的是「去登录」而不是
|
|
9614
|
+
* 「一切正常」。判序的完整理由在 {@link WireMcpConnector} 上那张表里。
|
|
9615
|
+
*
|
|
9616
|
+
* ## 为什么摘成一个函数住在 protocol(2026-09-11)
|
|
9617
|
+
*
|
|
9618
|
+
* 它原来是 `server/src/capability.ts` 的 `toWireMcp()` 里那个三元,而那时它只有
|
|
9619
|
+
* **一个**消费者,摘出来是纯开销。这一天长出了第二个:模型自述那一段
|
|
9620
|
+
* (`core/src/agent/self-index.ts`,取数在 `runtime/src/self-index.ts`)要回答
|
|
9621
|
+
* 「我连了哪几台、连上了吗」,而 runtime **不许 import server**。
|
|
9622
|
+
*
|
|
9623
|
+
* 于是只有两条路:在 runtime 里照抄一遍那个三元,或者摘到两边都够得着的地方。
|
|
9624
|
+
* 抄一遍的下场很具体 —— 两处判序走散之后,**能力页说「去登录」而模型说
|
|
9625
|
+
* 「一切正常」**,而两处都答得出「我判了」。这正是上面那段 ⚠️ 拦的那件事,
|
|
9626
|
+
* 只是换了个方向。
|
|
9627
|
+
*/
|
|
9628
|
+
declare function mcpConnectorState(server: {
|
|
9629
|
+
connected: boolean;
|
|
9630
|
+
needsLogin?: boolean;
|
|
9631
|
+
}): WireMcpConnector['state'];
|
|
8981
9632
|
/**
|
|
8982
9633
|
* 「项目」那一层的来源。角色和技能共用它 —— 两边读的是同一个工作区根,
|
|
8983
9634
|
* 也卡在同一道信任闸门上。
|
|
8984
9635
|
*
|
|
8985
9636
|
* ⚠️ `trusted` 为假时,角色和技能里**不会有** `project` 那一档,而且原因不是
|
|
8986
|
-
* 「过滤掉了」:`loader.ts`
|
|
8987
|
-
*
|
|
9637
|
+
* 「过滤掉了」:`loader.ts` 在不受信任时**连读都不读**。界面上那句话必须照实说。
|
|
9638
|
+
*
|
|
9639
|
+
* ## ⚠️ 2026-09-11:上面那句话原来还有半句,那半句被推翻了
|
|
9640
|
+
*
|
|
9641
|
+
* 原文是「不能写成『已屏蔽 N 个』—— 那个 N 根本不存在,谁也没数过」。
|
|
9642
|
+
* 现在 N 存在了:{@link inventory} 由 core 的 `inventoryProjectExtensions()` 数出来,
|
|
9643
|
+
* 它**只 readdir、不读任何文件内容**,所以「连读都不读」那半句照旧成立
|
|
9644
|
+
* (读的是目录项,不是文件)。
|
|
9645
|
+
*
|
|
9646
|
+
* 放宽的理由是宿主那条路:界面原来只能说「它的技能一个都没读」外加一条用户
|
|
9647
|
+
* 跑不了的命令,而「这个仓库里有 7 个技能、1 个 hooks.json」是把「要不要信任」
|
|
9648
|
+
* 从一道信仰题变成判断题的唯一材料。
|
|
9649
|
+
*
|
|
9650
|
+
* **但那句话的内核一个字没松**:不许编一个没人数过的数。谁要在这一屏写出一个
|
|
9651
|
+
* {@link inventory} 里没有的数字,先去把它数出来。
|
|
8988
9652
|
*/
|
|
8989
9653
|
interface WireCapabilityProject {
|
|
8990
9654
|
/** 工作区主根(服务端绝对路径)。没绑工作区就是 `null` */
|
|
8991
9655
|
root: string | null;
|
|
9656
|
+
/** 读类:指令文件 / 技能 / 角色 / 命令加载了吗 */
|
|
8992
9657
|
trusted: boolean;
|
|
9658
|
+
/**
|
|
9659
|
+
* 执行类:hook / 策略 / 项目设置生效了吗。
|
|
9660
|
+
*
|
|
9661
|
+
* 这一屏用不到它去过滤任何东西(技能和角色全在读类那一档),发它只为一件事:
|
|
9662
|
+
* 那块「未信任」的提示要说得出**这一次到底差哪一档** —— 一个只授了读类的
|
|
9663
|
+
* 工作区,它的技能明明列出来了,再说一句「这个工作区还没被信任」就是假话。
|
|
9664
|
+
*/
|
|
9665
|
+
execTrusted: boolean;
|
|
9666
|
+
/** 这个目录里有什么被挡着。**未信任时也是满的**,那正是它的用处 */
|
|
9667
|
+
inventory: WireProjectInventory;
|
|
9668
|
+
/** 宿主接了「请求授信」那条回调吗 —— 判据同 `WireSecurityWorkspace.trustRequest` */
|
|
9669
|
+
trustRequest: boolean;
|
|
8993
9670
|
}
|
|
8994
9671
|
declare const WIRE_CAPABILITY_PROJECT_FIELDS: WireFields<WireCapabilityProject>;
|
|
8995
9672
|
interface WireCapabilitiesResponse {
|
|
@@ -9223,8 +9900,10 @@ declare const WIRE_SKILL_BODY_FIELDS: WireFields<WireSkillBodyResponse>;
|
|
|
9223
9900
|
* 「是用户自己的机器」这个前提**不成立**;
|
|
9224
9901
|
* 3. 方案 42 PR-3 已经判过一次同形状的事(信任的写入口刻意不上网线)。
|
|
9225
9902
|
*
|
|
9226
|
-
*
|
|
9227
|
-
*
|
|
9903
|
+
* 所以浏览器在**这两条上**只能选,不能造 —— 它们的请求体里没有一个字节会变成
|
|
9904
|
+
* system prompt 里的字。要加上传,**别在这儿加一个 `content` 字段**:
|
|
9905
|
+
* 交字节那条路是单独一条端点,判据全文在 {@link WireSkillStageResponse} 上
|
|
9906
|
+
* (一句话:它落在扫描范围之外、吃一道 403、而且它一个技能都装不上)。
|
|
9228
9907
|
*/
|
|
9229
9908
|
type WireSkillImportForm = 'markdown' | 'skill-dir' | 'tree' | 'archive';
|
|
9230
9909
|
/** 整件事没成的原因。**单个技能坏掉不在其列** —— 那走 `skipped` */
|
|
@@ -9323,6 +10002,87 @@ interface WireSkillImportResponse {
|
|
|
9323
10002
|
reason: WireSkillImportFailure | null;
|
|
9324
10003
|
}
|
|
9325
10004
|
declare const WIRE_SKILL_IMPORT_FIELDS: WireFields<WireSkillImportResponse>;
|
|
10005
|
+
/**
|
|
10006
|
+
* 一份技能能以什么形态交上来。
|
|
10007
|
+
*
|
|
10008
|
+
* = 插件那张表({@link WIRE_PLUGIN_ARCHIVE_SUFFIXES})**再加一档 `.md`** ——
|
|
10009
|
+
* 「单独一份带 frontmatter 的 `.md`」是技能这条路自己就有的一种形态
|
|
10010
|
+
* (`SkillImportForm` 的 `markdown` 那一格),而插件没有对应物。
|
|
10011
|
+
*
|
|
10012
|
+
* ⚠️ 这张表**只在浏览器那一侧省一次空跑**(松手那一刻就说「这个不行」,
|
|
10013
|
+
* 而不是等 40MB 传完)。服务端不靠它判内容:解包交给 bsdtar 按**内容**认,
|
|
10014
|
+
* 「里面有没有技能」交给后面那一次预览。判据同 `plugin-drop.tsx` 文件头第二节。
|
|
10015
|
+
*/
|
|
10016
|
+
declare const WIRE_SKILL_DROP_SUFFIXES: readonly [".zip", ".tgz", ".tar.gz", ".md"];
|
|
10017
|
+
/** 一条路径 / 文件名收不收。**只看后缀**,口径逐字同 {@link isWirePluginArchiveName} */
|
|
10018
|
+
declare function isWireSkillDropName(name: string): boolean;
|
|
10019
|
+
/** 交上来那一发没成的三档,各对一个不同的下一步 */
|
|
10020
|
+
type WireSkillStageFailure =
|
|
10021
|
+
/** 后缀不在 {@link WIRE_SKILL_DROP_SUFFIXES} 里 —— 换个东西再拖 */
|
|
10022
|
+
'not-archive'
|
|
10023
|
+
/** 解不开 —— 这个包坏了,或者它压根不是个包 */
|
|
10024
|
+
| 'unpack-failed'
|
|
10025
|
+
/** 写不下去(盘满、没权限) */
|
|
10026
|
+
| 'write-failed';
|
|
10027
|
+
/**
|
|
10028
|
+
* `POST /api/skills/stage` —— 浏览器里那一份字节 → 服务端本机一条路径(2026-09-13)。
|
|
10029
|
+
*
|
|
10030
|
+
* ## ⚠️ 一、它答的是上面那两条端点上那句提示的**反面**
|
|
10031
|
+
*
|
|
10032
|
+
* 那一屏的输入框顶着一句「说的是运行 epoch 那台电脑,**不是你这台**」。那句话
|
|
10033
|
+
* 是真的、也必须在,但它把用户堵在原地 —— 他手里的技能就在**他这台**上。
|
|
10034
|
+
* 这条端点就是那条路:字节走网线过去落地、解开,回来一条服务端那台机器上的
|
|
10035
|
+
* 路径,接着走原来那两步(`import/preview` → `import`)。
|
|
10036
|
+
*
|
|
10037
|
+
* 于是它和那个输入框**并排,不是替代** —— 两条答的是两个不同的问题。
|
|
10038
|
+
*
|
|
10039
|
+
* ## ⚠️ 二、上面那段「浏览器只能选,不能造」为什么没被它推翻
|
|
10040
|
+
*
|
|
10041
|
+
* 三条,缺一条这个设计就不成立:
|
|
10042
|
+
*
|
|
10043
|
+
* 1. **落点在扫描范围之外。** 字节落进 `~/.epoch/skill-drops/`,而
|
|
10044
|
+
* `scanSkillDirs` 扫的是 `~/.epoch/skills/`。**传上来 ≠ 装上了** ——
|
|
10045
|
+
* 这一发结束时,system prompt 里一个字都没变;
|
|
10046
|
+
* 2. **给人的那道闸门一格没动。** 出口是一条路径,它下游接的就是原来那两条,
|
|
10047
|
+
* 连 `token` 那条防 TOCTOU 的缝都照旧。用户仍然要看过「将导入什么」那一屏
|
|
10048
|
+
* 才按得下确认;
|
|
10049
|
+
* 3. **它吃一道 403。** `epoch web --host 0.0.0.0` 那一档下这条端点**直接拒**
|
|
10050
|
+
* (口径逐字同 `POST /api/plugins/stage` 和 `POST /api/agent-roles`)。
|
|
10051
|
+
* 这一条是三条里最硬的:上面那段判据的第 2 句说的正是「那一档下『是用户
|
|
10052
|
+
* 自己的机器』这个前提不成立」,而不成立的时候我们就不收字节。
|
|
10053
|
+
*
|
|
10054
|
+
* ⚠️ 那道 403 在**读 body 之前**判,而这条端点上它比别处刻薄:body 上限是
|
|
10055
|
+
* 50 MiB,漏一格就是让 LAN 上的人一发一发地灌这台机器的内存。
|
|
10056
|
+
*
|
|
10057
|
+
* ## ⚠️ 三、它**一个技能都不装,也一个都不验**
|
|
10058
|
+
*
|
|
10059
|
+
* 出口只有「解开之后那条目录路径」(`.md` 那一档就是那个文件本身)。
|
|
10060
|
+
* **「里面有没有技能」这个问题这一层不答** —— 它由紧接着那一次
|
|
10061
|
+
* `import/preview` 答,而那一侧的答案好得多:它说得出「找到三份、其中一份
|
|
10062
|
+
* 名字不合法」。在这儿先判一道的下场是两处各判一半,而两处分叉的那天
|
|
10063
|
+
* 没有任何东西会红(同 `plugin-drop.tsx` 文件头那条「抄的,不是共用的」的教训)。
|
|
10064
|
+
*
|
|
10065
|
+
* ## ⚠️ 四、文件名走 query 上的 `?name=`,而它是这条路上唯一不可信的输入
|
|
10066
|
+
*
|
|
10067
|
+
* body 就是那份字节本身,所以**这一半没有请求体形状可写**,别以为是漏了。
|
|
10068
|
+
* 名字来自网线,一个 `../../.ssh/authorized_keys` 会让落点跑出 `skill-drops/` ——
|
|
10069
|
+
* 唯一那道收窄在 runtime 的 `safeBaseName`(和插件那条共用同一份)。
|
|
10070
|
+
*/
|
|
10071
|
+
interface WireSkillStageResponse {
|
|
10072
|
+
ok: boolean;
|
|
10073
|
+
/**
|
|
10074
|
+
* 成了 = 服务端本机一条绝对路径(解开的目录,或者那份 `.md`);没成 = `null`。
|
|
10075
|
+
*
|
|
10076
|
+
* ⚠️ **别把它填回那个路径输入框**:它落在 `~/.epoch/skill-drops/` 里,
|
|
10077
|
+
* 对用户来说是一个他没见过的地方,印出来只会让他以为自己填错了。
|
|
10078
|
+
* 拿到它直接开下一屏(预览),判据同 {@link WirePluginStageResponse.path}。
|
|
10079
|
+
*/
|
|
10080
|
+
path: string | null;
|
|
10081
|
+
/** 没成时那句为什么(服务端原话,界面原样上屏);成了是 `null` */
|
|
10082
|
+
detail: string | null;
|
|
10083
|
+
reason: WireSkillStageFailure | null;
|
|
10084
|
+
}
|
|
10085
|
+
declare const WIRE_SKILL_STAGE_FIELDS: WireFields<WireSkillStageResponse>;
|
|
9326
10086
|
/**
|
|
9327
10087
|
* 删不成的原因。**四档,各对一个不同的下一步**,判据同
|
|
9328
10088
|
* {@link WireSkillSummary.residency} 那三档:合成一个 `ok:false` 之后界面说得出
|
|
@@ -9523,8 +10283,9 @@ interface WireRoleAddResponse {
|
|
|
9523
10283
|
declare const WIRE_ROLE_ADD_RESPONSE_FIELDS: WireFields<WireRoleAddResponse>;
|
|
9524
10284
|
|
|
9525
10285
|
/**
|
|
9526
|
-
* 插件那一页的契约 ——
|
|
9527
|
-
* 2026-09-04 补,见下面第一节的**翻案**;上传 2026-09-08
|
|
10286
|
+
* 插件那一页的契约 —— 十四条端点(方案 59 §六 E2,2026-08-21;本地源与市场管理
|
|
10287
|
+
* 2026-09-04 补,见下面第一节的**翻案**;上传 2026-09-08 补,见第一节之二;
|
|
10288
|
+
* 落区 2026-09-11 补,见 {@link WirePluginStageRequest})。
|
|
9528
10289
|
*
|
|
9529
10290
|
* ```
|
|
9530
10291
|
* GET /api/plugins 装着的 + 市场里有什么 + 已加的市场 + pendingRestart + uploadEnabled
|
|
@@ -9540,6 +10301,7 @@ declare const WIRE_ROLE_ADD_RESPONSE_FIELDS: WireFields<WireRoleAddResponse>;
|
|
|
9540
10301
|
* POST /api/plugins/upload/preview {path} → 会打包哪些文件,一个字节都不发
|
|
9541
10302
|
* POST /api/plugins/upload {path, token} → 打包 + 交给宿主
|
|
9542
10303
|
* POST /api/plugins/refresh {} → 让宿主重拉目录 + 回一份新列表
|
|
10304
|
+
* POST /api/plugins/stage {path} 或字节 → 落地 + 解包 + 验清单 → 一条目录路径
|
|
9543
10305
|
* ```
|
|
9544
10306
|
*
|
|
9545
10307
|
* 底座是 `EpochRuntime.plugins`(方案 59 PR-4 落的那一片,判据全文在
|
|
@@ -9639,13 +10401,21 @@ declare const WIRE_ROLE_ADD_RESPONSE_FIELDS: WireFields<WireRoleAddResponse>;
|
|
|
9639
10401
|
* 那几条单独点名 —— 而**它们仍然在 `files` 里面**(静默剔除会让用户以为发出去的
|
|
9640
10402
|
* 是全量,判据在 core `pack.ts` 的文件头第四节)。
|
|
9641
10403
|
*
|
|
9642
|
-
* # 二、⚠️
|
|
10404
|
+
* # 二、⚠️ 闸门:**绑在回环之外时那十三条 POST 一律 403**
|
|
9643
10405
|
*
|
|
9644
10406
|
* > 这个数原来是「九条」,上传那两条 2026-09-08 加进来,刷新那一条 2026-09-10
|
|
9645
10407
|
* > 加进来(判据在 {@link WirePluginRefreshResponse} 第三节:它让**宿主**发一次
|
|
9646
10408
|
* > 出站请求,而这条路的前提是「网线另一头就是这台机器」)。**它们吃同一道闸,
|
|
9647
10409
|
* > 而且是这一整张表里最该吃的两条**:它们读这台机器上任意一条目录、把内容
|
|
9648
10410
|
* > **发到外面去**。放行的话,一个 LAN 上的人能指着 `~/.ssh` 说「上传它」。
|
|
10411
|
+
* >
|
|
10412
|
+
* > 落区那一条 2026-09-11 加进来({@link WirePluginStageRequest})。⚠️ 它最容易
|
|
10413
|
+
* > 被当成例外 —— 「字节是浏览器那台机器上的,又不读服务端的目录」。**但它落了盘,
|
|
10414
|
+
* > 而落下来的东西下一步就要被装,装进去的 `hooks.json` 起子进程。** 风险在落地
|
|
10415
|
+
* > 之后那一步,不在字节从哪儿来。⚠️ 它还有一条独占的理由:那道闸**必须在读
|
|
10416
|
+
* > 请求体之前**(`server/src/plugin.ts` 文件头第 4 条),而这一条的请求体是
|
|
10417
|
+
* > 几十 MB —— 别处漏一格是多解析一次 JSON,这儿漏一格是让 LAN 上的任何人
|
|
10418
|
+
* > 把这台机器的内存灌满。
|
|
9649
10419
|
*
|
|
9650
10420
|
* 判据同 [wire-agent-role.ts](./wire-agent-role.ts) 那道,但**这条路比它还远一格**,
|
|
9651
10421
|
* 四条:
|
|
@@ -9714,6 +10484,33 @@ declare const WIRE_ROLE_ADD_RESPONSE_FIELDS: WireFields<WireRoleAddResponse>;
|
|
|
9714
10484
|
* 界面据此说「这是一条软链 / 这是 clone 下来的」。
|
|
9715
10485
|
*/
|
|
9716
10486
|
type WirePluginSourceType = 'local' | 'git' | 'npm' | 'archive' | 'host';
|
|
10487
|
+
/**
|
|
10488
|
+
* 认得的压缩包后缀(2026-09-11,落区那一轮)。**全仓只有这一份。**
|
|
10489
|
+
*
|
|
10490
|
+
* ## ⚠️ 它摆在 protocol 里,是为了让浏览器和 core 用**同一张表**
|
|
10491
|
+
*
|
|
10492
|
+
* core 的 `resolveSource()` 靠这几个后缀把一条本地路径分成「目录」还是「压缩包」
|
|
10493
|
+
* (`plugin/source.ts` 的 `isArchiveUrl`,那儿写着「判的是后缀而不是它此刻是不是
|
|
10494
|
+
* 一个文件」);而落区在浏览器里松手的那一刻要当场答同一个问题 ——
|
|
10495
|
+
* 拖进来的这一个是压缩包,还是一个说不清的文件。
|
|
10496
|
+
*
|
|
10497
|
+
* 两边各写一份的表现最刻薄:浏览器放行了一个 `.tar.bz2`,字节发上去、落了盘,
|
|
10498
|
+
* 然后在服务端被判成「不认识」—— 一次本可以在松手那一刻就说清的拒绝,
|
|
10499
|
+
* 变成了一次几十 MB 的空跑。
|
|
10500
|
+
*
|
|
10501
|
+
* ⚠️ **不含 `.tar`**(不压缩的裸 tar)和 `.tar.bz2` / `.tar.xz`:这一份是
|
|
10502
|
+
* core 那条正则 `/\.(zip|tgz|tar\.gz)$/i` 的**原样搬家**,不是一次扩容。
|
|
10503
|
+
* 要加一档就两边一起验(`extractArchive` 交给 bsdtar,它认得比这张表多),
|
|
10504
|
+
* 而不是在这儿先放行。
|
|
10505
|
+
*/
|
|
10506
|
+
declare const WIRE_PLUGIN_ARCHIVE_SUFFIXES: readonly [".zip", ".tgz", ".tar.gz"];
|
|
10507
|
+
/**
|
|
10508
|
+
* 一条路径 / 文件名看起来是不是压缩包。**只看后缀**,不碰磁盘。
|
|
10509
|
+
*
|
|
10510
|
+
* ⚠️ 大小写不敏感(Windows 上一个 `FOO.ZIP` 很常见),而 `?` 后面的东西先切掉 ——
|
|
10511
|
+
* 同 core 那个 `isArchiveUrl`:这个函数在网线两侧都会被喂到带 query 的字符串。
|
|
10512
|
+
*/
|
|
10513
|
+
declare function isWirePluginArchiveName(name: string): boolean;
|
|
9717
10514
|
/**
|
|
9718
10515
|
* 那一条是**谁都能装**还是**只有我能装**(2026-09-08)。
|
|
9719
10516
|
*
|
|
@@ -9811,6 +10608,27 @@ interface WirePluginCounts {
|
|
|
9811
10608
|
/** 装着的一个插件在浏览器眼里的样子 */
|
|
9812
10609
|
interface WirePluginEntry {
|
|
9813
10610
|
name: string;
|
|
10611
|
+
/**
|
|
10612
|
+
* **给人看的名字**(2026-09-11)。`null` = 说不出来,界面上就印 {@link name}。
|
|
10613
|
+
*
|
|
10614
|
+
* ## ⚠️ 它是**这一刻从目录里 join 出来的**,不是装的时候存下来的
|
|
10615
|
+
*
|
|
10616
|
+
* `plugins.json` 那条安装记录上没有这一格(那儿存的是身份和来源)。这一格由
|
|
10617
|
+
* `server/src/plugin.ts` 拿**市场那份快照**比出来 —— 和 {@link WirePluginHit.installed}
|
|
10618
|
+
* 恰好是同一次 join 的两个方向(那一格也在那一层算,判据在 `toWirePluginHit` 上)。
|
|
10619
|
+
*
|
|
10620
|
+
* ⚠️ **于是它会在这几种情况下变回 `null`,而那不是 bug**:这一条从本机目录装的
|
|
10621
|
+
* (压根没有市场)、装完之后那个市场被移除了、或者它在目录里下架了。
|
|
10622
|
+
* 口径同 `WirePluginHit.downloads` 上那条「目录是快照」—— 我们印的是
|
|
10623
|
+
* 「目录**现在**管它叫什么」,不是「装的那天它叫什么」。
|
|
10624
|
+
*
|
|
10625
|
+
* ## ⚠️ 有它的时候界面**照样要印 {@link name}**
|
|
10626
|
+
*
|
|
10627
|
+
* 判据逐字同 `WirePluginHit.displayName`:那一格是**显示名**,`name` 是**标识** ——
|
|
10628
|
+
* 而标识正是用户在命令里真要敲的前缀(`/queqi-geo:xxx`)和权限规则里会看见的
|
|
10629
|
+
* 那一个。只印显示名等于让「这个插件叫什么」在界面和命令行上是两个答案。
|
|
10630
|
+
*/
|
|
10631
|
+
displayName: string | null;
|
|
9814
10632
|
version: string;
|
|
9815
10633
|
/** 用户 / 宿主敲的那串来源,原样 */
|
|
9816
10634
|
source: string;
|
|
@@ -9943,17 +10761,36 @@ interface WirePluginHit {
|
|
|
9943
10761
|
/**
|
|
9944
10762
|
* **装着的那个比市场说的旧**(2026-09-08)。
|
|
9945
10763
|
*
|
|
9946
|
-
* ##
|
|
10764
|
+
* ## 🔴 2026-09-11 翻案:`false` 现在**收得掉**那枚更新按钮,条件是目录刷得动
|
|
9947
10765
|
*
|
|
9948
|
-
*
|
|
9949
|
-
*
|
|
10766
|
+
* 原来那条规矩是「`false` 什么都不减,别拿 `!updateAvailable` 去隐藏任何东西」,
|
|
10767
|
+
* 算的是这么一笔账:市场目录是**加市场那一刻的快照**(会过时,判据在 core
|
|
10768
|
+
* `MarketplaceEntry.version` 上那张两行的表),于是
|
|
9950
10769
|
*
|
|
9951
|
-
* - 说「有新版本」而其实没有 →
|
|
10770
|
+
* - 说「有新版本」而其实没有 → 用户点一下,更新回同一版。**烦,不坏**;
|
|
9952
10771
|
* - 说「已是最新」而其实有 → **一次真的更新被藏起来**。
|
|
9953
10772
|
*
|
|
9954
|
-
*
|
|
9955
|
-
*
|
|
9956
|
-
*
|
|
10773
|
+
* 两件事把这笔账翻了过来:
|
|
10774
|
+
*
|
|
10775
|
+
* 1. **目录不再是一份没人管的快照**(2026-09-10 的 `refresh` + 同轮加的
|
|
10776
|
+
* 「进插件页自动刷一遍」)。`refreshEnabled` 为真时,「市场说版本一样」
|
|
10777
|
+
* 这句话是**刚问来的**,上面第二条那个代价没有了;
|
|
10778
|
+
* 2. **「点一下回同一版」不是零成本。** 那一下走的是完整的 `preview` + `install`
|
|
10779
|
+
* 两发(`plugin-install.ts` 的 `createInstallFlow`),也就是**两次取包**——
|
|
10780
|
+
* 在一个按下载量记账的市场里,它是给一个什么都没变的操作记两笔
|
|
10781
|
+
* (2026-09-11 星云那侧的后台反馈:装一个插件下载数 +2)。
|
|
10782
|
+
*
|
|
10783
|
+
* 于是今天的规矩是:
|
|
10784
|
+
*
|
|
10785
|
+
* | | 市场那一行 | 装着那一行 |
|
|
10786
|
+
* | --- | --- | --- |
|
|
10787
|
+
* | `true` | 「已装上」换成一枚**更新按钮** | 多一句「有新版本」+ 一枚更新按钮 |
|
|
10788
|
+
* | `false`,目录**刷得动** | 「已装上」 | 那一枚**不画** |
|
|
10789
|
+
* | `false`,目录**刷不动** | 「已装上」 | 那一枚**照旧画**(快照会过时,而用户没办法让它不过时) |
|
|
10790
|
+
*
|
|
10791
|
+
* ⚠️ 最后一行是这条翻案的**边界**,别顺手抹平:`epoch web --plugins` 那种不给
|
|
10792
|
+
* `refresh` 回调的宿主就落在那一档,对它们收按钮才是原来那条判据说的
|
|
10793
|
+
* 「藏掉一次真的更新」。界面那一侧的落法在 `plugins.tsx` 的 `canUpdate` 上。
|
|
9957
10794
|
*
|
|
9958
10795
|
* ## `false` 有三种成因,而界面不需要分
|
|
9959
10796
|
*
|
|
@@ -10131,6 +10968,71 @@ interface WirePluginLocalInstallRequest extends WirePluginLocalRequest {
|
|
|
10131
10968
|
token: string;
|
|
10132
10969
|
}
|
|
10133
10970
|
declare const WIRE_PLUGIN_LOCAL_INSTALL_FIELDS: WireFields<WirePluginLocalInstallRequest>;
|
|
10971
|
+
/**
|
|
10972
|
+
* `POST /api/plugins/stage` 的请求体 —— **JSON 那一种入口**(2026-09-11)。
|
|
10973
|
+
*
|
|
10974
|
+
* ## ⚠️ 这条端点有两种入口、一种出口,而出口是这一节的正题
|
|
10975
|
+
*
|
|
10976
|
+
* 出口永远是**一条已经验过的插件目录绝对路径**({@link WirePluginStageResponse.path})。
|
|
10977
|
+
* 于是它下游接的就是原来那四条(`install/local{,/preview}`、`upload{,/preview}`),
|
|
10978
|
+
* 一个字都不用改 —— 包括 runtime 那道「必须是绝对路径 + 必须解析成 `local`」的闸
|
|
10979
|
+
* (`resolveLocal`)。**那道闸永远看不到一个压缩包**,这是刻意的:
|
|
10980
|
+
* 把它放宽成「也收压缩包」的话,「装一个目录」和「装一个包」就在同一个形状上
|
|
10981
|
+
* 有了两种落地方式(软链 vs 解包拷贝),而界面上看不出区别。
|
|
10982
|
+
*
|
|
10983
|
+
* | 入口 | 收什么 | 解到哪儿 |
|
|
10984
|
+
* | ----------------------------- | ---------------------------- | ---------------------------- |
|
|
10985
|
+
* | `application/json`(这一条) | 本机一条**压缩包**绝对路径 | **它自己的同级目录** |
|
|
10986
|
+
* | `application/octet-stream` | 浏览器里拖 / 选的那一份字节 | `~/.epoch/plugin-drops/` 里 |
|
|
10987
|
+
*
|
|
10988
|
+
* ⚠️ **字节那一种没有请求体形状可写**(body 就是包本身),文件名走 query 上的
|
|
10989
|
+
* `name=`。所以这个 interface 只描述得了 JSON 那一半,别以为另一半是漏了。
|
|
10990
|
+
*
|
|
10991
|
+
* ## ⚠️ 它**一个字节都不删**,这是契约
|
|
10992
|
+
*
|
|
10993
|
+
* 用户交给我们的是他自己的文件。原包原地不动、解出来的目录留在它旁边,
|
|
10994
|
+
* 装完传完都不删;同名不覆盖,顺次 `-1` / `-2`。判据在
|
|
10995
|
+
* `infra/paths.ts` 的 `pluginDropsDir` 上(那儿还记了「为什么装完不能顺手清」)。
|
|
10996
|
+
*
|
|
10997
|
+
* ## 它吃**同一道** 403
|
|
10998
|
+
*
|
|
10999
|
+
* 字节是从浏览器那台机器来的没错,但落地之后装进去的 `hooks.json` / `mcp.json`
|
|
11000
|
+
* **会起子进程** —— 那正是下面第二节那道闸存在的全部理由。判据同
|
|
11001
|
+
* `install/local`:不因为「来源换了个方向」就换一套风险口径。
|
|
11002
|
+
*/
|
|
11003
|
+
interface WirePluginStageRequest {
|
|
11004
|
+
/** 本机上一条**绝对**路径,指向一个压缩包(后缀见 {@link WIRE_PLUGIN_ARCHIVE_SUFFIXES}) */
|
|
11005
|
+
path: string;
|
|
11006
|
+
}
|
|
11007
|
+
declare const WIRE_PLUGIN_STAGE_FIELDS: WireFields<WirePluginStageRequest>;
|
|
11008
|
+
/**
|
|
11009
|
+
* `POST /api/plugins/stage` 的回执。
|
|
11010
|
+
*
|
|
11011
|
+
* ⚠️ `path` 是**目录**不是包 —— 见 {@link WirePluginStageRequest} 第一节。
|
|
11012
|
+
* 界面拿到它之后原样递给 `install/local/preview` 或 `upload/preview`,
|
|
11013
|
+
* **自己不解析、不拼接、也不显示给用户当路径填回输入框**:那条路径落在
|
|
11014
|
+
* `~/.epoch/plugin-drops/` 里时,对用户来说是一个他没见过的地方,
|
|
11015
|
+
* 印出来只会让他以为自己填错了。
|
|
11016
|
+
*
|
|
11017
|
+
* `name` / `version` 读自解出来那份 `epoch-plugin.json`,给界面在跳转前
|
|
11018
|
+
* 说一句「认出来了,是 xxx」用。⚠️ 它们**不是**下一屏那份预览的替代品:
|
|
11019
|
+
* 那一屏才是这条路上给人的闸门(会起几个子进程、带几条 hook),
|
|
11020
|
+
* 判据逐字同 `plugin-add.tsx` 文件头第三节。
|
|
11021
|
+
*/
|
|
11022
|
+
interface WirePluginStageResponse {
|
|
11023
|
+
ok: boolean;
|
|
11024
|
+
/** 成了 = 一条插件目录绝对路径;没成 = `null` */
|
|
11025
|
+
path: string | null;
|
|
11026
|
+
/** 解出来那份清单里的名字。没成时 `null` */
|
|
11027
|
+
name: string | null;
|
|
11028
|
+
/** 同上 */
|
|
11029
|
+
version: string | null;
|
|
11030
|
+
/** 没成时那句给人看的话,**带得出下一步**。成了那一档是 `null` */
|
|
11031
|
+
detail: string | null;
|
|
11032
|
+
/** 没成是哪一档。成了那一档是 `null` */
|
|
11033
|
+
reason: WirePluginRefuseReason | null;
|
|
11034
|
+
}
|
|
11035
|
+
declare const WIRE_PLUGIN_STAGE_RESPONSE_FIELDS: WireFields<WirePluginStageResponse>;
|
|
10134
11036
|
/**
|
|
10135
11037
|
* `POST /api/plugins/marketplaces` 的请求体 —— 加一个市场。
|
|
10136
11038
|
*
|
|
@@ -10205,7 +11107,20 @@ declare const WIRE_PLUGIN_UPDATE_FIELDS: WireFields<WirePluginUpdateRequest>;
|
|
|
10205
11107
|
* 后者是「换一条市场引用」。合成一档的表现是界面拿同一句话去答两个问题 ——
|
|
10206
11108
|
* 而这条路上最常见的一次输入错误恰恰就是把 `github:` 贴进了本地那个框。
|
|
10207
11109
|
*/
|
|
10208
|
-
type WirePluginRefuseReason = 'unknown-ref' | 'not-local'
|
|
11110
|
+
type WirePluginRefuseReason = 'unknown-ref' | 'not-local'
|
|
11111
|
+
/**
|
|
11112
|
+
* 落区那三档(2026-09-11)。⚠️ **三档而不是一档**,判据同上面 `not-local`
|
|
11113
|
+
* 为什么不并进 `unknown-ref`:三个的下一步互不相同,而用户在落区上最常撞的
|
|
11114
|
+
* 恰恰是第一档(把一个 `.tar.bz2` 或者一个单独的 `.md` 拖了进来)。
|
|
11115
|
+
*
|
|
11116
|
+
* - `not-archive` —— 后缀不在 {@link WIRE_PLUGIN_ARCHIVE_SUFFIXES} 里。
|
|
11117
|
+
* 下一步:换一个 zip,或者干脆把**文件夹**拖进来;
|
|
11118
|
+
* - `unpack-failed` —— 解不开(包坏了 / 不是真的压缩包 / 加密过)。
|
|
11119
|
+
* 下一步:在自己机器上先解一次看看;
|
|
11120
|
+
* - `not-plugin` —— 解开了,但里面没有 `epoch-plugin.json`。
|
|
11121
|
+
* 下一步:确认拖的是插件本身那一层,而不是装着它的那个上级目录。
|
|
11122
|
+
*/
|
|
11123
|
+
| 'not-archive' | 'unpack-failed' | 'not-plugin' | 'remote-disabled' | 'conflict' | 'stale-token' | 'not-installed' | 'nothing-to-do' | 'upload-unavailable' | 'refresh-unavailable' | 'upload-rejected' | 'failed';
|
|
10209
11124
|
/** 一次 hook 盘点:这个事件上有几条 */
|
|
10210
11125
|
interface WirePluginHookTally {
|
|
10211
11126
|
type: string;
|
|
@@ -11153,6 +12068,34 @@ interface WireSecurityWorkspace extends WireSessionWorkspace {
|
|
|
11153
12068
|
* 后者是「把那个目录设成主根,或者把内容并进主根的约定文件」。
|
|
11154
12069
|
*/
|
|
11155
12070
|
unloadedExtraInstructionFiles: readonly string[];
|
|
12071
|
+
/**
|
|
12072
|
+
* **执行类**也授了吗(2026-09-11)。`trusted` 是读类那一档。
|
|
12073
|
+
*
|
|
12074
|
+
* 两格都要发,因为 `trusted: true` + `execTrusted: false` 是拆档之后**最常见**
|
|
12075
|
+
* 的一种状态(存量记录全在这儿),而界面上只有一个「已信任」的话,
|
|
12076
|
+
* 用户看到的是「已信任」配上「我的 hook 没跑」—— 一对无法自洽的事实。
|
|
12077
|
+
*/
|
|
12078
|
+
execTrusted: boolean;
|
|
12079
|
+
/**
|
|
12080
|
+
* 这个目录里有什么被挡着({@link WireProjectInventory})。
|
|
12081
|
+
*
|
|
12082
|
+
* **未信任时也是满的**,那正是它的用处:这一屏原来只能说「有东西没加载」,
|
|
12083
|
+
* 说不出有多少。
|
|
12084
|
+
*/
|
|
12085
|
+
inventory: WireProjectInventory;
|
|
12086
|
+
/**
|
|
12087
|
+
* 这个服务背后的宿主接了「请求授信」那条回调吗(方案 61 的门铃)。
|
|
12088
|
+
*
|
|
12089
|
+
* 为真时界面画一枚按钮(点它 = 请宿主弹自己的对话框),为假时画今天那块
|
|
12090
|
+
* 「复制 `epoch trust add`」。**不画灰按钮**(决定 20 ①:画一个点了没反应的
|
|
12091
|
+
* 菜单项,比不画更糟)。
|
|
12092
|
+
*
|
|
12093
|
+
* ⚠️ **它是进程级的事实,却在两份载荷上各出现一次**(这里和
|
|
12094
|
+
* `WireCapabilityProject.trustRequest`)。不抽成第三个端点是因为那要让这两屏
|
|
12095
|
+
* 各多打一发 GET,而「一次取齐」是这两份载荷共同的形状。两处**同源**——
|
|
12096
|
+
* server 从同一个 `CreateWebServerOptions.onTrustRequest` 是否存在算出来。
|
|
12097
|
+
*/
|
|
12098
|
+
trustRequest: boolean;
|
|
11156
12099
|
}
|
|
11157
12100
|
declare const WIRE_SECURITY_WORKSPACE_FIELDS: WireFields<WireSecurityWorkspace>;
|
|
11158
12101
|
/**
|
|
@@ -11175,6 +12118,35 @@ interface WireKnownWorkspace extends WireWorkspaceRef {
|
|
|
11175
12118
|
trusted: boolean;
|
|
11176
12119
|
/** 这个会话此刻绑在这儿 */
|
|
11177
12120
|
current: boolean;
|
|
12121
|
+
/**
|
|
12122
|
+
* 这个目录**现在还在盘上吗**(2026-09-11)。
|
|
12123
|
+
*
|
|
12124
|
+
* ## 为什么这一格非有不可
|
|
12125
|
+
*
|
|
12126
|
+
* 这份清单只增不减(`RecentWorkspaces.remember()` 是唯一的写口),于是跑过一阵
|
|
12127
|
+
* 之后它会塞满已经不存在的目录 —— 临时目录、删掉的项目、拔了的外置盘。
|
|
12128
|
+
* 实测一台开发机:**20 行里 16 行指向的目录已经没了**。
|
|
12129
|
+
*
|
|
12130
|
+
* 而界面在这一格出现之前**分不出它们**,于是那一屏把 16 行死路径和 4 行真目录
|
|
12131
|
+
* 并排画成同一种东西,还在上面那张卡上汇总成一句「18 个未信任」——
|
|
12132
|
+
* 读起来像 18 件待办,而其中绝大多数是清理,不是授信。
|
|
12133
|
+
*
|
|
12134
|
+
* ⚠️ **它不是「有没有权限读」**:`existsSync` 为假只说明那个路径现在不在。
|
|
12135
|
+
* 服务进程没权限看的目录也会报 false —— 两者对用户的下一步恰好相同
|
|
12136
|
+
* (这一行现在没用),所以不拆成两格。
|
|
12137
|
+
*
|
|
12138
|
+
* ⚠️ **别拿它当「该不该信任」的输入。** 信任一个还没 clone 下来的目录是合理
|
|
12139
|
+
* 用法(`epoch trust add` 那条路上明写着),这一格只影响**怎么显示**。
|
|
12140
|
+
*/
|
|
12141
|
+
exists: boolean;
|
|
12142
|
+
/**
|
|
12143
|
+
* 执行类也授了吗 —— 同 {@link WireSecurityWorkspace.execTrusted}。
|
|
12144
|
+
*
|
|
12145
|
+
* 逐行发它是因为「已信任」在拆档之后有两种,而这张表是**这台机器上**信任状态
|
|
12146
|
+
* 的唯一全貌:只印一个「已信任」的话,用户在这儿看到的和他在主根那一节看到的
|
|
12147
|
+
* 是两句对不上的话。
|
|
12148
|
+
*/
|
|
12149
|
+
execTrusted: boolean;
|
|
11178
12150
|
}
|
|
11179
12151
|
declare const WIRE_KNOWN_WORKSPACE_FIELDS: WireFields<WireKnownWorkspace>;
|
|
11180
12152
|
/**
|
|
@@ -11547,12 +12519,14 @@ declare const WIRE_PERMISSION_SET_RESPONSE_FIELDS: WireFields<WirePermissionSetR
|
|
|
11547
12519
|
* 这是整份契约里最要紧的一个字段,理由见它自己的 JSDoc。
|
|
11548
12520
|
* ⚠️ 2026-08-31 起**哪几档由键决定**:只有 `SettingsFileSchema` 白名单里那两个
|
|
11549
12521
|
* 标量给得出 ④,其余可写键的 `writes` 里只有 ② 一档(`settingWriteLayers()`)
|
|
11550
|
-
* 3.
|
|
12522
|
+
* 3. **写完要重启进程 —— 除了 `model`**({@link WireSettingApply})。它 2026-09-13
|
|
12523
|
+
* 分叉成了 `new-session`:此后新开的会话用新值,正在跑的那些不变
|
|
11551
12524
|
*
|
|
11552
|
-
* ⚠️ 读响应里那些 `value`
|
|
11553
|
-
*
|
|
11554
|
-
*
|
|
11555
|
-
*
|
|
12525
|
+
* ⚠️ 读响应里那些 `value`,**`restart` 那一档写完不会变**,而那不是 bug:这个进程
|
|
12526
|
+
* 装配时读过一次配置就不再重读。界面在写完之后照旧印旧值、另说一句
|
|
12527
|
+
* 「已写进 X,重启后生效」,判据同 {@link WireSettingApply}。把行上那个值乐观地改成
|
|
12528
|
+
* 新值,就是这一屏存在的理由本身要消灭的那种撒谎 —— 而这一条对 `new-session`
|
|
12529
|
+
* 那一档**同样成立**(正在跑的会话按的仍是旧值),只是它下一次 `GET` 会真的变。
|
|
11556
12530
|
*
|
|
11557
12531
|
* ## 会话作用域,不是进程级的 `/api/settings`
|
|
11558
12532
|
*
|
|
@@ -11653,22 +12627,37 @@ declare const WIRE_SETTING_WRITE_LAYERS: readonly ["user", "projectLocal"];
|
|
|
11653
12627
|
type WireSettingWriteLayer = (typeof WIRE_SETTING_WRITE_LAYERS)[number] & WireSettingLayer;
|
|
11654
12628
|
declare function isWireSettingWriteLayer(value: unknown): value is WireSettingWriteLayer;
|
|
11655
12629
|
/**
|
|
11656
|
-
*
|
|
12630
|
+
* 写完要做什么它才生效。**两档,而且它们都是关于进程的话,不是关于会话的**。
|
|
12631
|
+
*
|
|
12632
|
+
* `loadConfig()` 在装配时跑一次,之后这个进程手上那份配置再也不重读。所以对
|
|
12633
|
+
* `restart` 那一档的键,落盘那一刻正在跑的会话不变、**新开一个会话也不变**、
|
|
12634
|
+
* 连 `GET` 回来的值都还是旧的 —— 于是「重启」的准确含义是重启 `epoch web`
|
|
12635
|
+
* 那个进程。这条必须说破,不说的话用户改完、新建一个会话、发现行为没变,
|
|
12636
|
+
* 然后对着一个没动静的界面发呆。
|
|
11657
12637
|
*
|
|
11658
|
-
*
|
|
11659
|
-
* 之后这个进程手上那份配置再也不重读。所以落盘那一刻,正在跑的会话不变、
|
|
11660
|
-
* **新开一个会话也不变**、连 `GET` 回来的值都还是旧的。于是「重启」在这条路上
|
|
11661
|
-
* 的准确含义是重启 `epoch web` 那个进程 —— 这条必须说破,不说的话用户改完
|
|
11662
|
-
* `model`、新建一个会话、发现还是旧模型,然后对着一个没变的行为发呆。
|
|
12638
|
+
* ## ✅ `model` 2026-09-13 分叉出去了
|
|
11663
12639
|
*
|
|
11664
|
-
*
|
|
11665
|
-
*
|
|
12640
|
+
* 上一版这里写着「今天只有 `restart` 一档」,并且预告了这一天:「这个进程里已经
|
|
12641
|
+
* 有一条运行期换模型的路(`ModelControl`),哪天设置页接上它,`model` 就先变成
|
|
12642
|
+
* 另一档」。接上了,那一档叫 `new-session`。
|
|
11666
12643
|
*
|
|
11667
|
-
*
|
|
11668
|
-
*
|
|
11669
|
-
*
|
|
12644
|
+
* ⚠️ **`model` 这一行的 `apply` 不是恒定的**:provider 层起不来的那台机器上它仍是
|
|
12645
|
+
* `restart`(那时这个进程一个会话都建不出来,「新开的会话会用它」是假话)。
|
|
12646
|
+
* 所以界面**必须照发下来的这一格画,不许照键名硬编码**。判据全文在 core 的
|
|
12647
|
+
* `config/write.ts` 的 `SettingApplyFacts.canOpenSessions` 上。
|
|
12648
|
+
*
|
|
12649
|
+
* **仍然不摆 `live` 那一档占位**,判据同下面 `plugin` 那一条:摆一档永远不会出现
|
|
12650
|
+
* 的值,等于告诉读代码的人「有些键改完当场就生效」,而那是假的。
|
|
12651
|
+
*
|
|
12652
|
+
* 它挂在**每一个(键, 层)**上而不是整份响应上 —— 这一天到了之后,那句话不再是
|
|
12653
|
+
* 一个预告而是一条正在成立的性质:同一份响应里 `model` 那行是 `new-session`、
|
|
12654
|
+
* `maxTurns` 那行是 `restart`。
|
|
11670
12655
|
*/
|
|
11671
|
-
type WireSettingApply =
|
|
12656
|
+
type WireSettingApply =
|
|
12657
|
+
/** 要重启 `epoch web` 那个进程 */
|
|
12658
|
+
'restart'
|
|
12659
|
+
/** **此后新开的会话**用新值;正在跑的那些不变,也不用重启 */
|
|
12660
|
+
| 'new-session';
|
|
11672
12661
|
/**
|
|
11673
12662
|
* 写进去了却仍然不生效的两种成因。**这是整份契约里最要紧的一个东西。**
|
|
11674
12663
|
*
|
|
@@ -11855,10 +12844,18 @@ declare const WIRE_SETTINGS_WRITE_REQUEST_FIELDS: WireFields<WireSettingsWriteRe
|
|
|
11855
12844
|
/**
|
|
11856
12845
|
* 写成功之后的回执。**它不是新的一行** —— 行还是旧的那一行。
|
|
11857
12846
|
*
|
|
11858
|
-
*
|
|
11859
|
-
*
|
|
11860
|
-
*
|
|
11861
|
-
*
|
|
12847
|
+
* 界面拿这份回执画的是**一句话**,而那句话按 {@link apply} 分两档:
|
|
12848
|
+
*
|
|
12849
|
+
* - `restart`:「已写进 ④ 项目本地(<path>);本进程仍在用 <旧值>,重启后生效」
|
|
12850
|
+
* - `new-session`:「已写进 ②(<path>);此后新开的会话用它,正在跑的这些不变」
|
|
12851
|
+
*
|
|
12852
|
+
* **两档都不许把那一行的值乐观地换成新的。** `restart` 那档的理由是老的
|
|
12853
|
+
* (进程没重读,行上那个值真的没变);`new-session` 那档的理由换了一个,
|
|
12854
|
+
* 而结论一样:那一行答的是「**这个进程**此刻按的是什么」,而正在跑的会话
|
|
12855
|
+
* 按的仍是旧值 —— 乐观地换掉就是替一屏正在生效的旧行为印了个新名字。
|
|
12856
|
+
*
|
|
12857
|
+
* 值真的变没变由下一次 `GET` 说(`model` 走 `new-session` 那一档时它会跟着动,
|
|
12858
|
+
* 判据在 {@link WireSettingApply})。
|
|
11862
12859
|
*/
|
|
11863
12860
|
interface WireSettingsWriteResponse {
|
|
11864
12861
|
key: string;
|
|
@@ -12081,6 +13078,34 @@ interface WireProviderOption {
|
|
|
12081
13078
|
* 不是发全的让浏览器自己截(那样 key 已经过了网线)。
|
|
12082
13079
|
*/
|
|
12083
13080
|
keyHint: string | null;
|
|
13081
|
+
/**
|
|
13082
|
+
* **这台机器此刻配的就是这一家**(2026-09-11)。十三家里最多一家是 `true`。
|
|
13083
|
+
*
|
|
13084
|
+
* ## 加它是为了让选择器「一展示就有清单」
|
|
13085
|
+
*
|
|
13086
|
+
* 改造前浏览器这一侧 `provider` 的初值是 `undefined`,于是打开顶栏那张菜单
|
|
13087
|
+
* 看到的是一句「挑一家」和一个空的模型下拉 —— 用户必须先在 provider 那一格
|
|
13088
|
+
* 上手动选中他**本来就在用的那一家**,才会发出第一发探测。多一步、而且那一步
|
|
13089
|
+
* 的信息量是零(答案只有一个)。
|
|
13090
|
+
*
|
|
13091
|
+
* 有了这一格,`useModelCatalog` 在 provider 单子回来的那一刻就能自动探它。
|
|
13092
|
+
*
|
|
13093
|
+
* ## ⚠️ 为什么不让浏览器自己去比对
|
|
13094
|
+
*
|
|
13095
|
+
* 浏览器手上确实有一个「此刻的模型」(`GET /api/config` 的
|
|
13096
|
+
* `WireProviderSummary`,以及会话那一份 `WireModelSelection`),拿它去和这张
|
|
13097
|
+
* 单子对一遍也能得出同样的结论 —— **但那是在下游重建一份判断**。
|
|
13098
|
+
* `config.ts` 的文件头逐字记着这个病(「被复制了三遍,加一个 provider 要改
|
|
13099
|
+
* 四处」)。服务端本来就知道答案(`ModelCatalogOptions.configured`),
|
|
13100
|
+
* 让它直接说出来。
|
|
13101
|
+
*
|
|
13102
|
+
* ## ⚠️ 它**不是**「选中态」
|
|
13103
|
+
*
|
|
13104
|
+
* 说的是「配置里写的是这一家」。用户在菜单里点到别家之后,界面的选中态跟着
|
|
13105
|
+
* 走,而这一格纹丝不动 —— 它到下一次 `GET /api/providers` 之前都不会变。
|
|
13106
|
+
* 拿它当受控组件的 `value` 会得到一个点不动的下拉。
|
|
13107
|
+
*/
|
|
13108
|
+
current: boolean;
|
|
12084
13109
|
}
|
|
12085
13110
|
declare const WIRE_PROVIDER_OPTION_FIELDS: WireFields<WireProviderOption>;
|
|
12086
13111
|
/** `GET /api/providers` 的响应 */
|
|
@@ -13592,4 +14617,4 @@ declare const SECRET_SERVICE = "epoch-agent";
|
|
|
13592
14617
|
*/
|
|
13593
14618
|
declare const MCP_DATA_KEY_NAME = "mcp-auth-data-key";
|
|
13594
14619
|
|
|
13595
|
-
export { ACTION_CONTEXTS, AGENT_ROLE_NAME_PATTERN, API_KEY_ENV_VARS, APPROVAL_OUTCOMES, type ActiveAgentRole, type AgentEvent, type AgentEventOf, type AgentEventType, type AgentRole, type AgentRoleScope, type AgentRoleSource, type ApprovalAnswer, type ApprovalOutcome, type ApprovalReply, type ApprovalRequest, type ArtifactKind, type AttributeValue, type Attributes, type BackgroundTaskInfo, type BackgroundTaskKind, type BackgroundTaskStatus, type BlankCard, type BlankGreeting, type BoundKey, type BudgetBreach, COMMAND_NAME_PATTERN, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, type Catalogs, type ComplianceAction, type ComplianceCategory, type ContextBreakdown, type ContextSegment, type CustomCommandDef, type CustomCommandSource, DEFAULT_AGENT_ROLE, DEFAULT_LANG, type DecidedTrustLevel, type Diagnostic, DiagnosticSink, type DiagnosticStatus, type EpochConfig, type EpochContentPart, type EpochFilePart, type EpochHook, type EpochImagePart, type EpochMessage, type EpochMessageRole, type EpochPlugin, type EpochSessionPart, type EpochSkill, type EpochTextPart, type EpochTool, type EpochToolCall, type EpochToolResult, type EpochTurnFacts, type EpochUserContent, type ExpandedCommand, type FileOmitReason, type FinishReason, type FixableApproval, type FlatCatalog, GEN_AI, HEADLESS_INPUT_EVENT_TYPES, HEADLESS_INPUT_FORMATS, HEADLESS_OUTPUT_FORMATS, HEADLESS_PROTOCOL_VERSION, type HeadlessEnvelope, type HeadlessEvent, type HeadlessInit, type HeadlessInputEvent, type HeadlessInputEventType, type HeadlessInputFormat, type HeadlessLifecycleEvent, type HeadlessOutputFormat, type HeadlessResult, type HeadlessResultReason, type HookContext, type HookEvent, type HookHandler, type HookManager, type HookRegistration, type HookType, type HostText, type HostUser, type JsonSchema, KEY_ACTIONS, type KeyAction, type KeyChord, type KeyContext, type KeySequence, type KeybindingReport, type KeybindingSource, type KeybindingTable, LANGS, type Lang, type LocalizedDetail, type LogFn, MAX_ATTACH_BYTES, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_HEADER_CHARS, MAX_OPTIONS, MAX_QUESTIONS, MAX_SESSION_ATTACH_BYTES, MAX_SESSION_REFS, MCP_DATA_KEY_NAME, METRIC, MIN_OPTIONS, type MentionSet, type ModelRef, type ModelSelection, type ModelSelectionOrigin, NOOP_TELEMETRY, type NoticeCode, OPERATION_TYPES, OVERSIZE_RATIO, type Operation, type OperationType, PERMISSION_LEVELS, PLAN_OUTCOMES, PROVIDER_INFOS, PROVIDER_TYPES, type PermissionDecision, type PermissionLevel, type PermissionManager, type PermissionRuleLists, type PlanApprovalOutcome, type PlanProposal, type PluginContext, type ProviderInfo, type ProviderType, type QuestionAnswer, type QuestionItem, type QuestionOption, type QuestionRequest, RESERVED_CHORDS, RESERVED_COMMAND_NAMES, type RejectReason, type RejectedKey, type RuleValue, SCHEDULE_DRAFT_TOOL, SCHEDULE_INTERVAL_MINUTES, SCHEDULE_RUN_STATUSES, SCHEDULE_TEMPLATES, SEARCH_API_KEY_ENV, SEARCH_PROVIDER_TYPES, SECRET_SERVICE, SEQUENCE_CONTEXTS, SESSION_MENTION_PREFIX, SESSION_REFERENCE_ERROR_CODES, SHELL_KINDS, SIDEBAR_MENU_MESSAGE_TYPE, SIMULTANEOUS_CONTEXTS, SYSTEM_NOTE_PREFIX, type ScheduleAllowlist, type ScheduleBackendKind, type ScheduleCycle, type ScheduleDefinition, type ScheduleDraft, type ScheduleDraftAllowlist, type ScheduleDraftCreate, type ScheduleDraftPermission, type ScheduleDraftUpdate, type SchedulePendingApproval, type SchedulePendingItem, type ScheduleRun, type ScheduleRunStatus, type ScheduleRunnerSpec, type ScheduleTemplate, type ScheduleTemplateId, type ScheduleTrigger, type ScheduleTriggerKind, type ScheduleWeekday, type ScheduleWideningKind, type SearchProviderType, type SecretBackendId, type SecretStore, type SelectionContext, type SelectionRejection, type SelectionWarning, type SessionAttachKind, type SessionAttachResult, type SessionOmitReason, type SessionSurfaceMessage, type SessionSurfaceView, type SetSelectionResult, type ShellKind, type SidebarMenuItem, type SidebarMenuMessage, type SpanLike, type SubToolCall, type SubToolCallResult, type Telemetry, type TokenUsage, type ToolAnnotations, type ToolArtifact, type ToolArtifactInput, type ToolContext, type ToolDefinition, ToolExposure, type ToolProvider, type ToolResult, type Translate, type TranslateVars, type TrustLevel, type TrustManager, type TrustRecord, type TrustScope, UNLIMITED_TURNS, type VerifyResult, WIRE_ABORT_FIELDS, WIRE_ABOUT_FIELDS, WIRE_AGENT_ROLE_FIELDS, WIRE_APPROVAL_CACHE_REVOKE_REQUEST_FIELDS, WIRE_APPROVAL_CACHE_REVOKE_RESPONSE_FIELDS, WIRE_APPROVAL_LIST_FIELDS, WIRE_APPROVAL_ROW_FIELDS, WIRE_ARTIFACTS_FIELDS, WIRE_AUDIT_LOG_FIELDS, WIRE_AUDIT_ROW_FIELDS, WIRE_AUTH_COOKIE, WIRE_AUTH_COOKIE_ATTRS, WIRE_AUTH_TOKEN_PARAM, WIRE_BACKGROUND_TASK_FIELDS, WIRE_BLOCKED_GOALS_FIELDS, WIRE_BLOCKED_GOAL_FIELDS, WIRE_BLOCKED_LEVEL_FIELDS, WIRE_BUILTIN_CONNECTOR_FIELDS, WIRE_CACHED_APPROVAL_FIELDS, WIRE_CAPABILITIES_FIELDS, WIRE_CAPABILITY_PROJECT_FIELDS, WIRE_CHECKPOINT_LIST_FIELDS, WIRE_CHECKPOINT_SUMMARY_FIELDS, WIRE_COMMANDS_FIELDS, WIRE_COMMAND_EXPANSION_FIELDS, WIRE_COMPACT_FIELDS, WIRE_COMPRESSION_LINE_FIELDS, WIRE_CONFIG_FIELDS, WIRE_CONTEXT_FIELDS, WIRE_CREATE_SESSION_FIELDS, WIRE_CREATE_WORKSPACE_FIELDS, WIRE_CREATE_WORKSPACE_RESPONSE_FIELDS, WIRE_CUSTOM_COMMAND_FIELDS, WIRE_DELETE_SESSION_FIELDS, WIRE_DIFF_FILE_FIELDS, WIRE_ERROR_FIELDS, WIRE_FILE_CANDIDATES_FIELDS, WIRE_FILE_CANDIDATE_FIELDS, WIRE_FILE_CHANGE_FIELDS, WIRE_FILE_OPEN_RESPONSE_FIELDS, WIRE_FILE_REFERENCE_FIELDS, WIRE_FILE_STAT_MAX, WIRE_FILE_STAT_OK_FIELDS, WIRE_FILE_STAT_REFUSED_FIELDS, WIRE_FILE_STAT_RESPONSE_FIELDS, WIRE_FILE_TEXT_RESPONSE_FIELDS, WIRE_GOAL_ACTIONS, WIRE_GOAL_BLOCK_FIELDS, WIRE_GOAL_CLEAR_FIELDS, WIRE_GOAL_CREATE_FIELDS, WIRE_GOAL_FIELDS, WIRE_GOAL_LIMITS_FIELDS, WIRE_GOAL_PHASES, WIRE_GOAL_REFUSALS, WIRE_GOAL_RESPONSE_FIELDS, WIRE_GOAL_WRITE_FIELDS, WIRE_HEALTH_FIELDS, WIRE_IMAGE_REFERENCE_FIELDS, WIRE_KNOWN_WORKSPACE_FIELDS, WIRE_LANG_PARAM, WIRE_MANAGED_LOCK_FIELDS, WIRE_MCP_ADD_FIELDS, WIRE_MCP_ADD_RESPONSE_FIELDS, WIRE_MCP_APPLY_ENTRY_FIELDS, WIRE_MCP_APPLY_RESPONSE_FIELDS, WIRE_MCP_CONFIG_APPLY_FIELDS, WIRE_MCP_CONFIG_FIELDS, WIRE_MCP_CONFIG_ISSUE_FIELDS, WIRE_MCP_CONFIG_SAVE_FIELDS, WIRE_MCP_CONFIG_SAVE_RESPONSE_FIELDS, WIRE_MCP_CONNECTOR_FIELDS, WIRE_MCP_RECONNECT_FIELDS, WIRE_MESSAGE_LIST_FIELDS, WIRE_MODEL_FIELDS, WIRE_MODEL_SELECTION_FIELDS, WIRE_MODEL_SET_FIELDS, WIRE_MODEL_SUGGESTIONS_FIELDS, WIRE_PATCH_SESSION_FIELDS, WIRE_PATCH_SESSION_RESPONSE_FIELDS, WIRE_PERMISSION_RULE_FIELDS, WIRE_PERMISSION_SET_REQUEST_FIELDS, WIRE_PERMISSION_SET_RESPONSE_FIELDS, WIRE_PERMISSION_SHADOW_FIELDS, WIRE_PERMISSION_STATE_FIELDS, WIRE_PERMISSION_STATUS_FIELDS, WIRE_PLAN_ACTIONS, WIRE_PLAN_FIELDS, WIRE_PLAN_MODE_REQUEST_FIELDS, WIRE_PLAN_MODE_RESPONSE_FIELDS, WIRE_PLAN_MODE_STATE_FIELDS, WIRE_PLUGINS_FIELDS, WIRE_PLUGIN_ACTION_FIELDS, WIRE_PLUGIN_INSTALL_FIELDS, WIRE_PLUGIN_LOCAL_FIELDS, WIRE_PLUGIN_LOCAL_INSTALL_FIELDS, WIRE_PLUGIN_MARKETPLACE_FIELDS, WIRE_PLUGIN_MARKETPLACE_RESPONSE_FIELDS, WIRE_PLUGIN_NAME_FIELDS, WIRE_PLUGIN_PREVIEW_FIELDS, WIRE_PLUGIN_PREVIEW_RESPONSE_FIELDS, WIRE_PLUGIN_REFRESH_RESPONSE_FIELDS, WIRE_PLUGIN_UPDATE_FIELDS, WIRE_PLUGIN_UPLOAD_CONFIRM_FIELDS, WIRE_PLUGIN_UPLOAD_FIELDS, WIRE_PLUGIN_UPLOAD_FORM_FIELDS, WIRE_PLUGIN_UPLOAD_PREVIEW_RESPONSE_FIELDS, WIRE_PLUGIN_UPLOAD_RESPONSE_FIELDS, WIRE_POLICY_DIR_FIELDS, WIRE_POLICY_STATUS_FIELDS, WIRE_PROVIDERS_FIELDS, WIRE_PROVIDER_KEY_FIELDS, WIRE_PROVIDER_MODELS_FIELDS, WIRE_PROVIDER_OPTION_FIELDS, WIRE_QUESTION_LIST_FIELDS, WIRE_QUESTION_ROW_FIELDS, WIRE_RESPOND_APPROVAL_FIELDS, WIRE_RESPOND_APPROVAL_RESPONSE_FIELDS, WIRE_RESPOND_QUESTION_FIELDS, WIRE_RESPOND_QUESTION_RESPONSE_FIELDS, WIRE_REWIND_FILE_PLAN_FIELDS, WIRE_REWIND_OUTCOME_FIELDS, WIRE_REWIND_PREVIEW_FIELDS, WIRE_REWIND_REQUEST_FIELDS, WIRE_REWIND_RESPONSE_FIELDS, WIRE_REWIND_SCOPES, WIRE_ROLE_ADD_FIELDS, WIRE_ROLE_ADD_RESPONSE_FIELDS, WIRE_SANDBOX_STATUS_FIELDS, WIRE_SCHEDULE_CAPABILITY_FIELDS, WIRE_SCHEDULE_CREATE_FIELDS, WIRE_SCHEDULE_DEFAULTS_FIELDS, WIRE_SCHEDULE_DELETE_FIELDS, WIRE_SCHEDULE_FIELDS, WIRE_SCHEDULE_FIX_FIELDS, WIRE_SCHEDULE_FIX_REQUEST_FIELDS, WIRE_SCHEDULE_ISSUE_CODES, WIRE_SCHEDULE_LIST_FIELDS, WIRE_SCHEDULE_PENDING_FIELDS, WIRE_SCHEDULE_RECORDING_FIELDS, WIRE_SCHEDULE_ROW_FIELDS, WIRE_SCHEDULE_RUNS_FIELDS, WIRE_SCHEDULE_RUN_FIELDS, WIRE_SCHEDULE_SAVE_FIELDS, WIRE_SECURITY_FIELDS, WIRE_SECURITY_WORKSPACE_FIELDS, WIRE_SEND_MESSAGE_FIELDS, WIRE_SEND_MESSAGE_RESPONSE_FIELDS, WIRE_SESSION_CANDIDATES_FIELDS, WIRE_SESSION_CANDIDATE_FIELDS, WIRE_SESSION_FINISH_FIELDS, WIRE_SESSION_LIST_FIELDS, WIRE_SESSION_REFERENCE_FIELDS, WIRE_SESSION_RESPONSE_FIELDS, WIRE_SESSION_SUMMARY_FIELDS, WIRE_SESSION_WORKSPACE_FIELDS, WIRE_SESSION_WORKSPACE_RESPONSE_FIELDS, WIRE_SETTINGS_FIELDS, WIRE_SETTINGS_WRITE_FIELDS, WIRE_SETTINGS_WRITE_REQUEST_FIELDS, WIRE_SETTING_ROW_FIELDS, WIRE_SETTING_STEP_FIELDS, WIRE_SETTING_WRITE_FIELDS, WIRE_SETTING_WRITE_LAYERS, WIRE_SKILL_BODY_FIELDS, WIRE_SKILL_FIELDS, WIRE_SKILL_IMPORT_FIELDS, WIRE_SKILL_IMPORT_PREVIEW_FIELDS, WIRE_SKILL_REMOVE_FIELDS, WIRE_TASKS_FIELDS, WIRE_TOOLS_FIELDS, WIRE_TOOL_GATE_FIELDS, WIRE_TOOL_ROW_FIELDS, WIRE_WORKSPACE_DIFF_FIELDS, WIRE_WORKSPACE_DIRS_FIELDS, WIRE_WORKSPACE_DIR_ENTRY_FIELDS, WIRE_WORKSPACE_REF_FIELDS, type WireAbortResponse, type WireAbout, type WireAgentEnvelope, type WireAgentEvent, type WireAgentRoleSummary, type WireApprovalCacheRevokeRequest, type WireApprovalCacheRevokeResponse, type WireApprovalListResponse, type WireApprovalRequest, type WireArtifactsResponse, type WireAuditCode, type WireAuditLog, type WireAuditOutcome, type WireAuditRow, type WireAuthDenyReason, type WireAuthDenyStatus, type WireAuthGuard, type WireAuthRequestView, type WireAuthVerdict, type WireBackgroundTask, type WireBindWorkspaceRequest, type WireBlockedGoal, type WireBlockedGoalsResponse, type WireBlockedLevel, type WireBuiltinConnector, type WireCachedApproval, type WireCachedDecision, type WireCapabilitiesResponse, type WireCapabilityProject, type WireCheckpointListResponse, type WireCheckpointSummary, type WireCommandExpansion, type WireCommandsResponse, type WireCompactRequest, type WireCompactResponse, type WireCompressionLine, type WireConfigResponse, type WireContextResponse, type WireCreateSessionRequest, type WireCreateSessionResponse, type WireCreateWorkspaceRequest, type WireCreateWorkspaceResponse, type WireCustomCommand, type WireDeleteSessionResponse, type WireDiffFile, type WireDiffNote, type WireDiffOmitReason, type WireDiffSource, type WireDiffStatus, type WireEnvelope, type WireErrorResponse, type WireEvent, type WireFields, type WireFileCandidate, type WireFileCandidatesResponse, type WireFileChange, type WireFileKind, type WireFileOpenRefusal, type WireFileOpenResponse, type WireFileReference, type WireFileRefusal, type WireFileStat, type WireFileStatOk, type WireFileStatRefused, type WireFileStatResponse, type WireFileTextResponse, type WireFixture, type WireFixtureCase, type WireGoal, type WireGoalBlock, type WireGoalClearResponse, type WireGoalCreateRequest, type WireGoalLimits, type WireGoalPhase, type WireGoalRefusal, type WireGoalResponse, type WireGoalUpdateRequest, type WireGoalWriteResponse, type WireHealthResponse, type WireHubEnvelope, type WireHubEvent, type WireImageReference, type WireKnownWorkspace, type WireManagedLock, type WireMcpAddRequest, type WireMcpAddResponse, type WireMcpApplyAction, type WireMcpApplyEntry, type WireMcpApplyResponse, type WireMcpConfigApplyRequest, type WireMcpConfigIssue, type WireMcpConfigResponse, type WireMcpConfigSaveRequest, type WireMcpConfigSaveResponse, type WireMcpConnector, type WireMcpReconnectResponse, type WireMessageListResponse, type WireModelCaveat, type WireModelProbeStatus, type WireModelRejection, type WireModelResponse, type WireModelSelection, type WireModelSetRequest, type WireModelSetResponse, type WireModelSource, type WireModelSuggestions, type WirePatchSessionRequest, type WirePatchSessionResponse, type WirePermissionRememberFailure, type WirePermissionRuleRow, type WirePermissionSetRequest, type WirePermissionSetResponse, type WirePermissionShadow, type WirePermissionState, type WirePermissionStatus, type WirePickDirectoryResponse, type WirePlanAction, type WirePlanModeRequest, type WirePlanModeResponse, type WirePlanModeState, type WirePlanResponse, type WirePluginActionResponse, type WirePluginCounts, type WirePluginEntry, type WirePluginHit, type WirePluginHookTally, type WirePluginInstallRequest, type WirePluginLocalInstallRequest, type WirePluginLocalRequest, type WirePluginMarketplace, type WirePluginMarketplaceRequest, type WirePluginMarketplaceResponse, type WirePluginNameRequest, type WirePluginPreview, type WirePluginPreviewRequest, type WirePluginPreviewResponse, type WirePluginRefreshResponse, type WirePluginRefuseReason, type WirePluginSourceType, type WirePluginStatus, type WirePluginUpdateRequest, type WirePluginUploadConfirmRequest, type WirePluginUploadField, type WirePluginUploadFieldName, type WirePluginUploadFields, type WirePluginUploadFile, type WirePluginUploadForm, type WirePluginUploadPlan, type WirePluginUploadPreviewResponse, type WirePluginUploadRequest, type WirePluginUploadResponse, type WirePluginVisibility, type WirePluginsResponse, type WirePolicyDir, type WirePolicyStatus, type WireProviderKeyRequest, type WireProviderKeyResponse, type WireProviderModelsRequest, type WireProviderModelsResponse, type WireProviderOption, type WireProviderSummary, type WireProvidersResponse, type WireQuestionListResponse, type WireQuestionRequest, type WireReplayMessage, type WireResetReason, type WireRespondApprovalRequest, type WireRespondApprovalResponse, type WireRespondQuestionRequest, type WireRespondQuestionResponse, type WireRewindAction, type WireRewindDrift, type WireRewindFilePlan, type WireRewindOutcome, type WireRewindPreview, type WireRewindRequest, type WireRewindResponse, type WireRewindScope, type WireRoleAddRequest, type WireRoleAddResponse, type WireSandboxReason, type WireSandboxStatus, type WireScheduleCapability, type WireScheduleCreateRequest, type WireScheduleDefaults, type WireScheduleDeleteResponse, type WireScheduleFixRequest, type WireScheduleFixResponse, type WireScheduleIssue, type WireScheduleIssueCode, type WireScheduleListResponse, type WireSchedulePendingResponse, type WireScheduleRecordingResponse, type WireScheduleRegisterRefusal, type WireScheduleRegisterWarning, type WireScheduleRegistration, type WireScheduleResponse, type WireScheduleRow, type WireScheduleRunResponse, type WireScheduleRunsResponse, type WireScheduleSaveResponse, type WireScheduleUpdateRequest, type WireSecurityResponse, type WireSecurityWorkspace, type WireSendMessageRequest, type WireSendMessageResponse, type WireSessionCandidate, type WireSessionCandidatesResponse, type WireSessionFinish, type WireSessionListResponse, type WireSessionReference, type WireSessionResponse, type WireSessionSummary, type WireSessionWorkspace, type WireSessionWorkspaceResponse, type WireSettingApply, type WireSettingFutile, type WireSettingLayer, type WireSettingRow, type WireSettingStep, type WireSettingValue, type WireSettingValueKind, type WireSettingWrite, type WireSettingWriteLayer, type WireSettingsResponse, type WireSettingsWriteRequest, type WireSettingsWriteResponse, type WireSkillBodyResponse, type WireSkillImportConflict, type WireSkillImportEntry, type WireSkillImportFailure, type WireSkillImportForm, type WireSkillImportIssue, type WireSkillImportPreviewResponse, type WireSkillImportResponse, type WireSkillRemoveFailure, type WireSkillRemoveResponse, type WireSkillSummary, type WireSummaryWorkspace, type WireTaggedEvent, type WireTasksResponse, type WireToolGate, type WireToolGateAxis, type WireToolRow, type WireToolSummary, type WireToolVerdict, type WireToolsResponse, type WireTurnState, type WireWorkspaceBinding, type WireWorkspaceDiffResponse, type WireWorkspaceDirEntry, type WireWorkspaceDirsResponse, type WireWorkspaceRef, apiKeyEnvVar, assertNeverPart, assistantTurnText, attachSessionSurface, chordId, collectPendingApprovals, compressionThresholdTokens, conformsToWire, contentToText, diagnosticToLine, extractAllMentions, extractMentions, extractSessionMentions, filePartSummary, flattenCatalog, getProviderInfo, hasFailure, isApprovalOutcome, isContextNearlyFull, isHeadlessInputFormat, isHeadlessLifecycleEvent, isHeadlessOutputFormat, isKeyAction, isLang, isMentionableFilePath, isOperationType, isPermissionLevel, isPlanOutcome, isPromptOversize, isProviderType, isQuestionAnswerMap, isSearchProviderType, isValidAgentRoleName, isValidCommandName, isWireGoalPhase, isWireHubEvent, isWirePlanAction, isWireRewindScope, isWireSettingWriteLayer, makeTranslate, normalizeApproval, packSessionSurface, parseChord, parseModelRef, parseSequence, perAction, placeholdersOf, promptTokens, resolveHostText, sequenceId, sessionPartSummary, stripSystemNote, systemNote, tableOf, totalUsageTokens, translatorFor, turnDigest, unfixedRules, utf8ByteLength, wireFields };
|
|
14620
|
+
export { ACTION_CONTEXTS, AGENT_ROLE_NAME_PATTERN, API_KEY_ENV_VARS, APPROVAL_OUTCOMES, type ActiveAgentRole, type AgentEvent, type AgentEventOf, type AgentEventType, type AgentRole, type AgentRoleScope, type AgentRoleSource, type ApprovalAnswer, type ApprovalOutcome, type ApprovalReply, type ApprovalRequest, type ArtifactKind, type AttributeValue, type Attributes, type BackgroundTaskInfo, type BackgroundTaskKind, type BackgroundTaskStatus, type BlankCard, type BlankGreeting, type BoundKey, type BudgetBreach, COMMAND_NAME_PATTERN, COMPLIANCE_ACTIONS, COMPLIANCE_CATEGORIES, CURRENCIES, type Catalogs, type ComplianceAction, type ComplianceCategory, type ContextBreakdown, type ContextSegment, type Currency, type CurrencyDisplay, type CustomCommandDef, type CustomCommandSource, DEFAULT_AGENT_ROLE, DEFAULT_LANG, type DecidedTrustLevel, type Diagnostic, DiagnosticSink, type DiagnosticStatus, type EpochConfig, type EpochContentPart, type EpochFilePart, type EpochHook, type EpochImagePart, type EpochMessage, type EpochMessageRole, type EpochPlugin, type EpochSessionPart, type EpochSkill, type EpochTextPart, type EpochTool, type EpochToolCall, type EpochToolResult, type EpochTurnFacts, type EpochUserContent, type ExpandedCommand, type FileOmitReason, type FinishReason, type FixableApproval, type FlatCatalog, type FormatMoneyOptions, GEN_AI, HEADLESS_INPUT_EVENT_TYPES, HEADLESS_INPUT_FORMATS, HEADLESS_OUTPUT_FORMATS, HEADLESS_PROTOCOL_VERSION, type HeadlessEnvelope, type HeadlessEvent, type HeadlessInit, type HeadlessInputEvent, type HeadlessInputEventType, type HeadlessInputFormat, type HeadlessLifecycleEvent, type HeadlessOutputFormat, type HeadlessResult, type HeadlessResultReason, type HookContext, type HookEvent, type HookHandler, type HookManager, type HookRegistration, type HookType, type HostText, type HostUser, type JsonSchema, KEY_ACTIONS, type KeyAction, type KeyChord, type KeyContext, type KeySequence, type KeybindingReport, type KeybindingSource, type KeybindingTable, LANGS, type Lang, type LocalizedDetail, type LogFn, MAX_ATTACH_BYTES, MAX_ATTACH_FILES, MAX_ATTACH_TOTAL_BYTES, MAX_HEADER_CHARS, MAX_OPTIONS, MAX_QUESTIONS, MAX_SESSION_ATTACH_BYTES, MAX_SESSION_REFS, MCP_DATA_KEY_NAME, METRIC, MIN_OPTIONS, type MentionSet, type ModelRef, type ModelSelection, type ModelSelectionOrigin, type MoneyDigits, NOOP_TELEMETRY, type NoticeCode, OPERATION_TYPES, OVERSIZE_RATIO, type Operation, type OperationType, PERMISSION_LEVELS, PLAN_OUTCOMES, PROVIDER_INFOS, PROVIDER_TYPES, type PermissionDecision, type PermissionLevel, type PermissionManager, type PermissionRuleLists, type PlanApprovalOutcome, type PlanProposal, type PluginContext, type ProviderInfo, type ProviderType, type QuestionAnswer, type QuestionItem, type QuestionOption, type QuestionRequest, RESERVED_CHORDS, RESERVED_COMMAND_NAMES, type RejectReason, type RejectedKey, type RuleValue, SCHEDULE_DRAFT_TOOL, SCHEDULE_INTERVAL_MINUTES, SCHEDULE_RUN_STATUSES, SCHEDULE_TEMPLATES, SEARCH_API_KEY_ENV, SEARCH_PROVIDER_TYPES, SECRET_SERVICE, SEQUENCE_CONTEXTS, SESSION_MENTION_PREFIX, SESSION_REFERENCE_ERROR_CODES, SHELL_KINDS, SIDEBAR_MENU_MESSAGE_TYPE, SIMULTANEOUS_CONTEXTS, SYSTEM_NOTE_PREFIX, type ScheduleAllowlist, type ScheduleBackendKind, type ScheduleCycle, type ScheduleDefinition, type ScheduleDraft, type ScheduleDraftAllowlist, type ScheduleDraftCreate, type ScheduleDraftPermission, type ScheduleDraftUpdate, type SchedulePendingApproval, type SchedulePendingItem, type ScheduleRun, type ScheduleRunStatus, type ScheduleRunnerSpec, type ScheduleTemplate, type ScheduleTemplateId, type ScheduleTrigger, type ScheduleTriggerKind, type ScheduleWeekday, type ScheduleWideningKind, type SearchProviderType, type SecretBackendId, type SecretStore, type SelectionContext, type SelectionRejection, type SelectionWarning, type SessionAttachKind, type SessionAttachResult, type SessionOmitReason, type SessionSurfaceMessage, type SessionSurfaceView, type SetSelectionResult, type ShellKind, type SidebarMenuItem, type SidebarMenuMessage, type SpanLike, type SubToolCall, type SubToolCallResult, type Telemetry, type TokenUsage, type ToolAnnotations, type ToolArtifact, type ToolArtifactInput, type ToolContext, type ToolDefinition, ToolExposure, type ToolProvider, type ToolResult, type Translate, type TranslateVars, type TrustExecGrant, type TrustGrant, type TrustLevel, type TrustManager, type TrustRecord, type TrustScope, type TrustTier, UNLIMITED_TURNS, type VerifyResult, WIRE_ABORT_FIELDS, WIRE_ABOUT_FIELDS, WIRE_AGENT_ROLE_FIELDS, WIRE_APPROVAL_CACHE_REVOKE_REQUEST_FIELDS, WIRE_APPROVAL_CACHE_REVOKE_RESPONSE_FIELDS, WIRE_APPROVAL_LIST_FIELDS, WIRE_APPROVAL_ROW_FIELDS, WIRE_ARTIFACTS_FIELDS, WIRE_ATTACHMENT_UPLOAD_FIELDS, WIRE_AUDIT_LOG_FIELDS, WIRE_AUDIT_ROW_FIELDS, WIRE_AUTH_COOKIE, WIRE_AUTH_COOKIE_ATTRS, WIRE_AUTH_TOKEN_PARAM, WIRE_BACKGROUND_TASK_FIELDS, WIRE_BLOCKED_GOALS_FIELDS, WIRE_BLOCKED_GOAL_FIELDS, WIRE_BLOCKED_LEVEL_FIELDS, WIRE_BUILTIN_CONNECTOR_FIELDS, WIRE_CACHED_APPROVAL_FIELDS, WIRE_CAPABILITIES_FIELDS, WIRE_CAPABILITY_PROJECT_FIELDS, WIRE_CHECKPOINT_LIST_FIELDS, WIRE_CHECKPOINT_SUMMARY_FIELDS, WIRE_COMMANDS_FIELDS, WIRE_COMMAND_EXPANSION_FIELDS, WIRE_COMPACT_FIELDS, WIRE_COMPRESSION_LINE_FIELDS, WIRE_CONFIG_FIELDS, WIRE_CONTEXT_FIELDS, WIRE_CREATE_SESSION_FIELDS, WIRE_CREATE_WORKSPACE_FIELDS, WIRE_CREATE_WORKSPACE_RESPONSE_FIELDS, WIRE_CUSTOM_COMMAND_FIELDS, WIRE_DELETE_SESSION_FIELDS, WIRE_DIFF_FILE_FIELDS, WIRE_ERROR_FIELDS, WIRE_FILE_CANDIDATES_FIELDS, WIRE_FILE_CANDIDATE_FIELDS, WIRE_FILE_CHANGE_FIELDS, WIRE_FILE_OPEN_RESPONSE_FIELDS, WIRE_FILE_REFERENCE_FIELDS, WIRE_FILE_STAT_MAX, WIRE_FILE_STAT_OK_FIELDS, WIRE_FILE_STAT_REFUSED_FIELDS, WIRE_FILE_STAT_RESPONSE_FIELDS, WIRE_FILE_TEXT_RESPONSE_FIELDS, WIRE_FORGET_WORKSPACE_FIELDS, WIRE_FORGET_WORKSPACE_RESPONSE_FIELDS, WIRE_GOAL_ACTIONS, WIRE_GOAL_BLOCK_FIELDS, WIRE_GOAL_CLEAR_FIELDS, WIRE_GOAL_CREATE_FIELDS, WIRE_GOAL_FIELDS, WIRE_GOAL_LIMITS_FIELDS, WIRE_GOAL_PHASES, WIRE_GOAL_REFUSALS, WIRE_GOAL_RESPONSE_FIELDS, WIRE_GOAL_WRITE_FIELDS, WIRE_HEALTH_FIELDS, WIRE_IMAGE_REFERENCE_FIELDS, WIRE_KNOWN_WORKSPACE_FIELDS, WIRE_LANG_PARAM, WIRE_MANAGED_LOCK_FIELDS, WIRE_MCP_ADD_FIELDS, WIRE_MCP_ADD_RESPONSE_FIELDS, WIRE_MCP_APPLY_ENTRY_FIELDS, WIRE_MCP_APPLY_RESPONSE_FIELDS, WIRE_MCP_CONFIG_APPLY_FIELDS, WIRE_MCP_CONFIG_FIELDS, WIRE_MCP_CONFIG_ISSUE_FIELDS, WIRE_MCP_CONFIG_SAVE_FIELDS, WIRE_MCP_CONFIG_SAVE_RESPONSE_FIELDS, WIRE_MCP_CONNECTOR_FIELDS, WIRE_MCP_RECONNECT_FIELDS, WIRE_MESSAGE_LIST_FIELDS, WIRE_MODEL_FIELDS, WIRE_MODEL_SELECTION_FIELDS, WIRE_MODEL_SET_FIELDS, WIRE_MODEL_SUGGESTIONS_FIELDS, WIRE_PATCH_SESSION_FIELDS, WIRE_PATCH_SESSION_RESPONSE_FIELDS, WIRE_PERMISSION_RULE_FIELDS, WIRE_PERMISSION_SET_REQUEST_FIELDS, WIRE_PERMISSION_SET_RESPONSE_FIELDS, WIRE_PERMISSION_SHADOW_FIELDS, WIRE_PERMISSION_STATE_FIELDS, WIRE_PERMISSION_STATUS_FIELDS, WIRE_PLAN_ACTIONS, WIRE_PLAN_FIELDS, WIRE_PLAN_MODE_REQUEST_FIELDS, WIRE_PLAN_MODE_RESPONSE_FIELDS, WIRE_PLAN_MODE_STATE_FIELDS, WIRE_PLUGINS_FIELDS, WIRE_PLUGIN_ACTION_FIELDS, WIRE_PLUGIN_ARCHIVE_SUFFIXES, WIRE_PLUGIN_INSTALL_FIELDS, WIRE_PLUGIN_LOCAL_FIELDS, WIRE_PLUGIN_LOCAL_INSTALL_FIELDS, WIRE_PLUGIN_MARKETPLACE_FIELDS, WIRE_PLUGIN_MARKETPLACE_RESPONSE_FIELDS, WIRE_PLUGIN_NAME_FIELDS, WIRE_PLUGIN_PREVIEW_FIELDS, WIRE_PLUGIN_PREVIEW_RESPONSE_FIELDS, WIRE_PLUGIN_REFRESH_RESPONSE_FIELDS, WIRE_PLUGIN_STAGE_FIELDS, WIRE_PLUGIN_STAGE_RESPONSE_FIELDS, WIRE_PLUGIN_UPDATE_FIELDS, WIRE_PLUGIN_UPLOAD_CONFIRM_FIELDS, WIRE_PLUGIN_UPLOAD_FIELDS, WIRE_PLUGIN_UPLOAD_FORM_FIELDS, WIRE_PLUGIN_UPLOAD_PREVIEW_RESPONSE_FIELDS, WIRE_PLUGIN_UPLOAD_RESPONSE_FIELDS, WIRE_POLICY_DIR_FIELDS, WIRE_POLICY_STATUS_FIELDS, WIRE_PROJECT_INVENTORY_FIELDS, WIRE_PROVIDERS_FIELDS, WIRE_PROVIDER_KEY_FIELDS, WIRE_PROVIDER_MODELS_FIELDS, WIRE_PROVIDER_OPTION_FIELDS, WIRE_QUESTION_LIST_FIELDS, WIRE_QUESTION_ROW_FIELDS, WIRE_RESPOND_APPROVAL_FIELDS, WIRE_RESPOND_APPROVAL_RESPONSE_FIELDS, WIRE_RESPOND_QUESTION_FIELDS, WIRE_RESPOND_QUESTION_RESPONSE_FIELDS, WIRE_REWIND_FILE_PLAN_FIELDS, WIRE_REWIND_OUTCOME_FIELDS, WIRE_REWIND_PREVIEW_FIELDS, WIRE_REWIND_REQUEST_FIELDS, WIRE_REWIND_RESPONSE_FIELDS, WIRE_REWIND_SCOPES, WIRE_ROLE_ADD_FIELDS, WIRE_ROLE_ADD_RESPONSE_FIELDS, WIRE_SANDBOX_STATUS_FIELDS, WIRE_SCHEDULE_CAPABILITY_FIELDS, WIRE_SCHEDULE_CREATE_FIELDS, WIRE_SCHEDULE_DEFAULTS_FIELDS, WIRE_SCHEDULE_DELETE_FIELDS, WIRE_SCHEDULE_FIELDS, WIRE_SCHEDULE_FIX_FIELDS, WIRE_SCHEDULE_FIX_REQUEST_FIELDS, WIRE_SCHEDULE_ISSUE_CODES, WIRE_SCHEDULE_LIST_FIELDS, WIRE_SCHEDULE_PENDING_FIELDS, WIRE_SCHEDULE_RECORDING_FIELDS, WIRE_SCHEDULE_ROW_FIELDS, WIRE_SCHEDULE_RUNS_FIELDS, WIRE_SCHEDULE_RUN_FIELDS, WIRE_SCHEDULE_SAVE_FIELDS, WIRE_SECURITY_FIELDS, WIRE_SECURITY_WORKSPACE_FIELDS, WIRE_SEND_MESSAGE_FIELDS, WIRE_SEND_MESSAGE_RESPONSE_FIELDS, WIRE_SESSION_CANDIDATES_FIELDS, WIRE_SESSION_CANDIDATE_FIELDS, WIRE_SESSION_FINISH_FIELDS, WIRE_SESSION_LIST_FIELDS, WIRE_SESSION_REFERENCE_FIELDS, WIRE_SESSION_RESPONSE_FIELDS, WIRE_SESSION_SUMMARY_FIELDS, WIRE_SESSION_WORKSPACE_FIELDS, WIRE_SESSION_WORKSPACE_RESPONSE_FIELDS, WIRE_SETTINGS_FIELDS, WIRE_SETTINGS_WRITE_FIELDS, WIRE_SETTINGS_WRITE_REQUEST_FIELDS, WIRE_SETTING_ROW_FIELDS, WIRE_SETTING_STEP_FIELDS, WIRE_SETTING_WRITE_FIELDS, WIRE_SETTING_WRITE_LAYERS, WIRE_SKILL_BODY_FIELDS, WIRE_SKILL_DROP_SUFFIXES, WIRE_SKILL_FIELDS, WIRE_SKILL_IMPORT_FIELDS, WIRE_SKILL_IMPORT_PREVIEW_FIELDS, WIRE_SKILL_REMOVE_FIELDS, WIRE_SKILL_STAGE_FIELDS, WIRE_TASKS_FIELDS, WIRE_TOOLS_FIELDS, WIRE_TOOL_GATE_FIELDS, WIRE_TOOL_ROW_FIELDS, WIRE_TRUST_REQUEST_FIELDS, WIRE_TRUST_REQUEST_RESPONSE_FIELDS, WIRE_WORKSPACE_DIFF_FIELDS, WIRE_WORKSPACE_DIRS_FIELDS, WIRE_WORKSPACE_DIR_ENTRY_FIELDS, WIRE_WORKSPACE_REF_FIELDS, type WireAbortResponse, type WireAbout, type WireAgentEnvelope, type WireAgentEvent, type WireAgentRoleSummary, type WireApprovalCacheRevokeRequest, type WireApprovalCacheRevokeResponse, type WireApprovalListResponse, type WireApprovalRequest, type WireArtifactsResponse, type WireAttachmentUploadResponse, type WireAuditCode, type WireAuditLog, type WireAuditOutcome, type WireAuditRow, type WireAuthDenyReason, type WireAuthDenyStatus, type WireAuthGuard, type WireAuthRequestView, type WireAuthVerdict, type WireBackgroundTask, type WireBindWorkspaceRequest, type WireBlockedGoal, type WireBlockedGoalsResponse, type WireBlockedLevel, type WireBuiltinConnector, type WireCachedApproval, type WireCachedDecision, type WireCapabilitiesResponse, type WireCapabilityProject, type WireCheckpointListResponse, type WireCheckpointSummary, type WireCommandExpansion, type WireCommandsResponse, type WireCompactRequest, type WireCompactResponse, type WireCompressionLine, type WireConfigResponse, type WireContextResponse, type WireCreateSessionRequest, type WireCreateSessionResponse, type WireCreateWorkspaceRequest, type WireCreateWorkspaceResponse, type WireCustomCommand, type WireDeleteSessionResponse, type WireDiffFile, type WireDiffNote, type WireDiffOmitReason, type WireDiffSource, type WireDiffStatus, type WireEnvelope, type WireErrorResponse, type WireEvent, type WireFields, type WireFileCandidate, type WireFileCandidatesResponse, type WireFileChange, type WireFileKind, type WireFileOpenRefusal, type WireFileOpenResponse, type WireFileReference, type WireFileRefusal, type WireFileStat, type WireFileStatOk, type WireFileStatRefused, type WireFileStatResponse, type WireFileTextResponse, type WireFixture, type WireFixtureCase, type WireForgetWorkspaceRequest, type WireForgetWorkspaceResponse, type WireGoal, type WireGoalBlock, type WireGoalClearResponse, type WireGoalCreateRequest, type WireGoalLimits, type WireGoalPhase, type WireGoalRefusal, type WireGoalResponse, type WireGoalUpdateRequest, type WireGoalWriteResponse, type WireHealthResponse, type WireHubEnvelope, type WireHubEvent, type WireImageReference, type WireKnownWorkspace, type WireKnownWorkspaceRef, type WireManagedLock, type WireMcpAddRequest, type WireMcpAddResponse, type WireMcpApplyAction, type WireMcpApplyEntry, type WireMcpApplyResponse, type WireMcpConfigApplyRequest, type WireMcpConfigIssue, type WireMcpConfigResponse, type WireMcpConfigSaveRequest, type WireMcpConfigSaveResponse, type WireMcpConnector, type WireMcpReconnectResponse, type WireMessageListResponse, type WireModelCaveat, type WireModelProbeStatus, type WireModelRejection, type WireModelResponse, type WireModelSelection, type WireModelSetRequest, type WireModelSetResponse, type WireModelSource, type WireModelSuggestions, type WirePatchSessionRequest, type WirePatchSessionResponse, type WirePermissionRememberFailure, type WirePermissionRuleRow, type WirePermissionSetRequest, type WirePermissionSetResponse, type WirePermissionShadow, type WirePermissionState, type WirePermissionStatus, type WirePickDirectoryResponse, type WirePlanAction, type WirePlanModeRequest, type WirePlanModeResponse, type WirePlanModeState, type WirePlanResponse, type WirePluginActionResponse, type WirePluginCounts, type WirePluginEntry, type WirePluginHit, type WirePluginHookTally, type WirePluginInstallRequest, type WirePluginLocalInstallRequest, type WirePluginLocalRequest, type WirePluginMarketplace, type WirePluginMarketplaceRequest, type WirePluginMarketplaceResponse, type WirePluginNameRequest, type WirePluginPreview, type WirePluginPreviewRequest, type WirePluginPreviewResponse, type WirePluginRefreshResponse, type WirePluginRefuseReason, type WirePluginSourceType, type WirePluginStageRequest, type WirePluginStageResponse, type WirePluginStatus, type WirePluginUpdateRequest, type WirePluginUploadConfirmRequest, type WirePluginUploadField, type WirePluginUploadFieldName, type WirePluginUploadFields, type WirePluginUploadFile, type WirePluginUploadForm, type WirePluginUploadPlan, type WirePluginUploadPreviewResponse, type WirePluginUploadRequest, type WirePluginUploadResponse, type WirePluginVisibility, type WirePluginsResponse, type WirePolicyDir, type WirePolicyStatus, type WireProjectInventory, type WireProviderKeyRequest, type WireProviderKeyResponse, type WireProviderModelsRequest, type WireProviderModelsResponse, type WireProviderOption, type WireProviderSummary, type WireProvidersResponse, type WireQuestionListResponse, type WireQuestionRequest, type WireReplayMessage, type WireResetReason, type WireRespondApprovalRequest, type WireRespondApprovalResponse, type WireRespondQuestionRequest, type WireRespondQuestionResponse, type WireRewindAction, type WireRewindDrift, type WireRewindFilePlan, type WireRewindOutcome, type WireRewindPreview, type WireRewindRequest, type WireRewindResponse, type WireRewindScope, type WireRoleAddRequest, type WireRoleAddResponse, type WireSandboxReason, type WireSandboxStatus, type WireScheduleCapability, type WireScheduleCreateRequest, type WireScheduleDefaults, type WireScheduleDeleteResponse, type WireScheduleFixRequest, type WireScheduleFixResponse, type WireScheduleIssue, type WireScheduleIssueCode, type WireScheduleListResponse, type WireSchedulePendingResponse, type WireScheduleRecordingResponse, type WireScheduleRegisterRefusal, type WireScheduleRegisterWarning, type WireScheduleRegistration, type WireScheduleResponse, type WireScheduleRow, type WireScheduleRunResponse, type WireScheduleRunsResponse, type WireScheduleSaveResponse, type WireScheduleUpdateRequest, type WireSecurityResponse, type WireSecurityWorkspace, type WireSendMessageRequest, type WireSendMessageResponse, type WireSessionCandidate, type WireSessionCandidatesResponse, type WireSessionFinish, type WireSessionListResponse, type WireSessionReference, type WireSessionResponse, type WireSessionSummary, type WireSessionWorkspace, type WireSessionWorkspaceResponse, type WireSettingApply, type WireSettingFutile, type WireSettingLayer, type WireSettingRow, type WireSettingStep, type WireSettingValue, type WireSettingValueKind, type WireSettingWrite, type WireSettingWriteLayer, type WireSettingsResponse, type WireSettingsWriteRequest, type WireSettingsWriteResponse, type WireSkillBodyResponse, type WireSkillImportConflict, type WireSkillImportEntry, type WireSkillImportFailure, type WireSkillImportForm, type WireSkillImportIssue, type WireSkillImportPreviewResponse, type WireSkillImportResponse, type WireSkillRemoveFailure, type WireSkillRemoveResponse, type WireSkillStageFailure, type WireSkillStageResponse, type WireSkillSummary, type WireSummaryWorkspace, type WireTaggedEvent, type WireTasksResponse, type WireToolGate, type WireToolGateAxis, type WireToolRow, type WireToolSummary, type WireToolVerdict, type WireToolsResponse, type WireTrustRequestRequest, type WireTrustRequestResponse, type WireTurnState, type WireWorkspaceBinding, type WireWorkspaceDiffResponse, type WireWorkspaceDirEntry, type WireWorkspaceDirsResponse, type WireWorkspaceRef, apiKeyEnvVar, assertNeverPart, assistantTurnText, attachSessionSurface, chordId, collectPendingApprovals, compressionThresholdTokens, conformsToWire, contentToText, diagnosticToLine, extractAllMentions, extractMentions, extractSessionMentions, filePartSummary, flattenCatalog, formatMoney, getProviderInfo, hasFailure, imagePartOmittedSummary, isApprovalOutcome, isContextNearlyFull, isCurrency, isHeadlessInputFormat, isHeadlessLifecycleEvent, isHeadlessOutputFormat, isKeyAction, isLang, isMentionableFilePath, isOperationType, isPermissionLevel, isPlanOutcome, isPromptOversize, isProviderType, isQuestionAnswerMap, isSearchProviderType, isValidAgentRoleName, isValidCommandName, isWireGoalPhase, isWireHubEvent, isWirePlanAction, isWirePluginArchiveName, isWireRewindScope, isWireSettingWriteLayer, isWireSkillDropName, makeTranslate, mcpConnectorState, normalizeApproval, packSessionSurface, parseChord, parseModelRef, parseSequence, perAction, placeholdersOf, promptTokens, resolveHostText, sequenceId, sessionPartSummary, stripSystemNote, systemNote, tableOf, totalUsageTokens, translatorFor, truncateToBudget, turnDigest, unfixedRules, utf8ByteLength, wireFields };
|