dsh-connect-agnes-token-plan 0.6.0 → 0.8.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/CHANGELOG.md +93 -7
- package/README.md +11 -9
- package/THIRD_PARTY_NOTICES.md +21 -1
- package/client.js +462 -173
- package/lib/{agnescode-llm-adapter-Darpc8DP.js → agnescode-llm-adapter-CTaTAHvp.js} +31 -14
- package/lib/agnescode-models-eTXfaiwF.js +1567 -0
- package/lib/index.js +3354 -3179
- package/lib/{llm-adapter-DjSVmJNx.js → llm-adapter-BgxoDG2y.js} +3 -4
- package/lib/{llm-error-fix-DQUng8AL.js → llm-error-fix-cwd4vn26.js} +28 -9
- package/lib/{llm-models-BoU1LWmL.js → llm-models-CvWAbIG8.js} +656 -94
- package/locale/en.json +5 -0
- package/locale/zh.json +6 -0
- package/package.json +8 -5
- package/lib/agnescode-models-C8Gd08aG.js +0 -713
- package/lib/host-config-BNGgm_j7.js +0 -456
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,93 @@
|
|
|
2
2
|
|
|
3
3
|
本文件只记**公开行为变化**(新增能力、破坏性改动、重要修复)。实现细节、重构与测试加固请直接看 `git log`。
|
|
4
4
|
|
|
5
|
+
## [0.8.0] — 2026-10-02
|
|
6
|
+
|
|
7
|
+
### 修复:AgnesCode provider 必须进 tab 才启用(mount seed 竞态)
|
|
8
|
+
|
|
9
|
+
- **现象**:插件更新后重启 DSH,AgnesCode provider 不注册;凭据没变、桌面 App 没开过,但只要**进一次插件页的 AgnesCode tab** 就自动完成启用 + 热重载。
|
|
10
|
+
- **根因**:mount seed 只跑一次。它需要两个可能**晚于本插件**注册的服务——读凭据的 `credentials` 服务、注册用的 `llm` 服务。Host 启动早期两者未就位时,seed 撞上 `not_configured`(凭据读不到)或 `no llm registration service`,随即静默放弃,没有重试;唯一能救它的是 tab GET 的自愈,而 GET 只在打开 tab 时才发——于是「进 tab 才启用」。
|
|
11
|
+
- **修法**(对齐小浣熊线 `seedRaccoonOnMount` 的既有做法):
|
|
12
|
+
- `util.ts` 移植 `retryBounded`(线性退避)。
|
|
13
|
+
- `agnescode-lifecycle.ts` 的 mount seed 改为有界重试(6 次 × 300ms,`AGNESCODE_SEED_ATTEMPTS`/`AGNESCODE_SEED_DELAY_MS`):每轮重读开关 + 凭据 + 注册状态,`registered===true` 或 `isDisposed()` 即停;开关每轮重读,并发关掉也被尊重。
|
|
14
|
+
- `routes/agnescode.ts` 的 GET 自愈从「只修 `not_configured`」放宽为「开关 on + 已关联 + 任何未注册错误」——覆盖 seed 窗口耗尽但 llm 仍未就位的残局。
|
|
15
|
+
- `lifecycle.ts` 的 draw/video 工具读 `tools` 服务改为 `resolveServiceWithRetry`(与工具线同款防护:只重试读、绝不重试注册)。
|
|
16
|
+
- 影响面:`src/host/{util, agnescode-lifecycle, lifecycle, routes/agnescode}.ts`、`test/agnescode.test.mjs`。
|
|
17
|
+
|
|
18
|
+
### 破坏性改动:AgnesCode provider id 改为裸产品名 `agnescode`
|
|
19
|
+
|
|
20
|
+
- **改动**:provider id `agnes-agnescode` → `agnescode`,显示名 `Agnes AgnesCode` → `AgnesCode`。
|
|
21
|
+
- **为什么**:`agnes-agnescode` 读起来是结巴——供应商前缀 `agnes-` 重复了产品名里本就有的 "Agnes"(显示名 `Agnes AgnesCode` 同样)。兄弟插件 `dsh-connect-workbuddy` 的 id 就是裸产品名(`workbuddy` / `workbuddy-global`),本线对齐这个粒度。**撞名论证不依赖前缀**:裸 `agnescode` 与 `sensenova-*` 命名空间仍不相交,`dsh-connect-sensenova-token-plan` 的 `DUPLICATE_ADAPTER` 风险不变;`test/agnescode.test.mjs` 的钉字面量从「在 agnes- 命名空间」改为「是裸产品名、既非 sensenova- 也非 agnes-agnescode」。
|
|
22
|
+
- **迁移**:**不需要重新勾选**——开关文件 `agnescode-provider.json`、模型勾选 `agnescode-models.json`、凭据引用 `AGNESCODE_CREDENTIAL` 的名称都没变,只有注册用的 id 变。Host 重启后 mount seed 会在新 id 下重新注册(上一节修好的有界重试正是这条路径的兜底),旧 id 的注册随进程结束自然消失。(历史上 `sensenova-agnescode` → `agnes-agnescode` 那次需要重勾,是因为当时 seed 是单次、可能撞上服务晚到;这次 seed 已收敛,无此要求。)
|
|
23
|
+
- **影响面**:`src/host/{agnescode-models, agnescode-llm-adapter}.ts`、`test/agnescode.test.mjs`、`README.md`、`AGENTS.md`。
|
|
24
|
+
|
|
25
|
+
## [0.7.0] — 2026-10-02
|
|
26
|
+
|
|
27
|
+
**AgnesCode 面板从「只读花名册」升级为「可勾选的模型推送给」**:每个模型一行勾选框,决定哪些模型注册进 DSH 模型列表,改动即时生效;配套搜索 + 全部勾选/取消 + 已勾选计数,与 Token Plan 那套同一形状。勾选存在独立的 profile 级状态文件,**空 = 不筛选 = 全推**,所以没勾过的安装行为完全不变。面板信息架构另有一刀(额度 / 累计 / 套餐拆成三个 section)。另修掉一个「删注释时误删三元条件行、构建失败、插件无法加载」的问题。
|
|
28
|
+
|
|
29
|
+
### AgnesCode:模型勾选决定哪些模型推送进 DSH
|
|
30
|
+
|
|
31
|
+
- **能力**:AgnesCode tab 的模型花名册每行加勾选框(未勾选行降低透明度),决定哪些模型注册进 DSH 模型列表;保存后**立刻**重发一次过滤后的 roster,不必等下一次轮询。
|
|
32
|
+
- **完整版交互**:搜索框(`autocomplete="off"`,避免浏览器密码管理器把控制台账号填进这个 tab 唯一的文本输入)+ 全部勾选/全部取消(作用于可见行)+ 已勾选/共 N 计数;搜索只过滤「渲染什么」,不改变「保存什么」。
|
|
33
|
+
- **持久化**:新增 profile 级状态文件 `agnescode-models.json`(空列表 = 不筛选 = 全推,与 Token Plan 侧同一约定);`/agnescode` 路由新增 `saveModels` 动作。
|
|
34
|
+
- **隔离**:独立的 store 与过滤点(`agnescode-models-store.ts` + `filterAgnescodeRows`),只在发布前裁剪 roster,不与 Token Plan 的 `enabledModelIds` 或 publisher 状态串味。
|
|
35
|
+
- 影响面:`src/host/{agnescode-models-store, agnescode-models, agnescode-lifecycle, index, routes/agnescode, types}.ts`、`src/client/{agnescode-tab, i18n}.ts`、`test/agnescode.test.mjs`。
|
|
36
|
+
|
|
37
|
+
### 修复:删除注释时误删三元条件行,导致构建失败、插件无法加载
|
|
38
|
+
|
|
39
|
+
- **现象**:插件报 `Cannot find module 'lib/agnescode-llm-adapter-DkN4N4JD.js'`,Host 起不来。
|
|
40
|
+
- **根因**:一个临时脚本按正则删「冗余注释」,误删了 `src/client/account-form.ts` 里三元表达式的条件行(`cooling`),rolldown 解析失败、整次构建中断,`lib/` 从未重建——而 `index.js` 还引用着旧的 chunk。
|
|
41
|
+
- **修法**:补回条件行;修复另两处被删掉句子主语/替换成重复 `@param` 的注释;仓库换行统一回 LF;删除临时脚本。
|
|
42
|
+
|
|
43
|
+
### 面板信息架构:额度 / 累计 / 套餐拆成三个 section
|
|
44
|
+
|
|
45
|
+
- **问题**:`积分额度` tab 原来只有两个 section——「额度上限」里塞了当前套餐 + 四个窗口池 + 账号累计用量,「用量统计(近 30 天)」里只有柱图;套餐目录(catalogue)折叠在 PlanCard 内部。这导致三件彼此无关的事(我的窗口额度 / 我的历史累计 / 平台卖的所有套餐)共享同一个 section 标题「额度上限」,名字只覆盖其中一件;账号累计(无上限)挤在「额度上限」section 里,而真正的用量数据(柱图)在另一个 section,读者要把两个 section 的数字相减才能算「剩余」——这个减法没有意义(窗口周期 ≠ 账号累计周期)。
|
|
46
|
+
- **修法**:拆成三个 section:
|
|
47
|
+
- **「我的额度」**(`section.quota`):当前套餐身份 + 四个窗口池 + vision 模型行。只讲「我当前能用多少」。
|
|
48
|
+
- **「套餐对比({count} 档)」**(`section.catalogue`):`CatalogueCard`(从 `PlanCard` 剥离),独立 section,默认折叠。未登录时它是唯一的额度信息源;已登录时它回答「升级值不值」,不再与读者自己的数字挤在同一张卡里读起来像推销。
|
|
49
|
+
- **「我的用量」**(`section.usage`):`windowNote`(「不能相减」的诚实声明)+ 账号累计用量 + 近 N 天柱图。窗口在上一 section,累计在本 section,声明放在两者之间。
|
|
50
|
+
- **`windowNote` 跟着累计走**:「下面的上限 / 下方的账号累计」这段诚实声明原来夹在 PlanCard 与 UsageTotals 之间(同一个 section 内),现在随累计移入「我的用量」section 开头——读者进入这个 section 先看到声明、再看到累计数字。
|
|
51
|
+
- **`section.usage` 不再含 `{days}` 占位符**:柱图的日期范围由 x 轴自带,section 标题「我的用量」是稳定标签;「近 {days} 天」作为 chart 上方的小标题(`usage.period`),与累计用量分开。
|
|
52
|
+
- **`PlanCard` 不再吃 `quota.plans`**:它的空态判定从「plan null + windows 空 + catalogue 空」收窄为「plan null + windows 空」;`CatalogueCard` 在 `plans` 为空时返回 `null`,section 整块隐藏(不画空卡)。
|
|
53
|
+
- 影响面:`src/client/{i18n, cards, index, panel-page}.ts`、`test/{render.test.mjs, panel-render.js}`;`quota.catalogue` 键退役(`section.catalogue` 接管,带 count),`usage.period` 键新增。
|
|
54
|
+
|
|
55
|
+
### AgnesCode:存储格式漂移哨子——桌面端升级不再冒充「文件不存在」
|
|
56
|
+
|
|
57
|
+
- **问题**:AgnesCode 线吃的是从桌面 App 逆推的私有格式。App 升级改了会话文件形状(如 `code-auth-session.cn.v2`)时,严格模式全 miss,面板只给出与「没登录」**同款**的「文件不存在」档;而此前采集的 JWT 还能用约 28 天——没人会注意,直到凭据死掉、重登重采也无济于事的那天。
|
|
58
|
+
- **修法**:检测步进新增第 9 档 `format_drift`——App 目录存在、里面有「像会话文件族」却不认识形状的文件时,第一档就说**「存储格式已变,升级本插件后再点检测」**,不再把人往「重新登录」上引。同时 `doctor` 新增机器级**只读盘点**:`%APPDATA%/AgnesCode` 的会话文件名清单与漂移点名——「没装 App / 装了没登录 / 登录了但格式变了」在命令行即可分辨;盘点只看文件名,**永不读文件字节、永不碰解密密钥**。
|
|
59
|
+
- **诚实性**:有可读的 `.v1` 时漂移声明**不成立**(同目录的未知兄弟可能是 App 自留备份);平台没有已知 App 布局时如实报「未盘点」,不报零。
|
|
60
|
+
|
|
61
|
+
### 修复:插件卡在中文界面显示英文文案
|
|
62
|
+
|
|
63
|
+
- **现象**:Plugins 页卡片标题是裸包名、描述是一段英文——全程无报错(`docs/PITFALLS.md` §33)。
|
|
64
|
+
- **根因**:卡片文案由 Host 的 `readPluginMeta()` 读**包元数据**(`locale/*.json` 的 `meta.title`/`meta.description`),不经插件 bundle 渲染。本插件没有 `locale/` 目录、`exports` 也没有该资源子路径——解析抛 `ERR_PACKAGE_PATH_NOT_EXPORTED` 被读取端当「无元数据」吞掉,落回 `package.json.description` 的英文兜底(`displayName` 这条链路根本不读)。
|
|
65
|
+
- **修法**:新增 `locale/en.json` + `locale/zh.json`(标题「Agnes Token Plan 接入全家桶」与中文描述),`exports` 加 `./locale/*.json` 子路径,`files` 白名单加 `locale`(三者缺一即哑,见 PITFALLS §33);`package.test.mjs` 新增检查 7 把这条链钉死。
|
|
66
|
+
|
|
67
|
+
### 破坏性改动:AgnesCode provider id 改入 `agnes-` 命名空间(避免与兄弟插件撞名)
|
|
68
|
+
|
|
69
|
+
- **改动**:provider id `sensenova-agnescode` → `agnes-agnescode`,显示名 `SenseNova AgnesCode` → `Agnes AgnesCode`。
|
|
70
|
+
- **为什么**:兄弟插件 `dsh-connect-sensenova-token-plan` 注册 `sensenova-*` id;重复 id 会被 `registerAdapter` 以 `DUPLICATE_ADAPTER` 拒绝,其中一个 provider 会从选择器**静默消失**(`docs/ARCHITECTURE.md` §5)。本插件走 Agnes 体系,id 统一 `agnes-*`,与 `sensenova-*` 命名空间不相交,撞名不可能;`test/agnescode.test.mjs` 把 `agnes-agnescode` 字面量钉死,防止有人改回去。
|
|
71
|
+
- **对已有安装的影响**:曾启用 AgnesCode 提供方的安装需**重新勾选一次**(provider id 变了,旧注册不再认领)。凭据引用 `AGNESCODE_CREDENTIAL`、switch-store、publisher 全部不变,**无需重新采集登录态**。
|
|
72
|
+
- **一并**:`llm-error-fix.ts` 的 429 分诊注释把「商汤方言」定位改为「判据方言无关 + Agnes 未实测但有兜底」(判定逻辑未动——它本就只读 `type` 字段名与消息词,未硬编码商汤码值);`test/error-fix.test.mjs` 补一组「无结构化 `type` 的 Agnes 兜底」夹具。
|
|
73
|
+
|
|
74
|
+
### 修复:做过 profile 分段迁移的机器上,draw / video 开关重启后自己关掉
|
|
75
|
+
|
|
76
|
+
- **现象**:面板打开「出图」或「视频」开关后,**下一次 Host 启动它自己回到配置默认(关)**——无报错、无告警,`doctor` 也读不出异常。只在经历过 §23 profile 分段迁移的机器上出现,且**只有 draw / video 中招**,provider 与 AgnesCode 正常。
|
|
77
|
+
- **根因**:四个开关商店是逐字互抄的四份代码。§23 的「继承旧共享目录的值」回调在布尔-only 的两份里收到布尔、在带偏好的两份里收到 `{enabled, modelId}` 对象,而写回体照抄了布尔版——把整个对象塞进 `enabled` 字段。进程内的读缓存掩盖了它,所以只有重开 Host 从磁盘重读才腐烂(`docs/PITFALLS.md` §34)。
|
|
78
|
+
- **修法**:四个开关商店收敛到一个共用构造(`src/host/switch-store.ts`),各自只声明不同的事实(文件名 / 形状版本号 / 偏好 wire key / 报错措辞);`doctor` 的三份解析器改为复用商店自己的那份。新增 `test/switch-store.test.mjs` 对**四个商店跑同一组断言**(含「继承后重开仍读得到」),此类复制型漂移从此会红。
|
|
79
|
+
|
|
80
|
+
### doctor 新增一行:不带 Origin 的写请求留痕
|
|
81
|
+
|
|
82
|
+
- **改动**:`npm run doctor` 的报告多出一行 `admission: N state-changing request(s) admitted with no Origin (last: <方法> @ <时间>)`;`--json` 报告新增 `admission` 字段。没有记录过就不显示这一行。
|
|
83
|
+
- **为什么**:同源闸在请求未声明 `Origin` 时放行,这是**必须**的(浏览器的同站 GET 不发 `Origin`;跨站 POST 必发、发了就被比对拦掉),所以那条分支上过的只可能是非浏览器客户端。它本身不是漏洞,但此前完全不可见——`doctor` 给不出"有没有发生过"。
|
|
84
|
+
- **不是加固**:放行逻辑**一字未动**(`routes` 190 / `wiring` 44 / `doctor` 39 零回归)。记录只含次数、时间与方法名,**不含** Host / Origin / 路径 / 头值 / 凭据(`docs/PITFALLS.md` §35)。
|
|
85
|
+
|
|
86
|
+
### 可读性:11 处手抄的「面板值 > 配置默认」收敛到唯一裁决模块
|
|
87
|
+
|
|
88
|
+
- **现象**:「面板存过的值胜过补丁声明的默认」这一条开关优先级规则,被手抄在 11 处调用点,且有两种长得几乎一样、语义却不同的方言——有默认(`panel ?? settings.x === true`,用于 provider / draw / video)与无默认(`panel === true`,仅 AgnesCode:它根本没有配置默认,未设置必须落到 `off`)。两者靠肉眼分不出来。
|
|
89
|
+
- **风险(不仅有可读性)**:① 把无默认型误读成有默认型,会让 AgnesCode 在补丁某天多出一个默认值时自行注册起来;② `provider-publish.ts` 里 `panelValue ?? effectiveSettings.registerProvider === true` 实际按 `panelValue ?? (x === true)` 解析——结果正确但**读起来像** `(panelValue ?? x) === true`,诱导出错误编辑;③ `snapshot-aggregate.ts` 里「值」与「来源」各读一次开关,两次读取之间一翻(或第二次失败)就会输出 `true` 却标注来源为 `config`;④ 旧写法 `(store ? store.enabled() : null).catch(...)` 在 store 缺席时是对 `null` 调 `.catch`,抛 `TypeError` 而非回答 `null`,只是当前调用方都恰好传了 store 才没炸。
|
|
90
|
+
- **修法**:新增 `src/host/switch-precedence.ts`,三个函数(`resolveSwitchEnabled` / `resolveSwitchValue` / `readPanelValue`)承载全部判定,值与来源一起返回;11 处调用点改为调用它(AgnesCode 三处严格按「无配置默认」解析)。`readPanelValue` 安全接受缺席的 store(旧陷阱被消除)。新增 `test/switch-precedence.test.mjs`(23 条)钉住两种语义分界与上面四类缺陷,并带「接线钉」:任何文件仍自己拼装优先级、或 AgnesCode 三处传了配置默认,即红。重构前后 `routes` 190 / `provider` 204 / `agnescode` 119 / `doctor` 39 / `switch-store` 84 / `admission-audit` 27 逐项计数一致零漂移。
|
|
91
|
+
|
|
5
92
|
## [0.6.0] — 2026-10-01
|
|
6
93
|
|
|
7
94
|
**面板信息架构再收一刀**:顶栏从「页面标题栏」降格为「当前 tab 的状态与刷新出口」——撤销假的全局标题,「更新于」/令牌状态/刷新按 tab 归属;额度窗口卡片改以**百分比为主视**并按职责分池;三个 tab 补上常驻的官网入口。**AgnesCode 这条线修掉两个叠加的旧病**:GET 路由的 `lastHarvest` 落在暂时性死区,让「检测本机登录态」点了没反应;以及「开关先开、令牌后到」留下的 `not_configured` 被当作红色错误报警。推理侧把单次输出上限从兜底的 32768 提到实测平台上限 65536,契约基线 seed 一并退役、换真机全阶梯证据。
|
|
@@ -38,7 +125,7 @@
|
|
|
38
125
|
- 「接入 API」tab:同一份快照(它渲染的就是快照里的 `llm` 块),因此同样的「更新于」与刷新,但**不再挂令牌 chip**——那枚令牌是控制台凭据,这个 tab 用的是已保存的 API Key;
|
|
39
126
|
- 「AgnesCode」tab:它读自己的路由、按 60s 自己的节奏轮询,所以由该 tab **自己发布**「更新于」与刷新。此前顶栏在这一 tab 上引用的是快照的时间戳,刷新按钮也只重载快照——两者都指向**另一个 tab** 的数据。
|
|
40
127
|
- **顺带修掉一个看不见的失败**:AgnesCode tab 的路由读取失败时 `error` 只被 set、从不渲染,于是「Host 没回话」显示成「未关联——请先在桌面端登录」,把原因甩给了用户的桌面 App。现在失败会明说,且这一刻不再声称「未关联」(面板没有这个证据);顶栏刷新按钮在该 tab 尚未发布 loader 时置灰,而不是静默重载另一个 tab。
|
|
41
|
-
- 契约:`barPlan` 的决策由 `test/render.test.mjs` H3 驱动,接线与「失败必须渲染」由 `test/panel.test.mjs` F6 钉住;`docs.test.mjs` 检查
|
|
128
|
+
- 契约:`barPlan` 的决策由 `test/render.test.mjs` H3 驱动,接线与「失败必须渲染」由 `test/panel.test.mjs` F6 钉住;`docs.test.mjs` 检查 `README_TABS` 依赖 `activeTab` 的字面联合类型,源码注释已写明不要改成类型别名。
|
|
42
129
|
|
|
43
130
|
### 修复:AgnesCode tab 的「检测本机登录态」点了没反应(GET 路由每次都抛错)
|
|
44
131
|
|
|
@@ -164,12 +251,12 @@
|
|
|
164
251
|
|
|
165
252
|
`test/panel.test.mjs` 补三条断言把这次的决定钉住:三张卡的渲染顺序、默认展开集合、跨卡指引必须点卡片名而非方向词(均做过「故意改回旧序 / 改回 false → 红 → 还原 → 绿」验证)。
|
|
166
253
|
|
|
167
|
-
### 截图与市场清单对齐(`docs` 门禁新增检查
|
|
254
|
+
### 截图与市场清单对齐(`docs` 门禁新增检查 `SCREENSHOTS`)
|
|
168
255
|
|
|
169
256
|
重截截图时文件名从 `panel-credit-pools.png` / `panel-provider-setup.png` 换了新名,磁盘与 git 都已同步,**唯独 `screenshots.json` 仍指着两个已删掉的旧文件**——工作树干净、构建通过、其余检查全绿,**没有任何东西在报错**,而它是市场页取图的唯一依据,推上去就是图裂。
|
|
170
257
|
|
|
171
258
|
- **清单对齐当前两张**:`assets/panel-credit.png`(「积分额度」tab)、`assets/panel-API-provider.png`(「接入 API」tab);「小浣熊」那张待补。
|
|
172
|
-
- **`docs.test.mjs` 新增检查
|
|
259
|
+
- **`docs.test.mjs` 新增检查 `SCREENSHOTS`**:清单声明的每条路径必须**真实存在于磁盘**、是图片扩展名、条目数 1–8、且为仓库根相对路径。三种破坏实测红过再还原复验绿(换回旧名 / `..` 逃逸 / 拿 `README.md` 当条目)。
|
|
173
260
|
- **`PITFALLS` 新增 §26**(条目数 25 → 26,三处引用由门禁当场抓出并同步):**清单类文件(`.json` / `.yml` / `.toml`)不是文档,但同样是契约**——改资产名前先问「还有谁按名字引用它」;本仓库按名字引用 `assets/` 的机器消费方只有 `screenshots.json` 一处,正是「只有一处 + 又不叫 `.md`」让它成了盲区。
|
|
174
261
|
- **`CONTRIBUTING` §8** 那句「重截并推送后截图自动生效(**文件名不变**)」已修正:它藏了个未言明的前提——**改名就必须同步清单**,而这次恰恰是换了名。
|
|
175
262
|
|
|
@@ -195,8 +282,7 @@
|
|
|
195
282
|
面板花名册每行原来把 `low/medium/xhigh` 对**所有**商汤模型都画出来,但冻结契约表
|
|
196
283
|
`test/baselines/sensenova-contract.json` 里 `xhigh` 只实测过 deepseek-v4-flash(200)、
|
|
197
284
|
`max` 只实测过 glm-5.2(200),`low`/`medium` 对任何模型都**从未实测**(代码依据只是
|
|
198
|
-
平台 400
|
|
199
|
-
明说那串列表是**并集**、各模型支持面不同)——用户点了某家不支持的档就可能 400。
|
|
285
|
+
平台 400 报错文案里出现过这两个词,而那串列表是**并集**、各模型支持面不同)——用户点了某家不支持的档就可能 400。
|
|
200
286
|
现把 `thinkingLevelMapFor` 改为**逐模型门控**(新常量 `PROBED_EFFORT`,数据抄自同一张
|
|
201
287
|
冻结契约,覆盖 low/medium/high/xhigh/max 五格):`high`(平台默认,全家族实测过)保持
|
|
202
288
|
开,`xhigh` 只对 deepseek-v4-flash 开,`max` 只对 glm-5.2 开;未收录模型默认全关。
|
|
@@ -291,8 +377,8 @@ Token Plan 与小浣熊同为商汤旗下产品线,`sensenova` 这个名头名
|
|
|
291
377
|
- **`cordis.patch.yml` 头注释的同类漂移**:第 3 行同款地写着 "sidebar panel",同样进 npm 包,一并改掉。
|
|
292
378
|
- **第二上游的网关契约补复测**(新增 `docs/ROADMAP.md` §6.1.2):2026-10-01 的四次无凭据只读请求——本插件实际依赖的 `/model_catalog` 与 `/chat/completions` 均回 `401 authorization_empty_error`(已抵鉴权层,路由健在);09-30 记录里那个 404 的是参考件 `dsh-raccoon-work` 的 `/models`,**本插件不使用**。此前据前缀相同就判「实现的常量正是被标注 404 的那份清单」属**误判,已更正**。附带教训收进 PITFALLS §24。
|
|
293
379
|
- **护栏:`docs.test.mjs` 新增两条语义检查**——原有的全是形式校验(链接 / 表格去重 / 行数上限),对面「文档断言的事是否与代码一致」毫无感知:
|
|
294
|
-
- **检查
|
|
295
|
-
- **检查
|
|
380
|
+
- **检查 `README_TABS`**:README 必须覆盖面板的每一个 tab。tab 名单从 `panel-page.ts` 的 `activeTab` 联合类型派生、文案从 `i18n.ts` 的 `tab.<id>` 派生,**不写死任何名字**,于是「加 tab 忘了告诉用户」和「改 tab 名不跟」都必然红。
|
|
381
|
+
- **检查 `SELF_DESCRIPTION`**:README 与 `cordis.patch.yml` 声称的 UI 位置必须与 `src/client/*.ts` 实际注册的槽位一致。
|
|
296
382
|
- 两条都做过「故意破坏 → 必须红 → 还原 → 复绿」的双向验证(删光「小浣熊」精确报出 `raccoon(面板文案「小浣熊」)`;改回事故原文报「声称面板在侧边栏但没有 sidebar 槽位注册」)。
|
|
297
383
|
- **PITFALLS 新增 §24(GET 探活会误判)与 §25(形式门禁全绿 ≠ 文档说实话)**,总数 23 → 25;三处散落的过期引用(`README.md` / `AGENTS.md` / `docs/README.md`)同步——这批数字正是由新门禁当场揪出来的。
|
|
298
384
|
|
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ Agnes 的 Token Plan **按窗口限流**,不是积分余额——账号级四
|
|
|
15
15
|
|
|
16
16
|
这个面板把数字搬进 DSH 的 Plugins 页,写代码时不用切网页就能盯住:
|
|
17
17
|
|
|
18
|
-
-
|
|
18
|
+
- **额度窗口**:四个窗口的上限、周期与**平台报出的已用量**(`used / limit` 与百分比)。面板直接引用控制台自己的「当前用量」,进度条是逐字转写、不做减法;`usage_pct` 也是平台算好的
|
|
19
19
|
- **账号累计用量**:控制台口径的累计请求 / 文本 Token / 生图 / 视频秒数 / 活跃天数,以及近 N 天的分桶柱图
|
|
20
20
|
- **套餐对比**:平台**公开**的套餐目录(六档:入门版 / 专业版 / 高级版 × 月付 / 年付),无需登录即可读,用来回答"升级能买到什么"
|
|
21
21
|
- **模型清单**:当前 Key 实际能调哪些模型,其中哪些能看图(按平台 `input_modalities` 判定,不靠名字猜)
|
|
@@ -24,7 +24,7 @@ Agnes 的 Token Plan **按窗口限流**,不是积分余额——账号级四
|
|
|
24
24
|
|
|
25
25
|
面板**不代你操作账务**:不改套餐、不代扣额度、不碰 Key 明文;数据来自 Agnes 控制台自己的 API,与网页控制台口径一致。真正会「动」的四部分——注册 provider、挂出图工具、挂视频工具、接入 AgnesCode 桌面端上游——全部 opt-in 且**默认关闭**,不打开时插件退化为纯信息展示。
|
|
26
26
|
|
|
27
|
-
**注册 provider 时**(面板开关打开),插件把 Agnes 模型接进 DSH 的对话模型选择器,并在 Host 侧纠正 peer 对限频 429 的误判(
|
|
27
|
+
**注册 provider 时**(面板开关打开),插件把 Agnes 模型接进 DSH 的对话模型选择器,并在 Host 侧纠正 peer 对限频 429 的误判(peer 的 `isQuotaExceededError` 命中面过宽,任何带额度措辞的 429——如 `out of rate budget`——都会被抢判成「额度耗尽」而不重试)——限频真正退避重试,模型不再无端 "消失"。
|
|
28
28
|
|
|
29
29
|
## 安装
|
|
30
30
|
|
|
@@ -37,6 +37,8 @@ Agnes 的 Token Plan **按窗口限流**,不是积分余额——账号级四
|
|
|
37
37
|
|
|
38
38
|
2. **完全退出 DSH(含托盘)再启动**。
|
|
39
39
|
|
|
40
|
+
> 装到的是哪一版由源决定:安装器会询问 profile 配的 registry,**默认含 `registry.npmmirror.com`,刚发布的版本在镜像上可能延迟几分钟**,官方源立即可用;要确认拿到了哪一版,对照 `npm view dsh-connect-agnes-token-plan version --registry=https://registry.npmjs.org`。三种 target 形态(npm 包名 / git 地址 / 本地路径)见 [docs/SETUP.md](docs/SETUP.md)。
|
|
41
|
+
|
|
40
42
|
## 快速开始
|
|
41
43
|
|
|
42
44
|
1. 打开 DSH 的 **Plugins 页**,找到 `dsh-connect-agnes-token-plan` 的插件卡(面板是页内的内联卡片,**不在侧边栏**)。
|
|
@@ -49,19 +51,19 @@ Agnes 的 Token Plan **按窗口限流**,不是积分余额——账号级四
|
|
|
49
51
|
|
|
50
52
|
登录原理一句话:Host 在后台向 `{consoleBase}/api/user/login` 发**一次**账号密码 POST 换取 access token(Agnes 没有 OIDC 跳转、没有 refresh token),令牌过期或被拒时用同一路径**重登一次**;面板打开时才轮询一个只读本地路由,关掉即停。协议细节(一跳登录、密码明文过 TLS 与「不落盘」纪律、防锁号节流)见 [docs/AUTH.md](docs/AUTH.md),接口契约见 [docs/AGNES-API.md](docs/AGNES-API.md)。
|
|
51
53
|
|
|
52
|
-
|
|
54
|
+
**窗口「已用」是平台报出的,面板不计算**:`/api/cn/user/subscription` 直接返回每个窗口的 `used` / `limit` / `reset_at` / `usage_pct`(控制台「当前用量」那一屏的数据源),面板逐字转写并渲染进度条。但 `overview` / `series` 是**账号累计**口径,覆盖的是一段更长的时间——**不能用它去减窗口上限**,那个「剩余」跨周期、没人能担保,所以面板把「窗口用量」与「账号累计」作为两个独立事实并排显示,并明说不可相减。
|
|
53
55
|
|
|
54
56
|
## 把 Agnes 模型接进 DSH(可选)
|
|
55
57
|
|
|
56
58
|
「接入 API」tab 的三张卡按"你为什么来这"排序,而不是按依赖排序:**语言模型**(注册 provider + 勾选推送哪些模型)、**出图工具**——两张都在最前且默认展开;**API Key** 收在最后(默认收起),它是前两张卡的前置条件,由它们指回来。
|
|
57
59
|
|
|
58
|
-
在「API Key」卡里粘贴 API Key 保存(免费版 `sk-` 或 Token Plan `cpk-` 皆可):Host 即以 `agnes-token-plan` 之名注册 OpenAI 兼容 provider,模型列表随 `/v1/models`
|
|
60
|
+
在「API Key」卡里粘贴 API Key 保存(免费版 `sk-` 或 Token Plan `cpk-` 皆可):Host 即以 `agnes-token-plan` 之名注册 OpenAI 兼容 provider,模型列表随 `/v1/models` 自动刷新,还能在「语言模型」卡勾选具体要推送哪些模型。Key 只进 DSH 凭据(引用名 `AGNES_TOKEN_PLAN_API_KEY`)、面板永不回显。开关与勾选都在面板热生效,无需重启。细节见 [docs/SETUP.md](docs/SETUP.md) §3 与 [docs/PROVIDER-HOT-RELOAD.md](docs/PROVIDER-HOT-RELOAD.md)。
|
|
59
61
|
|
|
60
|
-
> **免费版与付费 Token Plan 共用同一个 API Key
|
|
62
|
+
> **免费版与付费 Token Plan 共用同一个 API Key 输入框**:`sk-`(免费版)与 `cpk-`(Token Plan)两类 Key 都走同一份 `/v1/models` 目录,本插件对前缀不做限制。**计费双轨**——`sk-` 走 API 按 token / 张 / 秒计费(`agnes-2.5-flash` / `agnes-3.0-flash` / 图片模型当前优惠价 `$0`,`agnes-2.5-pro` 按刊例价),`cpk-` 走 Token Plan 订阅配额(四窗口)。面板「积分额度」tab 只读**订阅配额**,不读 API 按量余额;两类 Key 使用**独立限制池**,换 Key 即换池。两者都能在此粘贴。
|
|
61
63
|
|
|
62
64
|
## 出图工具(可选,默认关)
|
|
63
65
|
|
|
64
|
-
面板「出图工具」卡(在「语言模型」下方,默认展开)打开开关后,Host 给 agent 注册工具 `agnes_draw_image`(首选模型由 `drawModelId` 指定),鉴权走同一把 `AGNES_TOKEN_PLAN_API_KEY`。出图模型优先按 catalog 的 `output_modalities`
|
|
66
|
+
面板「出图工具」卡(在「语言模型」下方,默认展开)打开开关后,Host 给 agent 注册工具 `agnes_draw_image`(首选模型由 `drawModelId` 指定),鉴权走同一把 `AGNES_TOKEN_PLAN_API_KEY`。出图模型优先按 catalog 的 `output_modalities` 结构化判定,该字段在 Agnes 目录上**缺失**时退回模型名里的 `image` 段(名字兜底才是实际命中的路径)。注意:工具的实际挂载 / 缺席发生在**下一次 Host 启动**(agent tools 没有 unregister 语义),开关值本身立即生效。
|
|
65
67
|
|
|
66
68
|
## 视频工具(可选,默认关)
|
|
67
69
|
|
|
@@ -69,7 +71,7 @@ Agnes 的 Token Plan **按窗口限流**,不是积分余额——账号级四
|
|
|
69
71
|
|
|
70
72
|
## 桌面端上游:AgnesCode(可选,默认关)
|
|
71
73
|
|
|
72
|
-
面板「AgnesCode」tab 接的是 **AgnesCode 桌面端**的登录态:微信扫码发生在桌面 App 里,本插件只**读取** App 留在本机的加密会话文件(Chromium os_crypt,密钥经系统 DPAPI 解封,全程内存使用、不落盘不显示;解出的凭据随后存入 DSH 凭据服务,与账号密码同一纪律),并以 provider id `
|
|
74
|
+
面板「AgnesCode」tab 接的是 **AgnesCode 桌面端**的登录态:微信扫码发生在桌面 App 里,本插件只**读取** App 留在本机的加密会话文件(Chromium os_crypt,密钥经系统 DPAPI 解封,全程内存使用、不落盘不显示;解出的凭据随后存入 DSH 凭据服务,与账号密码同一纪律),并以 provider id `agnescode`(显示名 AgnesCode)注册**独立** provider。它的接口地址写在会话文件里、**按账号跟随**(钉死在 Agnes 域名族内,地址不对就拒绝使用);显示的积分是**订阅池**口径(时效 + 永久),模型清单带「会员」标记(会员门槛是账号状态,不是模型不存在,所以标记而不隐藏)。检测不到登录态时,面板逐条列出**探测过哪些文件、各自为什么没成**——「没装 App」「解不开密」「会话里没有令牌」是三种不同的处理方式,不会笼统叫你重新登录。JWT 有效期约 28 天,过期后开一次桌面 App 再点「检测本机登录态」即可;协议探针记录见 [docs/ROADMAP.md](docs/ROADMAP.md) §6.3。
|
|
73
75
|
|
|
74
76
|
## 运维诊断:这台机器现在挂没挂 provider?
|
|
75
77
|
|
|
@@ -88,7 +90,7 @@ npm run doctor:json # 机器读:JSON(可进你的巡检 / 工单脚本
|
|
|
88
90
|
- [docs/API.md](docs/API.md) — 路由与控制台端点
|
|
89
91
|
- [docs/AGNES-API.md](docs/AGNES-API.md) — Agnes 接口全集(控制台额度侧 + 推理侧)
|
|
90
92
|
- [docs/TESTING.md](docs/TESTING.md) — 测试体系
|
|
91
|
-
- [docs/PITFALLS.md](docs/PITFALLS.md) — 真实踩坑(
|
|
93
|
+
- [docs/PITFALLS.md](docs/PITFALLS.md) — 真实踩坑(39 条)
|
|
92
94
|
- [CHANGELOG.md](CHANGELOG.md) — 版本变化
|
|
93
95
|
|
|
94
96
|
AI 协作会话请先读 [AGENTS.md](AGENTS.md)。
|
|
@@ -96,7 +98,7 @@ AI 协作会话请先读 [AGENTS.md](AGENTS.md)。
|
|
|
96
98
|
## 诚实声明
|
|
97
99
|
|
|
98
100
|
- 面板显示的是**控制台自己的口径**,与网页控制台一致;`GET /v1/models` 只区分权限,不计费也不占推理额度;
|
|
99
|
-
-
|
|
101
|
+
- 窗口卡片里的「已用」是控制台报出的「当前用量」,面板逐字转写、不做减法;下方「账号累计」覆盖的是另一段时间,不能与窗口上限相减;
|
|
100
102
|
- 令牌被拒时面板明确提示重新登录,而不是静默显示旧数据;
|
|
101
103
|
- 凭据(账号、access token)只经 DSH 凭据服务保存,**密码不落盘**;本插件不写任何明文凭据文件或调试日志。
|
|
102
104
|
|
package/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -4,10 +4,30 @@
|
|
|
4
4
|
|
|
5
5
|
- **文档范式**:参照本地 `~/.dsh/fork/dsh-connect-qoder` 的 README——「这是一个 DSH 插件、如何被加载、bundle 结构」的完整讲述方式(见 `docs/DSH-PLUGIN.md`);
|
|
6
6
|
- **架构对齐**:provider settings 设计对齐 DSH connect 家族(`dsh-connect-trae` / `dsh-connect-workbuddy` / `llm-qoder`,`imageModelIds` 等见 `docs/ARCHITECTURE.md` §5.1);
|
|
7
|
-
-
|
|
7
|
+
- **接口参考实现(历史上的游)**:[shaobingtongzhi/sensenova-usage-dashboard](https://github.com/shaobingtongzhi/sensenova-usage-dashboard)(Python 桌面工具)——商汤时代的原始实现,其算法细节(登录 OIDC 流、密码 JWE 封包、用量接口解析)已吸收进本插件的 Node 实现。
|
|
8
|
+
- **AgnesCode 线的参照件**:`vibe-coding-labs/AgnesCode2Api`(Go 协议翻译代理)、`vibe-coding-labs/AgnesCodeReverseEngineering`(逆向协议文档 + Python 脚本,Apache-2.0)、`AgnesAI-Labs/AgnesCode`(官方 release / 反馈中心,不含源码)、`ViviQuan/agnescode`(终端 agent,MIT)、`minchieh-fay/agnescodex`、`AgnesAI-Labs/skills`(官方模型 Skills),外加本机安装的 AgnesCode 桌面端 `app.asar` 解包快照(闭源第三方,仅作本机对照证据)。
|
|
9
|
+
- 以上参照件全部落在 `.gitignore` 忽略、**不随本仓库提交**的本地容器 `upstream/` 里(清单与各自许可见 [REFERENCES.md](./docs/REFERENCES.md),容器姿势见 `docs/ARCHITECTURE.md` §1);本插件构建期与运行期均不依赖它们、不进包,仅本地对照。**对它们只吸收事实、不复制代码**,故不构成许可证约束下的再分发。
|
|
8
10
|
|
|
9
11
|
以上均为**设计 / 文档 / 接口层面的参照,无代码复制**,不构成许可证约束下的再分发。
|
|
10
12
|
|
|
13
|
+
## 参照对象及其被吸收部分(逐条说明)
|
|
14
|
+
|
|
15
|
+
| 参照对象 | 吸收的具体部分 | 在本插件中的对应实现 |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `sensenova-usage-dashboard`(Python 桌面工具,商汤时代) | 登录流程的**失败分类**思路(区分「令牌过期」与「路径 404」与「平台拒绝」);用量接口的**分桶聚合**算法(按日期桶求和而非按模型归并) | `agnes-auth.ts` 的 `classifyLoginFailure`;`parsers.ts` 的 `parseUsageSeries`(跨桶求和 + 按时间排序) |
|
|
18
|
+
| `dsh-connect-workbuddy-main`(DSH 家族同型插件) | 本机登录态采集的**架构范式**:读第三方 App 的加密会话文件(os_crypt / DPAPI + AES-GCM),provider 按会话文件跟随账号地址,`publisher`/`store`/凭据引用全部隔离 | `src/host/agnescode-*.ts` 整条 AgnesCode 线;`docs/ROADMAP.md` §6.3 的隔离裁定 |
|
|
19
|
+
| `dsh-connect-trae` / `llm-qoder`(DSH 家族同型插件) | provider settings 的**字段命名约定**(`imageModelIds`、`reasoningEffort`、`contextWindow` 等)与 opt-in 开关模式(默认关,失败降级为面板照常用、模块缺席) | `cordis.patch.yml` 的四开关商店;`src/host/switch-store.ts` |
|
|
20
|
+
| `vibe-coding-labs/AgnesCodeReverseEngineering`(逆向协议文档 + Python 脚本,Apache-2.0) | 12 份协议文档中的**认证授权**(DPAPI 解密流程、os_crypt 文件布局)、**BFF API**(端点路径与请求体形状)、**ACP WebSocket**(桌面端与后端的通信协议) | `agnescode-*.ts` 中桌面端会话采集与接口对接;`docs/AGNES-API.md` §1–§6 的 Agnes 控制台端点契约 |
|
|
21
|
+
| `vibe-coding-labs/AgnesCode2Api`(Go 协议翻译代理,Apache-2.0) | `pkg/auth/credentials.go` 的 **macOS `state.vscdb` 采集路径**(SQLite 表名、字段名、加密偏移量)——**未实现,仅登记为 fact** | `agnescode.ts` L440–445:macOS 分支目前直接返回 `UNSUPPORTED_PLATFORM`("no verified harvest path yet"),`state.vscdb` 的事实记录在此备查 |
|
|
22
|
+
| `AgnesCode-desktop-1.0.68/`(本机 `app.asar` 快照,闭源第三方) | 全部 BFF 调用的**真实出处**(`.vite/renderer/.../App-*.js` 里的 fetch 路径与参数);两个形状探针(`probe-agnescode-models.mjs` / `probe-agnescode-credits.mjs`)的原始输出 | `docs/AGNES-API.md` §4 的四窗口字段名;`docs/ROADMAP.md` §6.3.1 的积分端点契约 |
|
|
23
|
+
| `AgnesAI-Labs/AgnesAI-Models`(官方网关与模型目录) | 推理侧 `/v1/models` 的**接口形状**与模型 id 命名规则 | `src/host/llm-models.ts` 的 `LLM_PROVIDER_ID` 与 `modality.ts` 的名称兜底 |
|
|
24
|
+
| `AgnesAI-Labs/skills`(官方模型集成 Skills) | 出图 / 视频 / agent 三条线的**工具定义与参数约定** | `src/host/draw.ts`、`src/host/video.ts` 的请求体构造 |
|
|
25
|
+
| `AgnesCode/`(官方 release,不含源码) | 桌面端安装包版本线(确认本机快照与线上逆向件的版本漂移方向) | `docs/REFERENCES.md` §3 的「版本漂移优先于文档结论」纪律 |
|
|
26
|
+
| `wiki.agnes-ai.cn`(官方中文站文档,抓存于 `AGNES-API-docs/`) | RPM 限制表(§4.1);订阅配额三档表(§4.1②);429/402 错误码语义(§7.3.1);出图 / 视频 V2.0 与 2.5 的参数体系(§7.5);`agnes-3.0-flash` 等模型的上下文窗口声明(§7.1.2) | `llm-error-fix.ts` 的 429 纠正逻辑;`PROBED_CONTEXT_WINDOWS` / `PROBED_VISION` 硬编码表;`buildVideoBody` / `buildVideoBody25` 的校验规则 |
|
|
27
|
+
| `upstream/dsh-agnes*`(社区 Agnes 插件族) | 视频端点的两个常量(`AGNES_VIDEO_API_URL` / `AGNES_VIDEO_QUERY_URL`);2.5 家族的校验约束(flash 仅 720P、reference ≤5、秒数 4–12) | `video-protocol.ts` 的 `buildVideoQueryEndpoint`(剥版本号段);`video-protocol-25.ts` 的 `buildVideoBody25` 字段白名单 |
|
|
28
|
+
|
|
29
|
+
**边界说明**:以上所有参照仅用于「读出事实 → 用自有 TypeScript 实现重写」,**未 vendor 任何源码**。参照件多为「个人学习与技术研究」定位,其作者明确禁止商业转售与中转服务——本插件不做这两件事,也不随包分发任何参照件代码。
|
|
30
|
+
|
|
11
31
|
## 随包第三方依赖
|
|
12
32
|
|
|
13
33
|
`package.json` 的 `files` 打包清单(由 `test/package.test.mjs` 的 import 闭包检查钉住)**不包含任何第三方代码**:
|