@luchenglong/cli-bridge 0.0.0-stage → 0.2.2
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/CHANGELOG.md +148 -0
- package/LICENSE +21 -0
- package/MCP-POLICY.md +53 -0
- package/PROVIDER-CONTRACT.md +235 -0
- package/README.en.md +98 -0
- package/README.md +150 -2
- package/assets/indicator-states.svg +62 -0
- package/bin/agy-quota.mjs +223 -0
- package/core/bridge-kit.mjs +549 -0
- package/core/scheduling.mjs +149 -0
- package/docs/ARCHITECTURE.md +117 -0
- package/docs/FALLBACK-AND-INDICATOR.md +93 -0
- package/docs/INSTALL.md +118 -0
- package/docs/MCP-POLICY.zh.md +49 -0
- package/docs/MIGRATION.md +43 -0
- package/docs/RELEASE-SOP.md +77 -0
- package/docs/history/agy/CHANGELOG.md +326 -0
- package/docs/history/codebuddy/CHANGELOG.md +668 -0
- package/docs/history/mimo/CHANGELOG.md +346 -0
- package/dynamic/agy.host.js +1237 -0
- package/dynamic/agy.host.template.mjs +140 -0
- package/dynamic/codebuddy.host.js +1787 -0
- package/dynamic/codebuddy.host.template.mjs +162 -0
- package/dynamic/mimo.host.js +1732 -0
- package/dynamic/mimo.host.template.mjs +169 -0
- package/home-plugin/cli-bridge-indicator/cordis.patch.yml +31 -0
- package/home-plugin/cli-bridge-indicator/lib/client.js +606 -0
- package/home-plugin/cli-bridge-indicator/lib/index.mjs +420 -0
- package/home-plugin/cli-bridge-indicator/lib/preset-declarations.mjs +137 -0
- package/home-plugin/cli-bridge-indicator/lib/settings.mjs +300 -0
- package/mcp/agy-mcp-server.mjs +6 -0
- package/mcp/cli-bridge-mcp.mjs +184 -0
- package/mcp/codebuddy-mcp-server.mjs +6 -0
- package/mcp/mimo-mcp-server.mjs +6 -0
- package/mcp/providers/agy.mjs +254 -0
- package/mcp/providers/codebuddy.mjs +397 -0
- package/mcp/providers/mimo.mjs +290 -0
- package/package.json +87 -4
- package/preset/agy-first/agent.cordis.yml +141 -0
- package/preset/agy-first/cli-bridge.mjs +169 -0
- package/preset/agy-first/plugin-list.mjs +26 -0
- package/preset/agy-first/preset.yml +3 -0
- package/preset/codebuddy-first/agent.cordis.yml +141 -0
- package/preset/codebuddy-first/cli-bridge.mjs +188 -0
- package/preset/codebuddy-first/plugin-list.mjs +20 -0
- package/preset/codebuddy-first/preset.yml +3 -0
- package/preset/mimo-first/agent.cordis.yml +143 -0
- package/preset/mimo-first/cli-bridge.mjs +236 -0
- package/preset/mimo-first/plugin-list.mjs +39 -0
- package/preset/mimo-first/preset.yml +3 -0
- package/preset/standard-base.mjs +102 -0
- package/providers/agy.mjs +398 -0
- package/providers/codebuddy.mjs +926 -0
- package/providers/mimo.mjs +864 -0
- package/providers/registry.mjs +34 -0
- package/scripts/build.mjs +235 -0
- package/scripts/deploy.mjs +61 -0
- package/scripts/verify.mjs +148 -0
|
@@ -0,0 +1,668 @@
|
|
|
1
|
+
# 更新日志
|
|
2
|
+
|
|
3
|
+
本项目遵循 [语义化版本](https://semver.org/);版本号同步 `package.json`、Git tag 与 GitHub Release(`npm run check` 中的 `scripts/verify.mjs` 在 CI 里锁三处一致)。
|
|
4
|
+
|
|
5
|
+
## [1.6.2] - 2026-09-25
|
|
6
|
+
|
|
7
|
+
### 修复
|
|
8
|
+
- **「默认模型」候选只剩一个,看起来像模型列表丢了(用户实测反馈)**。用户指出
|
|
9
|
+
「所有的模型列表只有 deepseek-v4.1-flash 一个」——核查后确认**数据是完整的**
|
|
10
|
+
(live 接口实测返回 `codebuddy` 53 / `codebuddy-intl` 53 / `codebuddy-en` 26 /
|
|
11
|
+
`workbuddy` 53 项,一条没少),问题出在**渲染方式**:原来用的是 `<input list=…>` +
|
|
12
|
+
`<datalist>`,这是**自由文本框**,浏览器会**按输入框当前文字做前缀过滤**。
|
|
13
|
+
用户此刻的 `defaultModel` 正是 `deepseek-v4.1-flash`,而它又恰好排在候选第 1 位
|
|
14
|
+
(带 `Free now` 促销、实付 `x0.00`,落在免费段最前),于是展开下拉时只剩它自己 ——
|
|
15
|
+
看起来就像「整个列表只有一个模型」。
|
|
16
|
+
|
|
17
|
+
改用**显式 `<select>`** 列出全部可用型号(含 `(留空 = 各 CLI 自身默认)` 首项),
|
|
18
|
+
候选**不再受输入文字影响**;另加「**自定义…**」一项切到手动输入框,保留手输任意
|
|
19
|
+
model id 的能力(原 datalist 的自由输入语义不丢)。note 文案改为显示**实际候选数**
|
|
20
|
+
(如「共 26 项」),让「列表是不是空的」一眼可验。
|
|
21
|
+
|
|
22
|
+
- 顺带修掉一处样式拼接故障:`.cbs-rate-promo` 与 `.cbs-rate-ids` 两行被并到了同一行,
|
|
23
|
+
前者缺尾逗号会导致 CSS 解析中断、橙色促销标签不生效。
|
|
24
|
+
|
|
25
|
+
### 测试
|
|
26
|
+
- 155 通过(本次为渲染层改动,核心逻辑测试不变)。
|
|
27
|
+
|
|
28
|
+
## [1.6.1] - 2026-09-25
|
|
29
|
+
|
|
30
|
+
### 修复
|
|
31
|
+
- **数据源层次仍然不对:「安装目录的 product.json」不是用户菜单(v1.6.0 的遗留错误)**。
|
|
32
|
+
用户指出 v1.6.0 的输出与实际菜单不符 ——「WorkBuddy 国际版的免费项是 Hy4 preview / Hy3 /
|
|
33
|
+
Deepseek-V4.1-Flash(都是 Free now 0.00x),国内版是 Hy4 preview(夜间免费 0.29x)与
|
|
34
|
+
Hy3(限时免费 0.00x)」,**核实后确认用户是对的**,v1.6.0 读的层从头就偏了。
|
|
35
|
+
|
|
36
|
+
真正的三层结构(实测):
|
|
37
|
+
| 层 | 位置 | 作用 |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| ① | 安装目录 `product.json` / `product.ioa.json` | **产品面默认值**(v1.6.0 唯一读的层) |
|
|
40
|
+
| ② | `~/.workbuddy`、`~/.workbuddy-ai` 的 `cache/acc-product-config-v3.json` | 账号级配置,**含 `modelPromotions`** |
|
|
41
|
+
| ③ | 同目录 `local_storage/entry_*.info` | 桌面客户端实时快照,**用户菜单看到的就是它** |
|
|
42
|
+
|
|
43
|
+
关键证据:用户菜单里的「**Free now**」「**夜间免费**」「**限时免费**」全部来自
|
|
44
|
+
`modelPromotions`,而**安装目录的 product.json 根本没有这个字段** —— 所以无论怎么读
|
|
45
|
+
那个文件,都不可能显示出用户看到的东西。
|
|
46
|
+
|
|
47
|
+
- 新增 `accountConfigCandidates()`:把账号级配置排到候选链**最前**,安装目录描述文件降为兜底。
|
|
48
|
+
- 新增 `normalizeProductConfig()`:账号文件有**两种形态** —— `cache/` 是裸 product 对象,
|
|
49
|
+
`local_storage/entry_*.info` 是 `[{userId, data}, …]` 数组(本机国际版文件里有
|
|
50
|
+
527fed08 与 dc632238 **两个账号**的配置)。取数组**末尾**一份(最新写入在末尾)。
|
|
51
|
+
- 新增 `extractModelPromotions()` / `isPromotionActive()` / `activePromotionFor()`:
|
|
52
|
+
解析促销并**按有效期 + 跨零点时段**判定是否生效(「夜间免费」为 23:00–次日 8:00)。
|
|
53
|
+
- `parseCreditValue()` 补认 `"0.00x"` / `"0x"` 写法 —— 促销价的数字在前、x 在后,
|
|
54
|
+
与 `credits` 字段的 `"x0.29 credits"` **恰好相反**,不兼容会漏掉「Free now」的价格。
|
|
55
|
+
- 候选链改为**按字段各自取第一个有内容的文件**,而不是取第一个能读到的:实测国际版
|
|
56
|
+
`cache/` 停在旧时间点(37 项、**无促销、且没有 hy4-preview / deepseek-v4.1-flash**),
|
|
57
|
+
却排在链首,会遮蔽后面更新的 `local_storage` 快照(26 项、含三条 Free now)。
|
|
58
|
+
|
|
59
|
+
### 实测结果(与用户菜单逐条吻合)
|
|
60
|
+
- `workbuddy`(国内版,53 项):`hy3 · 免费 · 限时免费`、`hy4-preview · x0.29 · 夜间免费`
|
|
61
|
+
(白天只挂角标不折扣、夜间 factor=0 转免费,与菜单的「夜间免费 0.29x」一致)、
|
|
62
|
+
`deepseek-v4-pro · 夜间折扣`、`glm-5.2 · 夜间折扣`。
|
|
63
|
+
- `codebuddy-en`(国际版,26 项):`hy3` / `hy4-preview-f` / `deepseek-v4.1-flash`
|
|
64
|
+
三条均为 `免费 · Free now` —— **与用户描述完全一致**。
|
|
65
|
+
|
|
66
|
+
### 变更
|
|
67
|
+
- 面板新增「限时优惠 ×N」一行,列出**当前生效**的促销及其名称,与 CLI 菜单对齐;
|
|
68
|
+
下拉标签形如 `hy4-preview · x0.29 · 夜间免费`。`baseCredits`(原价)一并透传,
|
|
69
|
+
便于判断促销力度。
|
|
70
|
+
|
|
71
|
+
### 测试
|
|
72
|
+
- 148 → **155** 通过。新增 7 例:`normalizeProductConfig` 双形态、`extractModelPromotions`
|
|
73
|
+
展开与跳过规则、`isPromotionActive` 有效期与跨零点边界(8:00 整点为开区间)、
|
|
74
|
+
`activePromotionFor` 多条的 priority 取舍、`parseCreditValue` 双写法、
|
|
75
|
+
`modelCatalogDetailed` 促销计价与标签、以及**旧缓存遮蔽更新快照**的真实场景回归。
|
|
76
|
+
|
|
77
|
+
## [1.6.0] - 2026-09-25
|
|
78
|
+
|
|
79
|
+
### 修复
|
|
80
|
+
- **模型清单读错文件、且混入不可用型号(用户连续三次反馈的「模型获取错误」根因)**:
|
|
81
|
+
此前每个后端都只读安装目录下的 `product.json`。真机逆向 `npm\dist\codebuddy.js` 里的
|
|
82
|
+
`ClientInternetEnviromentProductProvider` 后确认:CLI 运行时加载的是
|
|
83
|
+
**`product.${env}.json`**(`env` 由 `CODEBUDDY_INTERNET_ENVIRONMENT` / settings 的 `env` /
|
|
84
|
+
账号的 `productConfigEnv` 决定,后者在本机解析为 `ioa`),读取失败才回退 `product.json`。
|
|
85
|
+
于是四个后端的清单全部来自「另一份文件」——这正是反复出现错漏的根因。
|
|
86
|
+
- `PRODUCT_DESCRIPTOR_ENV` 改为 `rel: product.ioa.json` + `fallbackRel: product.json`
|
|
87
|
+
(WorkBuddyAI 只带 `product.json`,回退链在其上真正生效)。
|
|
88
|
+
- 解析结果:`codebuddy` 30→67、`codebuddy-intl` 36→53、`codebuddy-en` 37(无 ioa 变体,回退)、
|
|
89
|
+
`workbuddy` 48→93;`claude-opus-4.8`、`gpt-5.4` 等首次正确出现。
|
|
90
|
+
|
|
91
|
+
- **描述文件不是「可用清单」——新增账号级授权分流(本次核心修正)**:
|
|
92
|
+
实测发现描述文件里绝大多数型号**本账号无权使用**:
|
|
93
|
+
`glm-5.3-ioa`、`hy3-ioa`、`deepseek-v4-pro-ioa` 全部返回
|
|
94
|
+
`400 ... is only available for authorized users`,而未带后缀的 `glm-5.3` / `hy3` 正常可用。
|
|
95
|
+
即描述文件用的 `-ioa` 命名与服务端账号清单**不是同一套 id**。
|
|
96
|
+
- 新增 `parseAccountModels()` 的**落地调用**:任何一次真实调用返回 400 时,CLI 会附
|
|
97
|
+
`Currently supported models for your account:`,`buildResult` 顺手解析并经
|
|
98
|
+
`rememberAccountCatalog()` 缓存 —— 零额外开销地拿到**唯一权威的可用清单**。
|
|
99
|
+
- 新增 `lookupModelCredits()`:跨 `-ioa` 命名与别名表匹配倍率,
|
|
100
|
+
使账号清单里的 `glm-5.3` 也能挂上描述文件里 `glm-5.3-ioa` 的 x0.79。
|
|
101
|
+
- `modelCatalogDetailed()` 合并两个来源:账号清单条目标 `authorized: true` 并排在最前,
|
|
102
|
+
描述文件独有的标 `authorized: false` 并在 label 里加「未授权」。
|
|
103
|
+
- 本机实测:`codebuddy` / `codebuddy-intl` / `workbuddy` 均为
|
|
104
|
+
**已授权 16 个、未授权 51~93 个**,且 16 个可用型号**全部挂上倍率**,
|
|
105
|
+
数值与用户 CLI 菜单截图逐条吻合(`glm-5.2` x0.79、`kimi-k2.6` x0.52、`minimax-m2.7` x0.19、
|
|
106
|
+
`hy4-preview` 免费)。
|
|
107
|
+
|
|
108
|
+
- **倍率字段未透传到面板(自查发现的连带缺陷)**:`backendSettingsMeta()` 的 `modelOptions`
|
|
109
|
+
漏传 `authorized`,导致面板「可用 / 未授权」分流全部落空、一个模型都渲染不出来。
|
|
110
|
+
已补上并用回归测试锁死。
|
|
111
|
+
|
|
112
|
+
### 变更
|
|
113
|
+
- **四个后端一律以自己安装的描述文件为准,取消 npm 面的静态表并集**(推翻 v1.4.1/v1.4.2 的设计)。
|
|
114
|
+
静态实测表既缺 CLI 真实菜单里的型号,又会留住已下架的 id;现降级为「读不到文件时的兜底」。
|
|
115
|
+
- 面板:下拉候选只列**本账号可用**的型号(上限 60 条),并在倍率区新增
|
|
116
|
+
「未授权 ×N」一行单独列出不可用型号 —— 避免用户选中后才发现报 400。
|
|
117
|
+
- `POLICY_TEXT` 与六处 `model` 参数说明同步改写:明确「可用性由账号决定,权威清单来自服务端
|
|
118
|
+
400 报文」,并点名 `claude-opus-4.8` / `gpt-5.4` / `gpt-6-astra` 属「目录里有但本账号无权限」。
|
|
119
|
+
|
|
120
|
+
### 测试
|
|
121
|
+
- 144 → **148** 通过。新增:`lookupModelCredits` 跨命名/别名匹配、
|
|
122
|
+
`modelCatalogDetailed` 授权分流与排序、`rememberAccountCatalog` 缓存语义(空数组不覆盖、
|
|
123
|
+
返回副本)、`authorized` 透传回归;并改写两条编码旧并集设计的用例。
|
|
124
|
+
|
|
125
|
+
## [1.5.0] - 2026-09-25
|
|
126
|
+
|
|
127
|
+
**每个模型后面挂上倍率**。用户要求:「在模型后方都挂上倍率,并且能够根据 cli 同步更新,让用户能够精确判断」。
|
|
128
|
+
|
|
129
|
+
### 倍率从哪来
|
|
130
|
+
|
|
131
|
+
查证 CLI 侧:`--help` 只印 id、**没有任何列出倍率的子命令**;而每个安装的 `product.json` **顶层** `models[]` 里带 `credits` 字段,就是界面那个 `0.00x`:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{ "id": "hy3", "credits": "x0.00 credits" }
|
|
135
|
+
{ "id": "glm-5.3", "credits": "x0.79 credits" }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
注意 `agents.cli.models` 只是**字符串数组、不带倍率**,所以必须读顶层 `models[]`。三种安装字段形态一致(`x0.29 credits` / 偶尔省略后缀的 `x0.00` / 空串),国内桌面版有 39 项没有该字段。
|
|
139
|
+
|
|
140
|
+
### 改了什么
|
|
141
|
+
|
|
142
|
+
- **新增 `extractModelCredits()` / `parseCreditValue()`**:只认 `x<数字>` 前缀,其余一律 `null`。**关键设计:`0` 与「未知」严格区分** —— `x0.00` 解析为数字 `0`(免费),空串/缺失为 `null`(未标倍率)。绝不把缺失猜成 0,否则用户会把「厂商没标」误读成「免费」。
|
|
143
|
+
- **新增 `modelCatalogDetailed(backend, io)`**:返回 `{id, credits, free, label, hasCredits}`,`label` 形如 `hy3 · 免费` / `glm-5.3 · x0.79`;无倍率数据时不挂后缀。**排序:有倍率的在前并按升序**(免费自然浮到最前),无数据的稳定殿后。
|
|
144
|
+
- **新增 `formatCreditLabel()`**:`0 → 免费`,其余统一两位小数(`x1.20`)便于竖排对齐。
|
|
145
|
+
- **`backendSettingsMeta()` 增补 `modelOptions`**(带 label/credits/free),`models` 仍保持纯 id 数组以向后兼容;`modelCatalogDetailed` 支持 `io` 注入,沿用既有的纯函数约定(**不联网、不 spawn**)。
|
|
146
|
+
- **面板**:输入框 `datalist` 改用 `label`,并在下方新增**倍率一览**——分「免费 ×N」「计费」「未标倍率」三行渲染,附说明「倍率取自该 CLI 的 product 描述文件,随 CLI 升级自动同步」。
|
|
147
|
+
- **同步方式**:与 id 同源,都读该后端自己的 product 描述文件,**运行时读取**——用户升级 CLI 后重启即自动更新,无需改插件。
|
|
148
|
+
- **policy 与六处 schema 描述**加入成本指引(`x0.00` 即免费;优先选够用的最便宜型号)。
|
|
149
|
+
|
|
150
|
+
### 顺带修掉一个反复踩的坑
|
|
151
|
+
|
|
152
|
+
单引号 JS 字符串里写英文所有格(`id's`、`machine's`)会把字符串提前截断,报 `SyntaxError: Unexpected identifier 's'`。这个坑在 v1.4.1、v1.4.2、v1.5.0 **各踩过一次**,每次都要靠人肉看生成物的报错才发现。现在 `test/build-sync.test.mjs` 里加了一道**引号状态机守卫**:逐行扫描,只在「单引号字符串内部又出现 撇号+字母」时报警(双引号串里的 `session's` 合法,不误报),并直接指出文件与行号。
|
|
153
|
+
|
|
154
|
+
测试 136→144。
|
|
155
|
+
|
|
156
|
+
## [1.4.2] - 2026-09-25
|
|
157
|
+
|
|
158
|
+
**「哪个产品面提供哪些模型」搞清楚了**。用户反馈:WorkBuddy 国际版界面上明明有 `Hy4 preview` / `Hy3` / `Deepseek-V4.1-Flash` 三个 **Free now(0.00x)** 模型,列表里却看不到。
|
|
159
|
+
|
|
160
|
+
### 查证结果
|
|
161
|
+
|
|
162
|
+
读各安装 `product.json` 的 `credits` 字段实测:
|
|
163
|
+
|
|
164
|
+
| 模型 | npm CLI(`codebuddy`/`codebuddy-intl`) | WorkBuddyAI(`codebuddy-en`) |
|
|
165
|
+
|---|---|---|
|
|
166
|
+
| `hy3` | `x0.00` ← 免费 | `x0.00` ← 免费 ✅ |
|
|
167
|
+
| `deepseek-v4.1-flash` | `x0.00` ← 免费 | **目录里根本没有** ❌ |
|
|
168
|
+
| `hy4-preview` | `x0.29`(促销号常免费) | **目录里根本没有** ❌ |
|
|
169
|
+
|
|
170
|
+
所以那三个免费模型是 **npm CLI 面**(`codebuddy`)的目录,**不是 WorkBuddyAI 的**。而 v1.4.1 的 `codebuddy-en` 清单是照 WorkBuddyAI 的 product.json 拼的 —— 它自己只有 `hy3` 一个免费模型,`agents.cli.models` 更只有 4 个角色别名(fast/balanced/primary/deep-model)。
|
|
171
|
+
|
|
172
|
+
### v1.4.1 的残余错误
|
|
173
|
+
|
|
174
|
+
v1.4.1 的并集逻辑(静态表 ∪ 文件)**会把 npm 面的型号混进桌面版**,让 `codebuddy-en` 列出自己安装根本不存在的型号 —— 用户选了必然报错。
|
|
175
|
+
|
|
176
|
+
### 改了什么
|
|
177
|
+
|
|
178
|
+
- **新增 `BACKEND_STRICT_CATALOG`**:`codebuddy-en` / `workbuddy` 两个桌面后端**严格只认自己安装目录里的 product 描述文件**,不与静态表做并集;npm 两个后端(`codebuddy` / `codebuddy-intl`)保持并集(静态账号实测表在前)。
|
|
179
|
+
- **`codebuddy-en` 静态回退表按实测重写**:按其 `credits` 字段排序,**免费优先** —— 首项为 `hy3`,其后是 `gpt-5.1-codex-mini`、`gemini-3.1-flash-lite`、`gemini-2.5-flash`、`minimax-m3`、`gemini-3.0-flash`、`deepseek-v3-2-volc` 等;**移除** `hy4-preview` / `deepseek-v4.1-flash`(该安装没有)。
|
|
180
|
+
- policy 模型段重写为「先分清是哪个产品面提供,再看账号授权」,并点名三个免费模型的归属。
|
|
181
|
+
- 新增 2 个测试(严格边界 + 免费模型归属),测试 134→136。
|
|
182
|
+
|
|
183
|
+
## [1.4.1] - 2026-09-25
|
|
184
|
+
|
|
185
|
+
**模型清单的权威来源找对了:按账号,不按安装**。用户指出「分清楚 codebuddy 与 workbuddy 的模型,暂时看来可能有误」——**确实有误,且 v1.4.0 的整个思路就是错的**。
|
|
186
|
+
|
|
187
|
+
### v1.4.0 错在哪
|
|
188
|
+
|
|
189
|
+
v1.4.0 认为「各安装的 `product.json` 是权威清单」,于是照它硬编码。真机把那些 id **逐个喂给 CLI 实测**后发现大量根本不存在:
|
|
190
|
+
|
|
191
|
+
```
|
|
192
|
+
--model default-model → 400 model [default-model] service info not found
|
|
193
|
+
--model primary-model → 400 model [primary-model] service info not found
|
|
194
|
+
--model gpt-6-astra → 400 model [gpt-6-astra] service info not found
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`product.json` 里的 `agents.cli.models` 是**发行版内置的候选表**,不等于**该账号实际可用**的模型。另外 `--help` 的静态表(`glm-5.2, kimi-k2.6, …`)对**三个安装完全相同**——这本身就说明差异不在安装,而在账号。
|
|
198
|
+
|
|
199
|
+
还有一处读错了文件:`workbuddy` 的 rel 用的是 `product.cloudhosted.json`(其 `endpoint` 与 `authentication.id` **均为空**,只是变体碎片),而该安装真正的产品面是 `product.json`(`applicationName=WorkBuddy`、`auth.id=workbuddy-desktop`、`endpoint=copilot.tencent.com`)。已改正。
|
|
200
|
+
|
|
201
|
+
### 真正的权威来源
|
|
202
|
+
|
|
203
|
+
给 CLI 传一个**不存在的 model**,服务端会在 400 里回一行 `Currently supported models for your account:`,后跟逐行 ` - <id>` —— 这是**按账号实时**返回的清单。v1.4.1 新增 `parseAccountModels()` 解析它(core 保持纯函数,不联网、不 spawn)。
|
|
204
|
+
|
|
205
|
+
**实测该账号(codebuddy 与 workbuddy 结果一致)**:`hy4-preview, hy3, hy3-x, deepseek-v4.1-flash, glm-5.3, glm-5.3-flash, glm-5.2, glm-5.1, glm-5v-turbo, minimax-m3, kimi-k3-1, kimi-k2.8-preview, kimi-k2.7, kimi-k2.6, deepseek-v4-pro`(`workbuddy` 另接受 `auto`;`minimax-m2.7` 实测也可用)。
|
|
206
|
+
|
|
207
|
+
### 改了什么
|
|
208
|
+
|
|
209
|
+
- **优先级反转**:`backendModelCatalog()` 改为**静态表(= 账号实测清单)为主**,product 文件**只做并集补充**(v1.4.0 反了,把不存在的 id 当成候选项)。静态表在前也保证下拉里最靠谱的排最前。
|
|
210
|
+
- **静态表按实测重写**:`codebuddy` / `workbuddy` 用上述账号清单(`workbuddy` 多 `auto`);`codebuddy-en` / `codebuddy-intl` 去掉 `default-model` / `primary-model` / `gpt-6-astra` 一类不存在的 id。
|
|
211
|
+
- **新增 `parseAccountModels()` + 测试**:解析服务端账号清单,含去重与「`Authentication required` 时报 null」的容错。
|
|
212
|
+
- 测试 132→134 例;policy 模型段重写为「可用性由账号决定,不由安装或产品面决定」,并写明两种 400 的区分(`service info not found` = 不在清单;`only available for authorized users` = 在清单但未授权)。
|
|
213
|
+
|
|
214
|
+
## [1.4.0] - 2026-09-25
|
|
215
|
+
|
|
216
|
+
**模型清单改为运行时读取 + CodeBuddy 国际版独立成第五个选项**:用户反馈「四个产品面的模型获取错误,请核实路径」,并要求「把国际版 WorkBuddy 与国际版 CodeBuddy 区成两个选项」。逐安装实测后确认:旧清单确实是错的(`codebuddy-en`/`workbuddy` 两份抄的是**国内版 `product.internal.json`**,且含本机不存在的型号),且此前把两个国际面混为一谈。
|
|
217
|
+
|
|
218
|
+
### 改了什么
|
|
219
|
+
|
|
220
|
+
- **模型清单不再硬编码**:新增 `readBackendModelCatalog()` / `extractModelIds()`,**运行时**从各安装自己的 product 描述文件现读 `agents.cli.models`(与顶层 `models` 取更完整的那份——真机实测 WorkBuddyAI 的 `agents.cli.models` 只有 4 个**角色别名**,37 个真实 id 在顶层 `models`)。读不到时回退内置静态表(即本次真机实测值),**永不抛错、永不为空**。
|
|
221
|
+
> ⚠ **此思路已被 v1.4.1 推翻**:product.json 是**发行版候选表**,不是**账号可用表**;照它列会给出大量本机不存在的 id(`default-model` / `primary-model` / `gpt-6-astra` 实测均报 `service info not found`)。v1.4.1 已反转为「静态账号实测表为主」。
|
|
222
|
+
- ~~`codebuddy`(npm `product.json`)→ 22 项;`codebuddy-intl`(npm `product.ioa.json`)→ 53 项;`codebuddy-en`(WorkBuddyAI `product.json`)→ 37 项;`workbuddy`(WorkBuddy `product.cloudhosted.json`)→ 23 项~~(**已被 v1.4.1 推翻**:这些是发行版候选,非账号可用;且 `workbuddy` 应读 `product.json` 而非 `cloudhosted`)。
|
|
223
|
+
- 修正真机实测清单:`codebuddy` = `glm-5.2, kimi-k2.6, minimax-m2.7, claude-opus-4.8(-1m), gpt-5.4, deepseek-v4-flash/-pro, default, deepseek-v3-0324`(与 `--help` 一致)。
|
|
224
|
+
- **新增后端 `codebuddy-intl`(CodeBuddy 国际版)**:与 `codebuddy` 是同一个 npm CLI 的**国际面**(`product.ioa.json` 目录:`claude-sonnet-5` / `claude-opus-5` / `gemini-3.1-pro` / `gpt-6-astra` / `hy3-ioa` …),面板上是**独立选项**,与「WorkBuddy 国际版」(`codebuddy-en`)区分。别名 `codebuddy-ioa` / `codebuddy-international` / `codebuddy-oversea` 归一。**规范 id 只增不改**:`codebuddy`/`codebuddy-en`/`workbuddy` 仍是历史会话归档键。
|
|
225
|
+
- **实测结论(重要)**:国际面模型**确实被同一个 npm CLI 接受**,但由服务端按账号授权放行 —— 真机 `--model claude-sonnet-5` 返回 `400 model [...] is only available for authorized users`,而 `--model hy4-preview` 正常返回 `PONG`。故 `codebuddy-intl` 的诊断提示专门说明这是**账号授权**问题、不是配置错误(避免用户误改端点/凭据)。
|
|
226
|
+
- **文案与 schema**:`POLICY_TEXT` 的后端段与模型段、preset/dynamic/MCP 六处 `enum` 与描述、面板「默认模型」提示(改为「运行时从安装目录实时读取」)全部同步到四后端。
|
|
227
|
+
|
|
228
|
+
## [1.3.3] - 2026-09-25
|
|
229
|
+
|
|
230
|
+
**WorkBuddy 国际版正名 + 后端别名**:用户反馈「把 WorkBuddy 国际版(`C:\Program Files\WorkBuddyAI`)加入列表」——实测核实该目录**在 v1.3.1 就已接入**(即 `codebuddy-en` 后端:二进制指向 WorkBuddyAI 自带 CLI,登录域 `www.workbuddy.ai`),但旧标签「CodeBuddy 国际版」把它藏在了 CodeBuddy 名下,看起来像缺一个后端。本版更正可见命名并补别名,功能面零变化。
|
|
231
|
+
|
|
232
|
+
### 改了什么
|
|
233
|
+
|
|
234
|
+
- **显示标签**:`codebuddy-en` 的用户可见名改为「**WorkBuddy 国际版(WorkBuddyAI 桌面 CLI)**」(设置面板下拉、诊断表、preset 设置描述同源生效)。
|
|
235
|
+
- **后端别名**:`backend="workbuddy-en"` / `"workbuddy-ai"` 归一为 `codebuddy-en`(新增 `normalizeBackend()` + `BACKEND_ALIASES`;大小写/首尾空白不敏感)。三条优先级通道(显式参数 / 会话归属 / 用户偏好 `preferredBackend`)与设置文件清洗(`normalizeBridgeSettings`)全部走归一,**规范 id 保持 `codebuddy-en` 不变** —— 历史会话按其归档,续接路由不受影响。工具 schema 的 `enum` 六处同步列出别名(宿主照单接受)。
|
|
236
|
+
- **文案纠偏**:policy 文本里 v1.3.0 时代的错误说法("using the same installed CLI binary")改为真机事实(三个独立安装包);模型分组不再把 `workbuddy`(国内办公面)标成 "international",改称 "desktop-bundled"。
|
|
237
|
+
|
|
238
|
+
## [1.3.2] - 2026-09-25
|
|
239
|
+
|
|
240
|
+
**可视化配置界面**:DSH 设置里新增「CodeBuddy 桥接」分区 —— 首选 CLI / 默认模型 / 端点覆盖 / 国际版凭据四项偏好在同一面板编辑保存,外加逐后端的生效配置诊断(登录域 → 端点 → 凭据来源)。保存即对 **preset / 动态插件 / MCP 三种形态**同时生效,无需重启。
|
|
241
|
+
|
|
242
|
+
### 为什么是自绘面板而不是官方自动表单
|
|
243
|
+
|
|
244
|
+
- 官方 `Config` 导出投影表单只覆盖 `fiber.entry.id === "include"` 的条目(`dsh-config-editor` L31);preset 桥接行经 `PresetTree` 组合挂载、不是 include → 桥接插件的 `Config` 永远进不了表单投影(0.1.7-rc.1 源码逐行核实)。
|
|
245
|
+
- `ctx.configForms` 的 host 命名空间通道依赖未在本 build 安装的 owner 包与 `WEB_SETTINGS_NAMESPACES` 白名单,且写入 `profiles\web\cordis.patch.yml` —— 对 preset/dynamic/MCP 三个进程不可见。
|
|
246
|
+
- 结论:**自绘分区 + 自家读写路由** 是唯一能让一次保存抵达全部三种形态的路径。表单消费面(settings.section 列表槽、label thunk、locale 读时解析)与 dsh-dream-skin / dsh-mobile-companion 完全同构。
|
|
247
|
+
|
|
248
|
+
### 机制(单一事实源:`<dsh-home>/codebuddy-bridge-settings.json`)
|
|
249
|
+
|
|
250
|
+
- **core 新增设置文件原语**(三形态与 host 共用):`SETTINGS_FILE_NAME` / `SETTINGS_KEYS` / `bridgeSettingsPath()`(`CODEBUDDY_SETTINGS_FILE` 可整体覆盖,测试注入)/ `normalizeBridgeSettings()` / `readBridgeSettingsFile()`(**文件缺失返回 `null`**,与「文件说默认值」可区分)/ `sanitizeBridgeSettings()` / `writeBridgeSettingsFile()`(tmp+rename 原子写,失败清理)。另新增 `BACKEND_MODEL_IDS` / `BACKEND_LABELS` / `backendSettingsMeta()` / `allBackendSettingsMeta()` / `diagnoseBackend()` / `readBackendAuthDomain()`(不占用 `readAuthDomain` 之名:core 以文本注入 dynamic 模板作用域,重名函数声明会静默互相覆盖)。
|
|
251
|
+
- **host 半(codebuddy-indicator)**:新增 `GET/POST /codebuddy-indicator/settings`(webServer 精确路由,handler 内自分发方法;body ≤64KB)。GET 返回视图 = 当前值 + 三后端元数据 + 诊断 + **掩码 token(尾 4 位,明文永不回传浏览器)**;POST 只认四个已知字段全清洗,token 语义:缺省/空串 = 保持现值、`codebuddyEnTokenClear:true` 显式清除。纯函数面(`maskToken`/`settingsView`/`parseSettingsBody`)可脱离 DSH 单测。
|
|
252
|
+
- **浏览器半(client.js)**:注册 `settings.section` 分区(id `codebuddy-bridge-settings`、order 7、label thunk 中英双语)。面板含后端下拉(联动该后端实测模型候选 datalist)、默认模型、端点覆盖、token(password 输入 + 清除勾选)、保存/重载反馈与诊断表(每后端:生效端点+来源、登录域、凭据来源、可能 401 警示)。
|
|
253
|
+
- **三形态热生效**:preset 桥接与 dynamic 模板的 runner getters 每次调用现读设置文件(文件 > 行 config > 默认——旧 patch 遗留行 config 不再吞掉面板保存);dynamic 模板删掉本地 `readBridgeSettings()` 副本改用 core;MCP 用 core 的 `readBridgeSettingsFile` 替换本地清洗(5s 缓存与 bin 父目录回退保留)。
|
|
254
|
+
- **deploy.mjs 新增第 5 步**:把 `core/` 与 `mcp/` 同步复制到 `<dsh-home>/core` + `<dsh-home>/bin`(家级 patch 的 mcp-codebuddy-global 指向 bin 副本,v1.3.1 时它漂移在 1.3.0 无人察觉)。
|
|
255
|
+
|
|
256
|
+
### 测试与治理
|
|
257
|
+
|
|
258
|
+
- 新增 `test/settings-ui.test.mjs` 14 例:core 原语(缺失/往返/原子性/损坏/清洗/写失败清理)、host 纯函数与 GET/POST 端到端(含 token 保持/清除、400/405、掩码无泄漏)、preset 热生效三连(保存即切后端、文件优先于行 config、无文件回退行 config)、client 假 react 烟测(注册形状 + 加载 id 回归锁 + 首帧不触网)。
|
|
259
|
+
- `verify.mjs` 新增 6 道闸门:indicator package.json 版本同步(本次即抓到 1.3.0 漂移)、settings.section 注册、路由注册、core 原语存在、dynamic 无本地重复实现。`mcp.test.mjs` 的 serverInfo 版本断言改为对照源码而非钉死字面量。
|
|
260
|
+
- 版本号本次起 **四处齐步**:根 package.json / indicator package.json / MCP `VERSION` / CHANGELOG 顶部,全部 1.3.2。
|
|
261
|
+
|
|
262
|
+
## [1.3.1] - 2026-09-24
|
|
263
|
+
|
|
264
|
+
**端点与凭据根因修复**:v1.3.0 关于国际版的机制结论(「国际版没有独立安装包,就是同一个 npm CLI + 端点 env」)经真机全盘核实**已被推翻**;本版据实测矩阵重写端点解析,并修复了一个影响**默认后端**的既存缺陷。
|
|
265
|
+
|
|
266
|
+
### 推翻 v1.3.0 的错误结论(真机证据)
|
|
267
|
+
|
|
268
|
+
- **三个产品面各有独立安装包与独立 `product.json`**,不是同一个 CLI:
|
|
269
|
+
|
|
270
|
+
| 后端 | 二进制 | productName | product 端点 | authentication.id |
|
|
271
|
+
|---|---|---|---|---|
|
|
272
|
+
| `codebuddy` | `%APPDATA%\npm\node_modules\@tencent-ai\codebuddy-code` | CodeBuddy | `www.codebuddy.ai` | `Tencent-Cloud.coding-copilot` |
|
|
273
|
+
| `codebuddy-en` | `C:\Program Files\WorkBuddyAI\...\cli\bin\codebuddy` | WorkBuddy AI | `www.workbuddy.ai` | `workbuddy-desktop-ai` |
|
|
274
|
+
| `workbuddy` | `C:\Program Files\WorkBuddy\...\cli\bin\codebuddy` | WorkBuddy | `copilot.tencent.com` | `workbuddy-desktop` |
|
|
275
|
+
|
|
276
|
+
(`C:\Users\lcl\AppData\Local\Programs\CodeBuddy` 即 CodeBuddy IDE **不附带** headless CLI,`resources/app.asar.unpacked/cli` 不存在,不可作二进制来源。)
|
|
277
|
+
- **`CODEBUDDY_AUTH_TOKEN` 本身不决定端点**:token 只在其登录域对应的端点上生效。实测:国内 token(域 `www.codebuddy.cn`)配 `workbuddy.ai/v2` → 401;配 `copilot.tencent.com/v2` → PONG。
|
|
278
|
+
- **`CODEBUDDY_INTERNET_ENVIROMENT=cloudhosted` 语义错误已删**:`www.workbuddy.ai` 属 `product.json` 的 `externalDomain`,不是 `cloudHostedDomain`。
|
|
279
|
+
|
|
280
|
+
### 修复:默认后端 codebuddy 的 401(既存缺陷)
|
|
281
|
+
|
|
282
|
+
npm CLI 的 product 端点是 `www.codebuddy.ai`,而本机登录 token 的域是 `www.codebuddy.cn` —— **域不匹配必然 401**。这正是用户会话日志中 312 次 `www.codebuddy.ai` 与 116 次 `Authentication required` 的根因:默认后端此前是坏的。实测注入 `CODEBUDDY_BASE_URL=https://www.codebuddy.cn/v2` 即恢复 PONG。
|
|
283
|
+
|
|
284
|
+
### 新机制:端点按登录域自动对齐
|
|
285
|
+
|
|
286
|
+
- 新增纯函数 `resolveEndpoint()` / `endpointEnv()` / `endpointMismatchHint()` / `endpointHost()` 与注册表 `BACKEND_ENDPOINTS` / `AUTH_DOMAIN_ENDPOINTS` / `BACKEND_AUTH_IDS`(取代 `intlEndpointEnv`)。
|
|
287
|
+
- 宿主侧读 `%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\<authentication.id>.info` 的 **`auth.domain`(三个文件均为明文)**,无需解密 token 即可对齐端点;读取失败一律回退为「沿用 CLI 自身 product 端点」。
|
|
288
|
+
- **仅当推导端点与后端 product 端点不同时才注入** `CODEBUDDY_BASE_URL`,避免无谓覆盖。
|
|
289
|
+
|
|
290
|
+
### `codebuddy-en` 凭据通道(三通道 + 自动复用)
|
|
291
|
+
|
|
292
|
+
国际版自己的 token 被 protector key(keyId `9127dea1b44020a7`)封装,该密钥**只经桌面 App 的 sidecar 通道下发、不落盘**——全盘 51612 个文件扫描、全部 DPAPI blob 解包尝试均未命中,且 CLI 自身亦以 `category:"missing-key"` 失败 21 次(`at-rest-failures-v1.json`),证明这不是探针假象。**但用户通常已经在 DSH 里配好了同一个 token**:DSH 的 provider 配置里有一个指向 `https://www.workbuddy.ai/v2` 的 workbuddy provider(`apiKeyEnv: WORKBUDDY_TOKEN`),其值就存在 `dsh-home` 的 `.credentials.yaml` / `.env` 里。真机实测:把该 token 经 `CODEBUDDY_AUTH_TOKEN` 下发给 WorkBuddyAI 自带 CLI,**无 BASE_URL 即返回 PONG**。故:
|
|
293
|
+
|
|
294
|
+
- 新增 `resolveEnToken()` / `readDshWorkbuddyToken()`:凭据按 **设置面板 `codebuddyEnToken` → 环境变量 `CODEBUDDY_AUTH_TOKEN` → DSH 凭据库** 依次取用,使 `codebuddy-en` **开箱即用**(无需用户手工粘贴)。凭据库解析只接受真实 token(≥40 字符、非 `$VAR` 引用、非 `<占位符>`),文件读取失败一律回退。
|
|
295
|
+
- 新增设置项 **`codebuddyEnToken`**;新增 **`endpointOverride`** 取代 `codebuddyEnBaseUrl`(后者默认值错误,已移除)。
|
|
296
|
+
- 三通道皆空时 `codebuddy-en` 前置返回 `AUTH_REQUIRED` 并附**可操作指引**(列出三条通道,而非让 CLI 报一句无从下手的 `Authentication required`);`isLimited` 将该状态排除出限流类,`failureHint` 透传指引。
|
|
297
|
+
- `codebuddy-en` 的二进制改指 WorkBuddyAI 自带 CLI(`CODEBUDDY_EN_BIN` 可覆盖),不再复用 npm CLI。
|
|
298
|
+
- 新增 `CODEBUDDY_CREDENTIALS_DIR` 覆盖 + `isolateHostState()` 测试助手:桥接会读 auth 库/凭据库/`DSH_HOME` 三类真机状态,不隔离则用例会随「本机是否登录、是否配过 workbuddy key」变化而不可复现。
|
|
299
|
+
|
|
300
|
+
### 测试与文档
|
|
301
|
+
|
|
302
|
+
- 测试改写:`intlEndpointEnv` 4 例断言(含已删除的 `INTERNET_ENVIROMENT`)→ 新增 `resolveEndpoint`/`endpointEnv`/`endpointMismatchHint`/`AUTH_REQUIRED` 归类共 5 例;`dynamic-sim`/`preset`/`mcp` 中依赖旧设置键与旧 env 的用例同步更新。
|
|
303
|
+
- 新增 [docs/ROOT-CAUSE-codebuddy-en.md](ROOT-CAUSE-codebuddy-en.md):完整实测矩阵(11 组后端 × 端点 × token 组合)与根因链。
|
|
304
|
+
|
|
305
|
+
## [1.3.0] - 2026-09-24
|
|
306
|
+
|
|
307
|
+
> **勘误(v1.3.1 更正)**:本版对国际版机制的结论「国际版没有独立 npm 包,就是同一个
|
|
308
|
+
> `@tencent-ai/codebuddy-code` CLI + 端点切换」**已被真机 `product.json` 推翻** —— 三个产品面
|
|
309
|
+
> 各有独立安装包(`productName` / `dataFolderName` / `endpoint` / `auth.id` 全不同),且
|
|
310
|
+
> `CODEBUDDY_INTERNET_ENVIROMENT=cloudhosted` 语义错误、`codebuddyEnBaseUrl` 默认值对默认后端有害。
|
|
311
|
+
> 详见 [1.3.1] 与 [ROOT-CAUSE-codebuddy-en.md](ROOT-CAUSE-codebuddy-en.md)。
|
|
312
|
+
|
|
313
|
+
**CodeBuddy 国际版接入 + 插件设置**:后端列表新增第三个条目 `codebuddy-en`(国际版 CodeBuddy / WorkBuddy 国际面),并在 DSH 设置面板提供「优先 CLI + 默认模型」两项用户偏好。
|
|
314
|
+
|
|
315
|
+
### 国际版后端(codebuddy-en)
|
|
316
|
+
|
|
317
|
+
- 新增 `codebuddy-en` 后端:国际版 CodeBuddy(`workbuddy.ai` 端点)。国际版**没有独立 npm 包**(已核实 npm 全量扫描与 CLI dist 内部常量)——它就是同一个 `@tencent-ai/codebuddy-code` CLI + 端点切换:CLI 官方支持 `CODEBUDDY_BASE_URL` 覆盖端点(`resolveModelBaseURL` 直接采用该值;CLI 自带 401 故障指引原文引用该变量),`CODEBUDDY_INTERNET_ENVIROMENT=cloudhosted`(官方拼写)声明云端企业环境。桥接在每次 `codebuddy-en` 调用的 spawn 上注入这两个变量(DSH subprocess 的 `spec.env` / MCP 的 spawn env),国内后端零注入。
|
|
318
|
+
- 端点机制核实(CLI dist 反编译):`isInternationalEndpoint` 按 hostname 判定国际端点(`codebuddy.ai` / `workbuddy.ai` / `staging-codebuddy.tencent.com`);`CODEBUDDY_BASE_URL` 需带 `/v2`(env 值按原样使用,只有 product 端点才会补 `/v2`)——默认值 `https://www.workbuddy.ai/v2` 与本机 profile patch 里 WorkBuddy 供应商行一致(已在用)。
|
|
319
|
+
- `coreExecute`/MCP 的后端路由重写为统一 `resolveBackend()`:显式 `backend` > 会话归属(登录域互斥)> 用户偏好 > 默认 `codebuddy`;白名单从硬编码双值改为 `BACKENDS` 注册表。工具 schema(preset/dynamic/MCP 三形态六处)与策略提示(POLICY_TEXT)同步扩为三后端,模型清单按产品面分列(国内 `hy4-preview`/`hy3`/`glm-5.3`…;国际 `auto`/`glm-5.1`/`kimi-k2.5`…——两列表来自两个已装 CLI 的 `--help` 实测)。
|
|
320
|
+
|
|
321
|
+
### 插件设置(优先 CLI + 默认模型)
|
|
322
|
+
|
|
323
|
+
- **新 DSH(≥0.1.7-alpha.1)设置面板**:preset 桥接行导出 `Config`(schemastery 同构鸭子 schema——preset 沙箱无法 import schemastery,鸭子形态是零依赖唯一路径;`toJSON()` 产出官方 refs JSON,可被官方 `z()` 原样重建,SettingsForms 投影契约逐函数核实)。三个字段全部标 `volatile`(热编辑无需重载):`preferredBackend`(枚举三后端)、`defaultModel`(留空 = CLI 默认)、`codebuddyEnBaseUrl`(默认 `https://www.workbuddy.ai/v2`)。
|
|
324
|
+
- **旧 DSH(≤0.1.6,provider/document settings)兼容**:`apply()` 里对 `ctx.settings` 鸭子探测(有 `register()` 才注册 `codebuddy-bridge` namespace + `watch` 热同步);服务缺失时静默降级为「profile patch 行 config 手改」。
|
|
325
|
+
- **MCP/动态形态**:共享同一份 dsh-home 根的 `codebuddy-bridge-settings.json`(MCP 5s 缓存重读;动态形态经 `DSH_HOME` 定位 apply 时读一次),三种形态的用户偏好一致生效。
|
|
326
|
+
|
|
327
|
+
### 测试与文档
|
|
328
|
+
|
|
329
|
+
- 新增 15 例(含真机 401 归类回归 1 例):core(BACKENDS/resolveBackend/intlEndpointEnv/buildArgv defaultModel+env/isLimited 401 收窄)×5、preset(鸭子 Config cordis 契约/SettingsForms 投影契约含官方 z() 重建对拍/三读数生效/非法回落/旧 settings 通道/静默降级)×6、dynamic-sim(codebuddy-en env 注入/偏好 defaultModel 注入与显式覆盖)×2(+2 改造)、mcp e2e(设置文件偏好 + en 路由 + 偏好模型端到端)×1;`fake-codebuddy.mjs` 夹具回报 `--model`(modelUsage 通道)。
|
|
330
|
+
- **真机验证**:`codebuddy-en` 实调(真实 CLI + env 注入)——CLI 错误原文确认请求确实被路由到 `https://www.workbuddy.ai`(env 注入链路生效),401 为国际域未登录(国际/国内登录互斥,属预期行为而非缺陷);据此把 401 认证失败从 `isLimited` 限流类中**收窄排除**(否则会误弹「回退/重试」三选一,而这两者对认证失败都无效),`failureHint` 新增认证类可行动指引(换登录域)。
|
|
331
|
+
- `npm run check` 全绿:verify 闸门 + **100** 例测试全过;版本五处同步 1.3.0。
|
|
332
|
+
|
|
333
|
+
## [1.2.0] - 2026-09-19
|
|
334
|
+
|
|
335
|
+
**Form-A 修复**:新 DSH(`@deepseek-ai/dsh` ≥ 0.1.7-alpha.1)上 preset 交付形态(A 形态)静默失效——本版恢复全版本可用,交付形态不变(安装方式/命令零改动)。
|
|
336
|
+
|
|
337
|
+
### 根因
|
|
338
|
+
|
|
339
|
+
- DSH 0.1.7-alpha.1 起 preset 从**目录制**(读取 `$DSH_HOME/.agent-presets/<id>/` 的 `preset.yml` + `agent.cordis.yml`)切换为**声明制**:preset 必须由插件在运行时向 `agentPresets` 注册表登记(官方四个 preset 即 dsh-web-app bundle patch 里的 `@deepseek-ai/dsh-agent-preset` 声明行)。旧目录在新 DSH 上**永远不会被读取**——装上即失效,无任何报错。机制边界:目录制 ≤ 0.1.6-alpha.2,声明制 ≥ 0.1.7-alpha.1。
|
|
340
|
+
|
|
341
|
+
### 修复方案(indicator 自注册声明)
|
|
342
|
+
|
|
343
|
+
- 新增 `home-plugin/codebuddy-indicator/lib/preset-definition.mjs`:codebuddy-first preset 的声明定义(官方 standard preset 全量移植 + 桥接行)。`plugins` 行序/id/config 与官方 `standard.patch.yml`(0.1.7-rc.1)逐项对齐,仅两处必要差异:末尾追加 `codebuddy-first-bridge` 桥接行(本插件全部增量);YAML `!!js` 表达式改写为等价 `{ __jsExpr: "…" }` 字面量(loader `interpolate` 一视同仁)。
|
|
344
|
+
- **注册通道 = indicator 自注册**:indicator `apply()` 里 `ctx.inject(['agentPresets'], …)` 等注册表服务出现后调用 `register(definition)`,返回的注销 disposer 登记为 effect(插件卸载/重载时先注销再重注册)。选此通道而非新增声明行的根因:`@deepseek-ai/dsh-agent-preset` 包 0.1.7-alpha.1 才存在,旧 DSH 的 loader(1.0.3)对导入失败**致命**(单声明行失败会炸掉整棵 profile 树);而 indicator 在全部 26 个已发布 dsh 版本上可加载。旧 DSH 上 `agentPresets` 服务永不出现,注入器按 cordis 语义保持挂起(等待≠失败,loader 不收集等待中的注入器),零副作用。
|
|
345
|
+
- **桥接行 name 用裸说明符子路径** `codebuddy-first-bridge/preset-bridge`(package.json `exports` 新增该子路径):注册表挂载 preset 插件时以**注册表自身的 baseUrl**(dsh-web-app 包目录)解析相对名,任何相对路径必然指错;裸说明符走 profile 包图路由,与官方行 `@deepseek-ai/dsh-tool-subagent-control/list-agents` 同机制。
|
|
346
|
+
- 失败隔离:`register()` 抛错(如重复 id)仅 `logger.warn`,绝不向宿主树抛出;等待器挂起不参与 loader 的 await 集,不拖慢启动。
|
|
347
|
+
|
|
348
|
+
### 兼容矩阵
|
|
349
|
+
|
|
350
|
+
- `scripts/dsh-compat.mjs`:新增 **C8 声明制 preset 探针**(agent-preset-registry 包存在性 + register API + 声明插件包),矩阵新增「声明制 preset」列;`PROBE_VER` → 1.2.0。
|
|
351
|
+
- `docs/COMPATIBILITY.md`:矩阵 22 → 26 版本(新增 `0.1.5-rc.3` / `0.1.7-alpha.1` / `0.1.7-alpha.2` / `0.1.7-rc.1`),Form-A 交付形态拆分为两段声明(目录制 ≤ 0.1.6-alpha.2 / 声明制 ≥ 0.1.7-alpha.1)。
|
|
352
|
+
|
|
353
|
+
### 测试
|
|
354
|
+
|
|
355
|
+
- 新增 `test/preset-declaration.test.mjs`(11 例):定义骨架 / 裸说明符(禁相对与 file:)/ `__jsExpr` 求值语义对拍 / 官方行移植完整性 / **与已装官方 standard.patch.yml 逐行 drift 比对** / 等待器新 DSH 形态(注册 + 注销)/ 旧 DSH 形态(挂起零副作用)/ 注册失败隔离 / 官方 shape 校验等价。
|
|
356
|
+
- `npm run check` 全绿:版本五处同步(package.json / MCP VERSION / CHANGELOG 顶部 / `test/mcp.test.mjs` 断言 / indicator package.json)+ verify 闸门(新增 9 项声明结构检查)+ 85 例测试全过。
|
|
357
|
+
|
|
358
|
+
## [1.1.12] - 2026-09-18
|
|
359
|
+
|
|
360
|
+
工程化修补:修复 `dsh-compat.mjs` 功能回测基线的两处真实缺陷,并把兼容矩阵从 20 个 dsh 版本扩展到 22 个(新增 `0.1.6-alpha.1` / `0.1.6-alpha.2`)。不涉及插件运行时行为。
|
|
361
|
+
|
|
362
|
+
### 修复
|
|
363
|
+
|
|
364
|
+
- **移除 `--legacy-peer-deps`**(`scripts/dsh-compat.mjs`):`@deepseek-ai/dsh-app-boot` 自 0.1.5-rc.2 起把 `@deepseek-ai/cordis-plugin-group` 等声明为**运行时必需的 peerDependencies**;`--legacy-peer-deps` 让 npm 跳过 peer 安装却仍返回成功(exit 0)——于是「第一顺位成功」后兜底不再执行,沙箱得到一个缺 peer、无法 boot 的 dsh 环境,实测 22 个版本全部在 `dsh-app-boot` 导入处 `ERR_MODULE_NOT_FOUND`(与所装插件无关)。
|
|
365
|
+
- **加 `--before=<发布时间>` 时间锚定**:dsh 内部组件互相以 `^0.1.x-rc.y` caret 范围引用;0.1.6-alpha.1/.2(2026-09-15/17 发布)出现后,安装任何历史 dsh 版本都会解析进 0.1.6-alpha.x 组件形成**混合树**,回测结果随上游发版漂移、不可复现。`--before` 让 npm 只取该版本发布时间点及以前存在的版本(另 +1 天缓冲防边界排除),树的构成与发布时代一致。
|
|
366
|
+
- **`PROBE_VER` 1.1.9 → 1.1.11**:功能回测安装的探测包版本对齐当前已发布版本。
|
|
367
|
+
|
|
368
|
+
### 兼容声明更新
|
|
369
|
+
|
|
370
|
+
- `docs/COMPATIBILITY.md`:20 → 22 版本,新增 `0.1.6-alpha.1`(2026-09-15)/ `0.1.6-alpha.2`(2026-09-17)两行,矩阵与分档按修复后的基线重跑。
|
|
371
|
+
- **更正 v1.1.10 的「CLI 环境不兼容」结论**:重跑后 `0.1.0-rc.*` / `0.1.1-rc.*` 旧版本**全部通过**,最终汇总 **PASS 17 / 功能失败 0 / 不可安装 2(E404 平台事实)/ 待重跑 3(瞬时网络超时)**。原「旧 CLI 与现代 Node ESM 不兼容」的归因随撤回(见 COMPATIBILITY §3.3)。
|
|
372
|
+
|
|
373
|
+
### 测试
|
|
374
|
+
|
|
375
|
+
- `npm run check` 全绿:版本四处同步(package.json / MCP VERSION / CHANGELOG 顶部 / `test/mcp.test.mjs` 断言,另同步 `home-plugin/codebuddy-indicator/package.json`)+ verify 闸门 + 74 例测试全过。
|
|
376
|
+
|
|
377
|
+
## [1.1.11] - 2026-09-18
|
|
378
|
+
|
|
379
|
+
工程化修补:两个发布/回测工具的**观测准确性**修复——审计刚发布的版本不再被 npm 本地缓存遮蔽,回测汇总不再把「功能失败」并入「未回测」。两者都是 v1.1.10 引入脚本后的实测反馈修,不涉及插件运行时行为。
|
|
380
|
+
|
|
381
|
+
### 修复
|
|
382
|
+
|
|
383
|
+
- **`scripts/audit-npm-sync.mjs`:版本列表加 `--prefer-online`**。`npm view <pkg> versions` 会命中 npm 本地元数据缓存,导致**刚 `npm publish` 完立刻审计仍只看到旧版本列表**(实测),审计看上去「少了最新版」;CI 里同样是新 tag 刚推、需要最新元数据。加 `--prefer-online` 强制回源取版本清单(仅版本列表回源,tarball 传输层不动,镜像兜底与 shasum 校验照旧)。
|
|
384
|
+
- **`scripts/dsh-compat.mjs`:回测汇总单列「功能失败」**。此前汇总按 `pass / skip / pending` 分档,`functional.ok === false` 的**真实功能失败**被算进 `untested`,与「根本没跑过」混为一谈——20 版本回测中 7 个「CLI 环境不兼容」的失败行口径不准确。现在 `untested = 总数 − pass − failed − skip − pending`,并把 `功能失败 ${failed}` 打进汇总行(与 `docs/COMPATIBILITY.md` §3.1 的「不可安装 / CLI 环境不兼容」分档对齐)。
|
|
385
|
+
|
|
386
|
+
### 测试
|
|
387
|
+
|
|
388
|
+
- `npm run check` 全绿:版本四处同步(package.json / MCP VERSION / CHANGELOG 顶部 / `test/mcp.test.mjs` 断言,另同步 `home-plugin/codebuddy-indicator/package.json`)+ verify 闸门 + 74 例测试全过。
|
|
389
|
+
|
|
390
|
+
## [1.1.10] - 2026-09-10
|
|
391
|
+
|
|
392
|
+
工程化:npm↔git 双侧一致性审计 + dsh 全版本回测 + 支持声明 + 交接文档体系。
|
|
393
|
+
|
|
394
|
+
### 新增
|
|
395
|
+
|
|
396
|
+
- **`scripts/audit-npm-sync.mjs`(npm run audit:npm)**:对 npm 上每个已发布版本做逐文件 sha256 比对(tarball vs `git -c core.autocrlf=false archive` 的 tag 树,取原始提交字节防 autocrlf 假阳性),校验 tag 存在性与 tarball 内 name/version 规格。分级输出 IDENTICAL / EOL-ONLY(仅行尾差异,通过但显著标注)/ DRIFT(exit 1)。传输层经 npm CLI(自动重试 + 官方元数据 dist.shasum 校验 + npmmirror 镜像兜底),规避国内直连官方 CDN 的间歇性 ECONNRESET 与 Node fetch 流截断(terminated)。**审计结论:1.1.6–1.1.9 全部版本内容零漂移**,唯一差异为 `docs/ARCHITECTURE.md` 行尾(历史工作区 CRLF 产物,见下)。
|
|
397
|
+
- **`scripts/dsh-compat.mjs`(npm run compat:dsh)**:dsh 全版本兼容性回测。Phase 1 静态探测全部 20 个已发布 `@deepseek-ai/dsh` 版本的 7 个契约点(plugin CLI / pnpm 转发 / `dsh.bundle.patch` 读取 / `dsh.profile.bundles` 对账 / persona schema / client-modules arrive 注册名校验 / `locatePkgJson` graph id 机制);Phase 2(`--full`)对每个版本做沙箱真实安装回测(隔离 USERPROFILE/APPDATA/LOCALAPPDATA 的 DSH_HOME 沙箱内跑 `dsh plugin --profile web add codebuddy-first-bridge@1.1.9`,验证依赖入列、bundles 层挂载、client 注册 id 契约)。
|
|
398
|
+
- **`docs/COMPATIBILITY.md` 支持声明**:20 版本回测矩阵 + 兼容结论(preset 要求 dsh ≥ 0.1.3-alpha.2;家级灯 bundle 安装全版本支持;1.1.7 类 id 失配在全版本都会崩,1.1.8+ 全版本成立)。
|
|
399
|
+
- **`docs/RELEASE-SOP.md`**:npm/GitHub 提交与维护 SOP(发布流程、npm 认证坑、网络坑、历史坑档案)。
|
|
400
|
+
- **`docs/HANDOVER.md`**:交接文档(项目坐标、架构速览、事故档案、未决事项、新会话上手清单)。
|
|
401
|
+
- CI 新增 **npm↔git sync audit job**(fetch-depth: 0 拉全量 tag,每次 push 自动审计双侧一致性)。
|
|
402
|
+
|
|
403
|
+
### 修复
|
|
404
|
+
|
|
405
|
+
- **CRLF 行尾归一化**:`docs/ARCHITECTURE.md`、`assets/indicator-states.svg`、`test/core.test.mjs`、`test/indicator.test.mjs` 四个工作区文件由 CRLF 归一为 LF,并新增 `.gitattributes`(`* text=auto eol=lf`)。根因:npm tarball 打包自工作区字节而 git blob 存 LF,工作区 CRLF 文件会造成 tarball 与 tag 树的行尾漂移(1.1.6–1.1.9 的 ARCHITECTURE.md 属此类;1.1.10 起工作区已归一,未来 tarball 与 tag 字节级一致)。
|
|
406
|
+
|
|
407
|
+
### 版本一致性基线
|
|
408
|
+
|
|
409
|
+
- npm 已发布版本:1.1.6 / 1.1.7 / 1.1.8 / 1.1.9,全部有对应 tag(v1.0.0–v1.1.9 共 11 个)与 GitHub Release;audit 全过(EOL-ONLY 4 项已解释归档)。
|
|
410
|
+
|
|
411
|
+
## [1.1.9] - 2026-09-11
|
|
412
|
+
|
|
413
|
+
加固:发布闸门补上 **client 注册 id 必须等于包名** 的静态检查,杜绝 v1.1.7→v1.1.8 同类事故复发。
|
|
414
|
+
|
|
415
|
+
### 背景(2026-09-10 事故)
|
|
416
|
+
|
|
417
|
+
v1.1.7 把家级灯并入主包后,`client.js` 的 `__ModuleLoader__.load({ id })` 仍写旧独立包名 `codebuddy-indicator`,与 graph row 以包名注册的 id `codebuddy-first-bridge` 不匹配 → client-modules 校验 `loaded without registering "codebuddy-first-bridge"` 失败 → 整个 client combo 崩溃 → DSH 启动致命屏(v1.1.8 热修)。根因除 id 写错外,**发布闸门漏检**:`verify.mjs` 不校验 client 注册 id,且 `prepack` 不跑测试(热修时 test 版本断言漂移也漏过)。
|
|
418
|
+
|
|
419
|
+
### 改动
|
|
420
|
+
|
|
421
|
+
- `scripts/verify.mjs` 新增 4 条护栏:主包必须声明 `exports["./client"]`;client 文件必须含 `__ModuleLoader__.load(` 调用;必须能从 load 块提取 `id:`;**提取的 id 必须严格等于 `package.json` 的 `name`**(剥除 `//` 注释后匹配,避免注释里的 id 字样干扰)。
|
|
422
|
+
- `prepack` 由 `verify + build --check` 加强为 `verify + npm test`:发布前强制跑完整测试套件,版本断言漂移等问题不再可能漏到 npm。
|
|
423
|
+
- 三处版本号同步 1.1.9(package.json / MCP VERSION / CHANGELOG;test 断言、home-plugin 子包版本一并同步)。
|
|
424
|
+
|
|
425
|
+
### 测试
|
|
426
|
+
|
|
427
|
+
- `npm run check` 全绿:版本三处同步 + persona 护栏 + 标准分发护栏 + **client id 护栏** + 全部 74 例测试通过。
|
|
428
|
+
|
|
429
|
+
## [1.1.8] - 2026-09-10
|
|
430
|
+
|
|
431
|
+
修复:client 半 `__ModuleLoader__.load` 注册 id 与包名不匹配导致 DSH 启动致命屏。
|
|
432
|
+
|
|
433
|
+
### 根因
|
|
434
|
+
|
|
435
|
+
client-modules 的 graph row 以【包名】(`codebuddy-first-bridge`)为 id;bundle 脚本执行后按
|
|
436
|
+
`loaded without registering "<packageName>"` 校验注册名。v1.1.7 起包内 client.js 仍写
|
|
437
|
+
`id: "codebuddy-indicator"`(旧独立包名),包并入主包后两者不匹配 → 整个 client combo
|
|
438
|
+
加载失败 → `Failed to load plugins`(2026-09-10 18:08 事故,桌面壳被迫进入安全模式)。
|
|
439
|
+
|
|
440
|
+
### 改动
|
|
441
|
+
|
|
442
|
+
- `home-plugin/codebuddy-indicator/lib/client.js`:注册 id 改为 `codebuddy-first-bridge`(与包名一致;slot id `codebuddy-indicator-home` 与 CSS 标记属另一命名空间,无需改)。
|
|
443
|
+
- 对照组:`agy-indicator`(独立 npm 包)包名 = 注册名,无此问题;`agy-first-bridge` v1.6.0 的 home-plugin 形态存在同样隐患(包名 ≠ 注册名),其安装为 bundle 时将复现同类错误——建议下个版本同步修正。
|
|
444
|
+
|
|
445
|
+
## [1.1.7] - 2026-09-08
|
|
446
|
+
|
|
447
|
+
适配:家级状态灯 `codebuddy-indicator` 从旧式本地 `file://` 注册改为**标准 npm 分发形态**(对齐 agy-first-bridge v1.6.0)。
|
|
448
|
+
|
|
449
|
+
### 改动
|
|
450
|
+
|
|
451
|
+
- **主包 package.json 补全标准分发字段**:`main` 直指 `./home-plugin/codebuddy-indicator/lib/index.mjs`(host 半真入口,不再是 client-entry 占位)、`exports`(`.` → index.mjs、`./client` → client.js)、`dsh.client.platform: web`(client 半自动纳入浏览器花名册)、`dsh.bundle.patch`(安装后自动挂载家级灯 bundle 补丁层)、`bin`(`codebuddy-mcp-server`)、`repository`/`homepage`/`bugs`。
|
|
452
|
+
- **新增 bundle 补丁层** `home-plugin/codebuddy-indicator/cordis.patch.yml`:裸包名 `name: codebuddy-first-bridge` 一行加载,不再有 `file://` 行、不再有 client-entry 占位 → 单实例,消除双实例二次注册崩溃风险(历史原因见 client-entry.mjs 留档注释)。
|
|
453
|
+
- **本机注册同步**:dsh-home 用户层 `cordis.patch.yml` 的 codebuddy-indicator 行由 `file:///...?v=6` 改为裸包名 `name: codebuddy-indicator`(经 junction 解析到 lib/index.mjs)。
|
|
454
|
+
- **防回归护栏**:`scripts/verify.mjs` 新增 6 条检查——主包 main 指向 indicator index.mjs、dsh.bundle.patch 声明、exports ./client、indicator 包 main 无占位、bundle 补丁层存在且含 insert。
|
|
455
|
+
|
|
456
|
+
### 安装方式(跨设备)
|
|
457
|
+
|
|
458
|
+
```
|
|
459
|
+
dsh plugin --profile web add codebuddy-first-bridge
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
### 测试
|
|
463
|
+
|
|
464
|
+
- `npm run check` 全绿:版本三处同步(package.json / MCP VERSION / CHANGELOG 顶部)+ persona 结构护栏 + 标准分发护栏 + 全部 73 例测试通过。
|
|
465
|
+
|
|
466
|
+
## [1.1.6] - 2026-09-08
|
|
467
|
+
|
|
468
|
+
适配:DSH 后端自动更新至 **0.1.3-alpha.2**(`@deepseek-ai/dsh-persona` 0.1.3-alpha.2 / Schemastery 3.18.2)的配置校验升级。
|
|
469
|
+
|
|
470
|
+
### 背景(实际报错)
|
|
471
|
+
|
|
472
|
+
DSH 后端自动更新后,官方插件 `@deepseek-ai/dsh-persona` 将配置 schema 由旧版 `text:` 字段强制升级为:
|
|
473
|
+
|
|
474
|
+
```
|
|
475
|
+
prefix: z.string().required()
|
|
476
|
+
suffix: z.string().default("")
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
Schemastery 校验器直接拒绝旧结构挂载,恢复会话时抛出:
|
|
480
|
+
|
|
481
|
+
```
|
|
482
|
+
invalid config: - $.prefix missing required value
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
自定义预设(`codebuddy-first`、`cordis-agy`)因仍使用旧版 `text:` 字段全部被拒。
|
|
486
|
+
|
|
487
|
+
### 修复
|
|
488
|
+
|
|
489
|
+
- **persona 配置结构迁移**:`preset/codebuddy-first/agent.cordis.yml` 的 persona 行改为新版 `prefix:` + `suffix:` 拆分,与官方 standard preset 写法完全一致:`prefix` 渲染为 `deployment:persona-prefix` 段落(必填),`suffix` 渲染为 `deployment:persona-suffix`(此处给 `Your working directory is {{cwd}}.`);两者都是 `{{…}}` 模板,渲染时严格解析。
|
|
490
|
+
- **防回归护栏**:`scripts/verify.mjs` 新增三条检查——persona 行必须使用 `prefix:`(0.1.3-alpha.2 起必填)、必须声明 `suffix:`、**禁止出现旧 `text:` 字段**(否则 `npm run check` / CI 直接失败)。全局目录(dsh-home)的迁移由部署侧完成并已核对无残留旧字段。
|
|
491
|
+
- **npm 发布能力**:去掉 `"private": true`,`files` 白名单补齐 `README*` 与 `LICENSE`,新增 `prepack` 钩子(发布前强制跑 verify + build 校验,保证发布内容与仓库一致且通过全部校验)。包名 `codebuddy-first-bridge` 在 npm registry 未被占用。
|
|
492
|
+
|
|
493
|
+
### 测试
|
|
494
|
+
|
|
495
|
+
- `npm run check` 全绿:版本三处同步(package.json / MCP VERSION / CHANGELOG 顶部)+ 新增 persona 结构护栏 + 全部 73 例测试通过。
|
|
496
|
+
|
|
497
|
+
## [1.1.5] - 2026-09-04
|
|
498
|
+
|
|
499
|
+
修复:① 状态灯在标准模式下**整个调用过程完全不出现**;② 状态输出里混入希腊字母 `Σ`。
|
|
500
|
+
|
|
501
|
+
### 修复
|
|
502
|
+
|
|
503
|
+
- **① 状态灯对标准模式完全失明(架构缺口)**:标准(非 codebuddy-first)模式下 codebuddy 经**全局 MCP 行**调用,而 MCP 服务器是**独立子进程** —— 它既没有 `ctx.emit`,也拿不到家级插件 `ctx.provide` 的 `codebuddyCollector` 服务,`createStatusEngine(null)` 更是直接把 publish 关掉了。结果家级插件从来收不到 MCP 路径的任何运行数据,标题栏状态灯在整个调用过程中不出现。
|
|
504
|
+
修复:新增 **文件通道**。MCP 每次状态变化把快照**原子写入**(临时文件 + rename,避免读到半截 JSON)`<dsh-home>/codebuddy-indicator-mcp.json`,家级插件在响应 `/codebuddy-indicator/status` 时读取合并。两端都只从自身模块位置推导 dsh-home,**不需要端口**。
|
|
505
|
+
为什么不用 HTTP 反推:`webServer.register` 不暴露端口(客户端能工作是因为同源相对 URL),子进程无从发现;且端口实测会变(49301 → 58199)。
|
|
506
|
+
- **② 活动明细永远为空(静默失败)**:修好通道后发现 `current`/`trail` 仍全空。根因是 `child.stdout` **未声明编码** —— `'data'` 事件派发的是 `Buffer`,而 `createLineStream.pushChunk` 只接受字符串(非字符串静默 `return`),于是 `engine.foldEvent` 从不触发。这个失败完全无声:`result` 事件是从累积的 `out` 字符串解析的,所以 tokens、session、状态全都正常,只有实时明细缺失。
|
|
507
|
+
修复:`child.stdout.setEncoding('utf8')`(stderr 同样处理)。用 `setEncoding` 而非 `String(d)`:后者会在多字节 UTF-8 字符跨 chunk 边界时产生乱码,`setEncoding` 由 Node 的 `StringDecoder` 正确处理半个字符。
|
|
508
|
+
- **过期保护**:快照带 `updatedAt` 与 `pid`;超过 90s 未更新且仍标记 running 的项目按「进程已死」降级(子进程可能被强杀而来不及写收尾快照),否则灯会永久转圈。读取端还按文件 mtime 去重,避免重复合并把过期数据一直刷新成「很新」而绕过过期判定。
|
|
509
|
+
- **③ 状态输出改为纯 ASCII**:`renderStatus` 此前用希腊字母 `Σ`(U+03A3)当合计记号,输出形如 `codebuddy status: failed | Σ 1 runs · 25268 tokens` —— 在中英文语境里都是异类字符。改为 `total 1 runs, 15 tokens`。(`·`、`×` 等中文排版合法符号保留。)
|
|
510
|
+
|
|
511
|
+
### 实测(DSH Desktop 0.3.14 / 真实 MCP 路径)
|
|
512
|
+
|
|
513
|
+
- 修复前:整段调用期间端点恒为 `projects: []`。
|
|
514
|
+
- 修复后:`state=running` 全程可见,活动明细逐步推进 —— 端点实测到 `cur=Bash#6`、`typing#0`,trail 由 1 增至 12,结束后转 `ok`。
|
|
515
|
+
|
|
516
|
+
### 测试
|
|
517
|
+
|
|
518
|
+
- 测试 68→73 例:快照载荷收窄与 JSON 无损往返、过期快照的 running 降级(含已结束项目不受影响、无 `cwd` 条目丢弃)、`createLineStream` 对非字符串 chunk 的丢弃契约与半行拼接、MCP 源码断言 `child.stdout.setEncoding('utf8')` 必须存在(静默失败模式,用源码契约钉住防回归)、状态输出不含希腊字母。
|
|
519
|
+
|
|
520
|
+
## [1.1.4] - 2026-09-04
|
|
521
|
+
|
|
522
|
+
修复:标准模式下调用不顺畅 —— CLI 瞬时错误既不重试也不给原因,调用方只能白耗回合靠猜。
|
|
523
|
+
|
|
524
|
+
### 背景(实际会话记录)
|
|
525
|
+
|
|
526
|
+
标准(非 codebuddy-first)模式下下发一个 FizzBuzz 冒烟测试任务,第一次 `codebuddy_run` 失败,工具**只回了一行**:
|
|
527
|
+
|
|
528
|
+
```
|
|
529
|
+
codebuddy FAILED [status=ERROR_DURING_EXECUTION mode=bypassPermissions session=1f70715d… tokens=25268 29.154s]
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
没有原因、没有指引。调用方于是白耗一次 `codebuddy_status`(同样只有一行状态),再靠**猜**显式指定 `model=glm-5.3` 才成功。复现验证:同一任务、同一默认模型(`hy4-preview`)重跑 39s 直接成功 —— 说明 `ERROR_DURING_EXECUTION` 是 **CLI/服务端瞬时故障**,不是默认模型坏了、也不是任务本身有问题。
|
|
533
|
+
|
|
534
|
+
### 修复
|
|
535
|
+
|
|
536
|
+
- **瞬时错误自动重试一次**:新增 `isTransientCliError()` 识别 CLI 自报的 `error_during_execution`,preset 与 MCP 两条路径都会静默重试一次后再交还结果(不打断用户)。与限流/网络类失败明确分流:后者可能是额度耗尽,重试纯烧钱,仍走原有「问用户」弹窗;瞬时错误则重试一次大概率就过。续接类调用(`--resume` / `--continue`)不自动重试,避免会话状态已被前一次改动。
|
|
537
|
+
- **失败必带可行动指引**:新增 `failureHint()`,失败结果不再只有一行 head。瞬时错误明确告知「直接重试同一请求通常即可通过,不要据此认为任务有问题」;已自动重试过则改口径提示换 `model` 或改用原生工具;`PARSE_ERROR` 提示输出被截断 / 进程被中断。
|
|
538
|
+
- **结果记录实际使用的模型**:`buildResult()` 从 result 事件的 `modelUsage` 提取模型名(只取键名字符串,不把其下对象带进结果,保持通道可无损 JSON 化),head 里输出 `model=…`;自动重试过的结果额外标 `retried=1`。此前结果完全不含模型信息,排查「默认模型是否不稳」只能靠猜着换 `model` 试 —— 用户那次正是这样才蒙对。
|
|
539
|
+
|
|
540
|
+
修复后同一失败形态的输出:
|
|
541
|
+
|
|
542
|
+
```
|
|
543
|
+
codebuddy FAILED [status=ERROR_DURING_EXECUTION mode=bypassPermissions model=hy4-preview retried=1 session=1f70715d… tokens=25268 29.154s]
|
|
544
|
+
|
|
545
|
+
[诊断] codebuddy CLI 侧瞬时错误(error_during_execution,CLI 未给出原因),已自动重试 1 次仍失败。可换 model 再试一次;若仍失败请改用原生工具完成,或告知用户。
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### 测试
|
|
549
|
+
|
|
550
|
+
- 测试 66→68 例:瞬时错误识别与限流优先级(`ERROR_DURING_EXECUTION` + 429 判为限流,不走静默重试)、其他失败态不误判、三类指引文案、`modelUsage` 提取与 JSON 可序列化、head 的 `model=` / `retried=1` 输出、无 `modelUsage` 时不影响渲染。
|
|
551
|
+
|
|
552
|
+
## [1.1.3] - 2026-09-03
|
|
553
|
+
|
|
554
|
+
修复:① 计划模式下 codebuddy 的 Bash 被门禁拦死(「无交互模式下未获授权」);② 状态灯的会话判定改用自有权威通道,不再随 DSH 客户端 API 漂移。
|
|
555
|
+
|
|
556
|
+
### 修复
|
|
557
|
+
|
|
558
|
+
- **① 计划模式 Bash 门禁(新发现)**:DSH 处于计划模式时,preset 把 `mode=auto` 映射成 `--permission-mode plan`。CLI 在 `-p` 非交互 + plan 下**默认拒绝 Bash**(该档需交互授权,非交互下无人可授),codebuddy 于是报「**Bash 工具在无交互模式下未获授权(被拒绝),所以我改用 PowerShell 执行了同一条命令**」——同样是 shell,却因门禁不一致白耗回合,有时干脆放弃调查。修复:plan 模式额外传 `--allowedTools Bash` **预批**只读 shell。实测确认:Bash 恢复可用(`tool_use` 出现且命令真跑),**写入仍被 plan 模式独立禁止**(预批后 codebuddy 仍拒绝创建文件并说明「该约束优先级高于本次请求」),`Read`/`Grep` 等工具不受影响(`--allowedTools` 是预批而非排他白名单)。`bypassPermissions` 模式本不受门禁影响,不加白名单。
|
|
559
|
+
- **② 状态灯会话判定改为 host 侧实时枚举**:v1.1.2 靠读 DSH 客户端会话摘要的 `agentPreset`(0.3.14 起在 `projectionValues` 里)判断「本会话是否 codebuddy-first」。但**默认会话本就没有这个字段** → 判定「未知」→ 回退全局租约 → 普通会话仍可能亮灯;且该字段位置随 DSH 版本漂移(0.3.14 刚移过一次)。修复:家级插件**自己在 host 侧算**——`agents.list()` 遍历活着的 agent,用 `agentPresets.composedPreset(agent.ctx)` 读它实际组合的 preset id,端点新增 `presetSessions` 名单(每次请求现算,**对已经开着的会话立即生效**,无需重开)。客户端只需判断「我的 sessionId 在不在名单里」。
|
|
560
|
+
- **判定逻辑设两条独立通道且「任一肯定即肯定」**:host 名单(权威)与 DSH 客户端摘要通道并行,任一给出肯定即显示;都不肯定时才让名单做否定;两者皆无结论则回退全局租约。这不是冗余而是**安全阀**:万一两端 `sessionId` 取法失配,结果是「灯不亮」而不是「永久不亮」——若让名单单方面否定,一旦失配就比原缺陷更糟。
|
|
561
|
+
- **兜底上报通道**:preset 仍在 `codebuddy/mode` 事件里带自己的 sessionId(apply 阶段试 `agents.currentInitiator()`,拿不到则在第一次工具调用时从 `exec.agent` 补记),host 按会话记租约并与实时枚举取并集;实时枚举不可用时(服务缺失或 DSH 内部 API 变动)仍能工作。preset 卸载时主动发 `active:false` + sessionId,该会话立刻熄灯,不必等 75s;最后一个会话离场时顺带清全局租约,让仍读 `presetActive` 的旧客户端也立即熄灭。
|
|
562
|
+
- 端点契约扩展为 `{ state, running, projects[], presetActive, presetSessions[], lastModeAt }`(新增字段向后兼容)。会话名单上限 64,超出丢最早到期。
|
|
563
|
+
|
|
564
|
+
### 测试
|
|
565
|
+
|
|
566
|
+
- 测试 58→66 例:实时枚举为权威来源(无需任何上报即产出名单、会话关闭立即离场)、双源取并集且去重、枚举器抛错时安全降级到上报租约、按会话租约(多会话共存 / 单会话到期离场)、带 `sessionId` 的主动下线(只熄该会话 / 最后一个离场清全局)、旧版 preset 无 `sessionId` 的全局语义、名单容量上限、`apply()` 端到端(枚举出的 codebuddy-first 会话 ∪ 上报会话经路由送达,普通会话不在名单),以及 plan 模式预批 Bash 的 argv 契约。
|
|
567
|
+
|
|
568
|
+
## [1.1.2] - 2026-09-03
|
|
569
|
+
|
|
570
|
+
适配:**DSH Desktop 0.3.14 / @deepseek-ai/dsh 0.1.2-alpha.5**(本次 DSH 更新带来的客户端 API 变更修复 + 全线 DSH 版本适配标注)。
|
|
571
|
+
|
|
572
|
+
### 适配
|
|
573
|
+
|
|
574
|
+
- **背景**:DSH Desktop 0.3.12 起插件体系重构(插件隔离、profiles bundles 化、客户端模块系统重写)。0.3.14 / dsh 0.1.2-alpha.5 实测发现 v1.1.1 的「会话级就绪灯」判定失效——客户端会话摘要里的 `agentPreset` 字段已移入 `projectionValues` 投影值,且槽位 `inject` 的调用契约从 `inject(sessionId)` 变为零参(会话身份改由框架标准 props 提供),导致 v1.1.1 的读取永远 UNKNOWN、退回全局租约 → 空闲 codebuddy-first 标签页开着时其他会话又出现「CB 就绪」灯(v1.1.1 修复的回归)。
|
|
575
|
+
- **修复(双通道,跨版本兼容)**:
|
|
576
|
+
- 优先走 **框架标准 props**(DSH ≥ 0.3.14):会话作用域槽位向条目组件注入 `sessionId` 与 `useSessions` 选择器钩子,读 `byId[sessionId].projectionValues.agentPreset`;
|
|
577
|
+
- 回退走 **旧式注入**(更早版本):`inject(sessionId)` 收到会话 id(改名 `injectedSessionId` 避免与标准 props 冲突)+ `sessions` 服务的 `list` 快照;
|
|
578
|
+
- 两条通道的读取函数同时认新旧两种摘要形状(`projectionValues.agentPreset` / 顶层 `agentPreset`);都不可用时仍回退端点全局心跳租约。
|
|
579
|
+
- **`dsh.compat` 元数据**:家级插件 package.json 声明 `desktop: ">=0.3.4"`、`backend: ">=0.1.2-alpha.4"`、`verified: "DSH Desktop 0.3.5 & 0.3.14 / @deepseek-ai/dsh 0.1.2-alpha.5"`(跟随 dsh-model-status 的家级插件约定)。
|
|
580
|
+
- **版本适配标注**:README 中英文版版本表新增「适配 DSH」列;历史 Release 备注补标各自适配的 DSH 版本(v1.0.0 / v1.1.0 → DSH Desktop 0.3.5;v1.1.1 → 0.3.5 开发、0.3.14 实测兼容)。
|
|
581
|
+
- 文档:`client-entry.mjs` 头注释更新为 0.3.14 的新扫描机制说明(client-modules 现扫描所有 Loader 行,裸名行仅为旧版兼容保留)。
|
|
582
|
+
|
|
583
|
+
### 实测(DSH Desktop 0.3.14 / dsh 0.1.2-alpha.5)
|
|
584
|
+
|
|
585
|
+
- host 半:`GET /codebuddy-indicator/status` 正常返回,preset 30s 心跳租约续期(`lastModeAt` 持续刷新)。
|
|
586
|
+
- 客户端半:新 client-modules 花名册(combo 路由 `/plugins/??<id>/client.js&rev=<内容指纹>`)逐字节命中(sha1 复算 rev 后 HTTP 200,正文与部署文件一致);HMR 内容指纹重建生效。
|
|
587
|
+
- preset 半:codebuddy-first preset 在新进程正常 apply 并心跳。
|
|
588
|
+
- 浏览器侧渲染需刷新页面(或等待客户端 HMR 热替换)后确认。
|
|
589
|
+
|
|
590
|
+
## [1.1.1] - 2026-09-02
|
|
591
|
+
|
|
592
|
+
修复:非 codebuddy-first 会话里状态灯常驻不灭(两层原因,都修)。
|
|
593
|
+
|
|
594
|
+
### 修复
|
|
595
|
+
|
|
596
|
+
- **① 家级插件 host 半 `presetActive` 粘滞**:`codebuddy/mode {active:true}` 事件把 `presetActive` 永久置 true——既无 TTL,preset 会话关闭时也无 `active:false`。DSH 进程启动后只要有任何会话加载过一次 codebuddy-first preset,之后即使再无 codebuddy-first 会话,所有会话(含普通模式)的标题栏都会常驻灰灯。修复:改为**心跳租约**——preset 每 30s 宣告一次续期,TTL 75s(≈两拍容差,容忍事件循环抖动);最后一个 codebuddy-first 会话关闭后 ≤75s 自动熄灭;收到 `active:false` 立即熄灭。host 半状态逻辑抽取为可独立测试的 `createIndicatorState()`(注入时钟 + TTL),端点新增 `lastModeAt` 诊断字段。
|
|
597
|
+
- **② 「CB 就绪」空转灯是全局的**:只要任何一个标签页开着 codebuddy-first 会话(哪怕空闲),其余所有会话(含普通模式)都会显示「CB 就绪」。修复:**会话级判定**——客户端经 slot `inject(sessionId)` 拿到本会话 id,从客户端 `sessions.list` 快照读取本会话的 `agentPreset`(preset id = 目录名 `codebuddy-first`)本地判定;空转灯只在该会话本身是 codebuddy-first 时显示,**活动灯(项目 pill)保持全局显示**。快照/服务不可用(旧版 DSH)时回退到全局租约判定。
|
|
598
|
+
- 家级插件 host 半首获测试覆盖:`test/indicator.test.mjs` 9 例(初始态、租约到期熄灭、心跳续期、`active:false`、ok 保持窗口 8s/10min、running/fallback 不受窗口影响、容量淘汰 MRU、无损 JSON、`apply()` 装配 + webServer 路由)。测试 49→58 例。
|
|
599
|
+
|
|
600
|
+
### 验证
|
|
601
|
+
|
|
602
|
+
- `npm test`:58/58 通过。
|
|
603
|
+
- 实机(host 半热加载部署,cordis.patch.yml `?v=3`):`lastModeAt` 采样证实存在开着的 codebuddy-first 会话每 30s 心跳续期(相隔恰 30014ms);新实例装载后无心跳时 `presetActive` 立即为 false。
|
|
604
|
+
- 客户端半:浏览器花名册已供应新 bundle(含 per-session 判定);本会话(非 codebuddy-first)刷新页面后空转灯不再渲染,即使另一标签页的 codebuddy-first 心跳仍在续期。
|
|
605
|
+
|
|
606
|
+
## [1.1.0] - 2026-09-02
|
|
607
|
+
|
|
608
|
+
双后端:`backend="workbuddy"` 把任务派发给 **腾讯 WorkBuddy**(CodeBuddy 的同引擎「孪生兄弟」,主打办公场景)。
|
|
609
|
+
|
|
610
|
+
### 背景
|
|
611
|
+
|
|
612
|
+
WorkBuddy 桌面版(`C:\Program Files\WorkBuddy`)内置与 codebuddy-code **同一引擎、同一 CLI、同一 stream-json 协议**的命令行(`resources\app.asar.unpacked\cli\bin\codebuddy`,`@genie/agent-cli`),差异只在产品面:办公工具集(腾讯文档/PPT/表格、知识库、图片视频生成、微信/企微回复),登录态与桌面应用共享。实测 `node <wb-bin> -p ... --output-format stream-json --permission-mode bypassPermissions` 输出事件逐字段兼容。
|
|
613
|
+
|
|
614
|
+
### 新增
|
|
615
|
+
|
|
616
|
+
- **`backend` 参数**(`codebuddy_run` / `codebuddy_continue`,三形态齐备):`'codebuddy'`(默认,编码场景)或 `'workbuddy'`(办公场景)。preset/dynamic 经 `WORKBUDDY_BIN` 环境变量(preset)或内置路径(dynamic 沙箱无 env)解析 WorkBuddy CLI;MCP 经 `WORKBUDDY_BIN`(未装 WorkBuddy 时返回带安装指引的 `CODEBUDDY_UNAVAILABLE`,而非裸 ENOENT)。
|
|
617
|
+
- **会话感知后端路由**:codebuddy 与 workbuddy 各自维护独立会话存储(`~/.codebuddy` 与 `~/.workbuddy`),同一 sessionId 只在其中一个后端有效。引擎以 `sessions[sessionId] = {cwd, backend}` 表一次解析出续接所需的工作目录与后端:`codebuddy_continue` 不带 backend 时按 sessionId 自动路由回所属 CLI;显式 `backend` 参数始终最优先。cwd 解析按会话查表而非项目级 `lastSessionId`(后者只记最后一个会话,同项目混跑多会话时会 miss)。
|
|
618
|
+
- **状态呈现**:结果对象新增 `backend` 字段(渲染头部 `workbuddy OK [...]`);`codebuddy_status` 项目行带 `[workbuddy]` 标记;回退弹窗文案按后端命名。
|
|
619
|
+
- **策略段更新**:office 任务(文档/幻灯/表格、知识库、图片视频生成、微信企微回复)优先 `backend="workbuddy"` 派发。
|
|
620
|
+
|
|
621
|
+
### 验证
|
|
622
|
+
|
|
623
|
+
- `npm test`:49/49 通过(新增 resolveTarget 后端路由、buildResult/fallbackResult/renderResult backend 贯通、dynamic 沙箱 backend 派发 + 自动路由、MCP workbuddy 夹具真跑 + 未装 WorkBuddy 报错文案)。
|
|
624
|
+
- 真实端到端(MCP + 真实 WorkBuddy CLI):`backend="workbuddy"` 真跑 SUCCESS + 同会话续接自动路由回 workbuddy;codebuddy 默认路径回归通过。
|
|
625
|
+
|
|
626
|
+
## [1.0.0] - 2026-09-02
|
|
627
|
+
|
|
628
|
+
首个正式版本:**codebuddy 优先派发 + DSH 全程掌控 + 受限回退**的完整闭环,外部代码评审驱动的可靠性基线、共享核心架构与测试套件。自 [agy-first-bridge](https://github.com/new-256/agy-first-bridge) v1.5.11 移植并完成 codebuddy 适配(`--permission-mode bypassPermissions`、`--resume`/`--continue` 续接、Claude Code 风格 stream-json 事件解析、effort 扩为 minimal/max 两端、新增 `maxTurns`、node+bin 可执行解析回退;codebuddy 无套餐额度 API,移除 agy 的 quota 体系,以 token 计量作替代观察)。
|
|
629
|
+
|
|
630
|
+
### 功能
|
|
631
|
+
|
|
632
|
+
- **三模型工具**:`codebuddy_run`(`mode` / `model` / `effort` / `maxTurns` / `cwd` / `addDirs` / `timeoutSec` / `background`)、`codebuddy_continue`(`sessionId` 或 `latest: true` 续接)、`codebuddy_status`(实时观测 + 按项目用量统计)。
|
|
633
|
+
- **codebuddy 优先策略**注入 systemPrompt(`codebuddy:policy` 段):所有模式下优先把实际工作派发给 codebuddy,原生工具只做快速只读查询与最终验证。
|
|
634
|
+
- **DSH 全程掌控**:非交互运行、权限全自动批准(codebuddy 从不弹提示);模式/模型/effort/工作目录/超时/后台/取消均由 DSH 决定(`exec.signal` + `handle.terminate()` 可中止)。
|
|
635
|
+
- **受限回退弹窗**:失败命中限流/网络/认证特征时 `userQuestions.ask()` 三选一(回退 DSH 本地 API 配置 / 重试 / 取消),最多 2 次尝试;子代理无应答者与后台任务失败不弹窗。
|
|
636
|
+
- **实时状态灯**:家级插件 `home-plugin/codebuddy-indicator/`(随软件启动、所有会话自动显示、无需审批;按项目一盏灯,点击弹出实时活动面板)+ 动态形态经 `codebuddyCollector` 推入同一张表。
|
|
637
|
+
- **按项目 token 用量统计**(`runs` / `totalTokens`,三形态一致):codebuddy 无套餐额度 API,以 token 计量作替代观察。
|
|
638
|
+
- **零依赖 MCP 服务器**:三个工具经 stdio JSON-RPC 暴露给任何 MCP 宿主(Claude Code / Codex / Cherry Studio…)自动发现;`--check` 自检;**安全护栏 `CODEBUDDY_MCP_ALLOWED_ROOTS`**(`;`/`,` 分隔的 cwd 白名单,越界返回 `CWD_BLOCKED`)。
|
|
639
|
+
- **文档与 CI**:中英双语 README / INSTALL / ARCHITECTURE / FALLBACK-AND-INDICATOR、MCP-POLICY、GitHub Actions(语法矩阵 + YAML 结构断言 + 测试 job)。
|
|
640
|
+
|
|
641
|
+
### 可靠性基线(全部由故障注入回归测试锁定)
|
|
642
|
+
|
|
643
|
+
- `codebuddy_status` 在任何失败路径下可用:全局状态判定仅依据最近 `lastStatus`(`SUCCESS → ok`,其余 `→ failed`),非 SUCCESS 失败后状态工具与家级灯数据通道不被异常打断。
|
|
644
|
+
- 会话感知 cwd 回落:codebuddy 会话按项目目录归档,续接未显式给 `cwd` 时回落到该 session 所在项目的 cwd(否则换目录报 "No conversation found"),三形态共用同一实现。
|
|
645
|
+
- 结果对象全程无损 JSON(轨迹折叠 `args` 存 `null` 而非 `undefined`)。
|
|
646
|
+
- 回退弹窗单次三选一;「重试」仅在还有重试次数时提供。
|
|
647
|
+
- 后台任务与前台一致的挂起守卫(`timeoutSec+60s` 强杀 + `HUNG_TIMEOUT` 标注);`jobs.start` 失败立即返回 `JOB_START_ERROR`,绝不静默回落前台重跑。
|
|
648
|
+
- 限流/网络判定只匹配 `stderr + status`(不匹配回复全文),数字码词边界(`"1500"` 不命中 `500`)。
|
|
649
|
+
- 半行安全的实时流解析:跨 stdout chunk 的 NDJSON 行不丢失(`createLineStream` 残余缓冲 + 结束冲刷)。
|
|
650
|
+
- MCP spawn ENOENT 单次结算(`settled` 标志);stdin EOF 请求护栏。
|
|
651
|
+
- 工具入参对象不可扩展(冻结)场景下可执行解析回退不误报(`_binPath` 存局部变量)。
|
|
652
|
+
|
|
653
|
+
### 架构:共享核心(单一事实来源 + 生成派生产物 + 同步锁定)
|
|
654
|
+
|
|
655
|
+
- **`core/codebuddy-core.mjs`**:纯函数(`parseCodebuddyJson` / `buildResult` / `buildArgv` / `isLimited` / `summarizeArgs` / `clampInt` / `shortLabel` / `fallbackResult`)、状态引擎(`createStatusEngine`:按项目聚合 + MRU 淘汰 + 会话感知路由 + 用量累计)、半行流(`createLineStream`)、执行编排(`createRunner`:runSync / 挂起守卫 / 弹窗回退 / 后台派发 / 限流循环)与共享文案(`POLICY_TEXT`)。
|
|
656
|
+
- 三形态只剩宿主适配层:**preset**(ctx.tools 注册 + `ctx.emit` 事件 + `process.env` 解析);**dynamic**(`scripts/build.mjs` 文本注入生成 `host.js`——动态沙箱禁止 import;`harness.registerTool` + collector 推送);**MCP**(stdio JSON-RPC + 白名单护栏 + 文本渲染)。复制式多形态维护是字段级漂移的温床,共享核心从结构上消除该类缺陷。
|
|
657
|
+
- `scripts/build.mjs` 生成两个派生产物(`dynamic/host.js` + preset 侧 `codebuddy-core.mjs` 副本),`test/build-sync.test.mjs` 重新生成并比对——改 core 忘记重新生成时 CI 失败。
|
|
658
|
+
|
|
659
|
+
### 测试(44 例)
|
|
660
|
+
|
|
661
|
+
`test/`(node:test,零依赖):纯函数/状态引擎/行流 22 例;dynamic 沙箱模拟 8 例(按真实求值方式 `new Function('harness', body)` 装载生成产物,故障注入覆盖上述回归位);preset 适配层 3 例(真实 ESM 导入 + `process.env` 解析形态);MCP stdio 端到端 6 例(真实子进程 + 伪 codebuddy 夹具);构建同步锁定 3 例。CI:语法矩阵(Node 18/20/22)+ 测试 job + `scripts/verify.mjs`(`package.json` ↔ MCP `VERSION` ↔ CHANGELOG 版本三处锁死 + preset YAML 结构断言)。
|
|
662
|
+
|
|
663
|
+
### 验证
|
|
664
|
+
|
|
665
|
+
- `npm test`:44/44 通过。
|
|
666
|
+
- 真实端到端(MCP server + 真实 codebuddy CLI):指定 `model: hy3` 真跑 SUCCESS、同会话续接 SUCCESS;用量累计算术自洽(25157 + 50347 = 75504 tokens)。
|
|
667
|
+
- 动态形态真实运行:工具注册 / 回退弹窗 / 后台 jobId 链路 / 运行中实时灯数据流实测通过。
|
|
668
|
+
- 安装同步:preset 目录 4 文件 SHA-256 与源码一致;MCP `--check` 自检通过。
|