dsh-connect-agnes-token-plan 0.10.2 → 0.11.1
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 +119 -97
- package/README.md +11 -3
- package/client.js +654 -63
- package/lib/index.js +6 -7
- package/package.json +4 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,51 +2,87 @@
|
|
|
2
2
|
|
|
3
3
|
本文件只记**公开行为变化**(新增能力、破坏性改动、重要修复)。实现细节、重构与测试加固请直接看 `git log`。
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
**本文件就是市场面**:DSH 插件市场渲染「每个版本发布了什么」只读打进 npm 包的这份文件(`files` 白名单内),不解析 git 提交、不抓 GitHub Release。因此每条默认读者是市场页前的用户,发版前先把条目写好再 `npm publish`(见 `RELEASING.md` §3)。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
读者只有一个:**已经装了上一版、正在决定要不要升级的用户**。他读一条时心里问的是「升上去之后,我的面板 / 选择器 / 胶囊会有什么不一样」。写任何一条之前先答这个问题——答不出来,这条就不该进本文件。
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- **修(额度渲染):`usagePct` 有值而 `used` 缺失时,`count(null)` 被渲染成 `0`,面板会打印「已用 0 / N」**(F1)。`UsageTotals` 四个主计数另加 `typeof` 门:缺席字段不再画成「0」——真实数据流下此门不触发(`countOf` 已把缺席平台字段压成数字 0、`overview` 失败时 `quota.totals:null` 见红线⑥ / ADR-007),属渲染层自防御,防未来 partial 对象被构造出来。
|
|
11
|
-
- **修(AgnesCode 花名册):两处目录正确性缺陷**。(F5)排除别名 `id === EXCLUDED_IDS[0]` 改为 `.includes(id)`,第二个别名不再静默失效、继续混进花名册;(F10)`provider-controls` 的 `idList` 用 `String(id)` 强转,`null` 会变成字符串 `"null"` 这个假模型 id 出现在候选列表里,改用 `models.ts` 的 `rosterIds`(只收非空字符串)。
|
|
12
|
-
- **修(凭据隔离):AgnesCode 的 DPAPI PowerShell 子进程不再继承含凭据的父进程 env**,新增 `dpapiChildEnv` 剥除四枚凭据名(`AGNES_PASSWORD` / `AGNES_USERNAME` / `AGNES_TOKEN_PLAN_API_KEY` / `AGNESCODE_CREDENTIAL`),与全仓凭据 REF 集合逐字一致——降低解密第三方桌面端会话文件那一步的凭据泄漏半径(红线①)。`harvest attempts[].detail` 与 `state().error` 出口统一过 `redactSecrets`。
|
|
13
|
-
- **内部加固 / 清理(不属公开行为变化,详见 `git log`)**:收敛三轮四域代码审查的约 22 项缺陷与计数器 / 方法归一化 / 单飞泄漏 / JSDoc 归位等低危项;删除 25 个零读者 style token(`details*` / `grant*` / `models*` / `trend*` / `poolsGrid` / `primaryHover`)与全仓零引用的孤儿 `jsqr` devDependency;统一 `countOf` 与 `Number(x)||0` 两处数值惯用法、`requestMethod` 六路由共用、BFF 门控头收敛为单一 `AGNESCODE_BASE_HEADERS`;CI `build-gate` 确保暂存目录存在再 `mkdtemp`。上述均以新增断言钉住,无破坏性改动。
|
|
14
|
-
- 影响面:`src/{host,client}/`(多文件)、`lib/`、`client.js`(随 src 同 commit 重建,构建零漂移)、`test/`(多套件 + 断言)、`package.json`(版本 + 去孤儿依赖)。`npm test` 全绿:28 套件 + tsc / build / dup / e2e 四门禁通过,e2e 66/66 PASSED。
|
|
9
|
+
## 写作纪律
|
|
15
10
|
|
|
16
|
-
|
|
11
|
+
**唯一判据(自检法)**:把这条念给那个没读过本仓库的用户听。他要是得先知道「承重面」「基线冻结」「state 窝点」这些词才能听懂,这条就写给了错的人——它属于 `docs/ADR.md` / `docs/PITFALLS.md`,本文件最多留**一行指针**(形如「内部:…详见 `docs/XXX.md`」)。
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
- **删的是维护者腔,留的是用户锚点**。可以删:自证式内心戏(「这正是…唯一能站住的地方」)、比喻、金句、给改代码的人看的精确行号。用户拿错误码 / 配置名来查这条时,需要看到那个码、那个名——端点路径、配置名、字段名、错误码、版本号照留;内部标识符(模块名、测试文件名、`ADR-xxx` 编号)只在用户排障真的会 grep 到它时才留,否则进指针。
|
|
14
|
+
- **一整节都写给维护者 = 整节删**,不是压缩。判据是该节「影响面」只列 `docs/*` 与「本文件」、且不含任何用户可见行为。
|
|
15
|
+
- **影响面清单最多一行**:只列文件名 / 测试名,不展开、不夹根因论证——根因去 `docs/PITFALLS.md`,决策去 `docs/ADR.md`,这里一行指针就够。一行变三行、开始解释「为什么改这些文件」,就是这条正在变成维护者交接文档的信号。
|
|
16
|
+
- **长句拆开**。一句里塞三个转折、两个破折号补语、一个括号说明,就是一次检索失败。数字与结论放句首,理由放后面。
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
- **这是 0.10.1 头号动机,优先级高于本节其余条目**:0.10.0 已发布且**不可覆盖**(npm 同版本号唯一,`unpublish` 后同号也不可复用),所以修复只能随新版本到达用户——这也是本版应当尽快发布的原因。
|
|
22
|
-
- **处置边界要说清,避免误判风险面**:泄漏面**仅此一个二进制资源**。已核对 0.10.0 tarball 内全部文本类文件(`.md` / `.json` / `.yml`),账号名**无任何文本残留**;其余两张截图不含账号名。本仓红线条目(凭据不入库、错误文本脱敏)针对的是凭据与令牌,昵称属个人信息、不在凭据服务内,故**不触发凭据层面的处置流程**,但仍按泄漏修掉。
|
|
23
|
-
- **`screenshots.json` 与文件名未变**:只换了图片内容,未增删文件,因此市场页的清单与 `files` 白名单不需跟着改(`files` 含 `assets`,重截自动随包发布)。
|
|
24
|
-
- 影响面:`assets/panel-AgnesCode.png`(仅此一个文件,无代码改动)。
|
|
18
|
+
## 本文件的豁免与代价
|
|
25
19
|
|
|
26
|
-
|
|
20
|
+
`test/docs.test.mjs` 对本文件**整文件豁免**(行号锚守卫、计数护栏、跨文件表格去重等一律跳过),理由是「不可变正是它们的价值」——历史记录不该被活文档的规矩追着改。
|
|
27
21
|
|
|
28
|
-
|
|
29
|
-
- **新增:已停车(`needsUserAction`)时给一句话而不是倒计时**。错密码、需人工验证、自造退避用尽这三类拒绝**没有**可等待的期限——倒计时数到零不会有任何东西重试,所以那个数字是撒谎。面板现在明说「已停止自动重试,请核对账号与密码后手动登录」并保持提交按钮可用(重新输入才是出路),与 `auth.locked`(平台说账号本身被锁)分作两句。
|
|
30
|
-
- **修:验证码类拒绝会同时渲染两句矛盾的话**。`POST /account` 的失败体在「平台给了 `Retry-After`」时会同时带一个整段窗口与 `needsUserAction: true`,于是旧渲染路径上「已停止自动重试」与一个两小时倒计时同时出现。`submit` 现在让 parked 优先于窗口——`AccountForm` 与 `snapshot.ts` 的规则同源,此前只有后者。
|
|
31
|
-
- **`API.md` 补上 `auth` 块两个节流字段的契约**(单位是**剩余**毫秒不是整段窗口;parked 时不许倒计时;面板必须服从它们而非只认自己那次失败),`AUTH.md` §7 与 `ARCHITECTURE.md` §3 数据流图同步接入。字段此前只有两个 JSON 值、没有任何语义说明,按字面读会把「parked 也倒计时」这类 bug 写出来。
|
|
32
|
-
- 影响面:`src/client/{snapshot,account-form,i18n}.ts`、`test/{panel.test.mjs,panel-decision.js}`、`docs/{API,AUTH,ARCHITECTURE,ADR}.md`、`docs/PITFALLS.md`(新增 §52–§54)、`docs/ADR.md`(新增 ADR-010)、`client.js`(重建产物)。`lib/` 未改——本次全部改动在 client 半边。
|
|
22
|
+
**代价是没有任何门禁会拦住上面那些错误**,包括把账本条目整段抄进来。所以纪律靠本节的判据自查;改动本文件后手工跑一次 `node test/docs.test.mjs`,确认没碰坏其它检查(如发布版本陈述)。
|
|
33
23
|
|
|
34
|
-
|
|
24
|
+
## [Unreleased]
|
|
25
|
+
|
|
26
|
+
## [0.11.1] — 2026-10-16
|
|
27
|
+
|
|
28
|
+
### 修复:用量胶囊首读失败不再卡死到会话结束、保存不再被旧轮询盖回
|
|
29
|
+
|
|
30
|
+
- **修(用量胶囊)**:控制台额度的首次读取失败时,胶囊不再停在失败帧直到会话结束——现在按 30 秒节奏持续重试,一读成功即显示正常读数;轮询间隔自动以 Host 报出的值为准。
|
|
31
|
+
- **修(用量胶囊)**:模型选择器的 provider 被清空(空值)时,胶囊不再在恰好转帧上丢掉读数——上一次的选择仍可用就继续用它。
|
|
32
|
+
- **修(面板)**:保存提供方开关 / 模型清单 / 出图·视频工具卡后,刚保存的值不再被在途的旧轮询快照盖回旧值。
|
|
33
|
+
- 影响面:`src/client/{composer-usage-pill,panel-page}.ts`、`client.js`、`test/{dom-render,composer-slot-gate,config}.test.mjs`。
|
|
34
|
+
|
|
35
|
+
## [0.11.0] — 2026-10-16
|
|
35
36
|
|
|
36
|
-
|
|
37
|
-
- **读取端是硬校验,不是降级**:`icon` 必须是相对路径、扩展名限 SVG/PNG/JPEG/WebP、文件必须落在 `files` 白名单目录内、体积 ≤256 KiB——任一不满足会让整条插件元数据报错(该经验的出处是 `dsh-connect-sensenova-token-plan` CHANGELOG 0.4.4,已写进 `docs/PITFALLS.md` §27)。因此 `icon.svg` 同时进 `files` 白名单,`exports` 无需新增子路径(图标由 Host 直接按仓库路径读,不走包导出)。
|
|
38
|
-
- 影响面:`icon.svg`、`package.json`、`docs/DSH-PLUGIN.md`(教学快照同步 `icon` 字段与 `files` 数组)。
|
|
37
|
+
本版两条主线:新能力**对话框用量胶囊**(输入框右侧的第二条读数),与一批**面板操作体感**改进(几处面板操作的等待时间缩短)。
|
|
39
38
|
|
|
40
|
-
###
|
|
39
|
+
### 对话框用量胶囊:输入框右侧的第二条读数
|
|
41
40
|
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
- 影响面:`
|
|
41
|
+
- **新**:使用本插件模型的会话,输入框右侧出现一枚小胶囊。Token Plan 模型显示「5 小时 / 每周请求窗口」的使用百分比——与面板进度条同一把尺子,超额(>100%)照实显示不钳制;AgnesCode 模型显示桌面端积分余额——余额是存量、不造百分比(`0` 是「已耗尽」的读数,破折号是「读不到」)。其它 provider 模型的会话一律不显示,胶囊不发起任何读取。
|
|
42
|
+
- **软失败**:读数失败不影响面板与其它功能,胶囊保留最后一次成功读数并标记「上次数据」;胶囊本身注册失败时整个模块缺席,面板照常工作。
|
|
43
|
+
- 影响面:`src/client/{composer-usage-pill,const,apply,cards,agnescode-tab,i18n,styles,index}.ts`、`client.js`、`test/{composer-slot-gate,dom-render,render,contract}.test.mjs`。
|
|
45
44
|
|
|
46
|
-
###
|
|
45
|
+
### 面板操作体感:几处面板操作不再等下一轮轮询
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
可感变化(账号失效 / 控制台降级场景),四项:
|
|
48
|
+
|
|
49
|
+
- ① 快照取数全部并行:失效账号下面板取数最坏情形从 30 s 起压到 ~15 s。死令牌每源至多出示一次、每轮自动登录一次——不重新引入锁号。
|
|
50
|
+
- ② 保存提供方开关 / 模型清单 / 出图·视频工具卡不再触发全量快照 reload,关模型、切开关的效果不再等下一轮慢轮询。
|
|
51
|
+
- ③ AgnesCode 三个动作(开关 / 检测本机登录态 / 保存模型清单)即时生效,采集成功立刻翻出已关联卡片,不再多等一次最长 30 s。
|
|
52
|
+
- ④ AgnesCode 侧的两个 30 s 上游读(积分余额 / 模型清单)改并行,最坏 60 s → 30 s。
|
|
53
|
+
- 工具卡「实际生效模型」徽标与额度数字仍随 30 s 轮询更新(Host 计算值,本地不造数)。
|
|
54
|
+
- **归位说明**:以上四项曾被记在 `[0.10.2]` 节下的补记里,但已发布的 0.10.2 包内并不含其中任何一条;它们随本版实际落地,原节移入本节订正。
|
|
55
|
+
- 内部:快照并行的决策依据见 `docs/ADR.md` ADR-014。
|
|
56
|
+
- 影响面:`src/host/{snapshot-aggregate,routes/agnescode}.ts`、`src/client/{panel-page,provider-controls,model-picker,wire,agnescode-tab}.ts`、`lib/`、`client.js`、`test/routes.test.mjs`。
|
|
57
|
+
|
|
58
|
+
## [0.10.2] — 2026-10-10
|
|
59
|
+
|
|
60
|
+
### 修复:视频任务续查、额度渲染与模型花名册的几处真实缺陷 + 凭据隔离加固
|
|
61
|
+
|
|
62
|
+
- **修(视频工具)**:异步视频任务首次查询被拒时现在携带任务 id、有限重试,任务可以续查——此前卡在「查不到」。
|
|
63
|
+
- **修(额度渲染)**:平台缺席某字段时不再显示「已用 0 / N」——缺席画成破折号,不画成 0。
|
|
64
|
+
- **修(AgnesCode 花名册)**:第二个排除别名不再静默失效;不再出现名为 `"null"` 的假模型候选。
|
|
65
|
+
- **修(凭据隔离)**:解密桌面 App 会话文件的本机子进程不再继承父进程的凭据环境(剥除 `AGNES_PASSWORD` / `AGNES_USERNAME` / `AGNES_TOKEN_PLAN_API_KEY` / `AGNESCODE_CREDENTIAL` 四枚凭据名),凭据可能出现的日志出口统一脱敏。
|
|
66
|
+
- **内部加固 / 清理**(不属公开行为变化,约 22 项低危缺陷与一个孤儿依赖的删除):详见 `git log`。
|
|
67
|
+
- 影响面:`src/{host,client}/`(多文件)、`lib/`、`client.js`、`test/`(多套件)、`package.json`。
|
|
68
|
+
|
|
69
|
+
## [0.10.1] — 2026-10-06
|
|
70
|
+
|
|
71
|
+
> **如果你装过 0.10.0,请升级到本版。** 0.10.0 的市场页截图 `assets/panel-AgnesCode.png` 里含一个真实账号昵称(面板「已关联:{昵称}」那一行,截图时未遮挡)。该图随 0.10.0 发布,已发布版本不可覆盖,因此只能随新版替换。图已重截,该行改为中性占位文案,昵称不再出现在任何像素里;泄漏面仅此一个图片文件,其余两张截图与包内全部文本文件均无该账号名残留。
|
|
72
|
+
|
|
73
|
+
### 登录节流窗口改为全机共享:刷新页面不再让按钮在锁定期内可点
|
|
74
|
+
|
|
75
|
+
- **修**:登录节流窗口现在**机器级共享**——一个 profile 撞上的 429,其它 profile 的 Host 同样算数。此前倒计时只从本进程的失败起步,刷新页面、换 profile、重启 Host 三种正常操作都会让提交按钮在仍被节流的窗口里显示为可点,而那次点击不止白费——它还会抹掉另一个进程正在遵守的节流记录。现在倒计时由 Host 下发的共享窗口播种,只延长、不缩短。
|
|
76
|
+
- **新增**:「等下去也没用」的已停车情形(错密码、需人工验证、重试次数用尽),面板明说「已停止自动重试,请核对账号与密码后手动登录」,不再给一个数到零也不会重试的倒计时;与「账号被平台锁定」分作两句。
|
|
77
|
+
- **修**:验证码类拒绝同时带回等待窗口与「需人工处理」时,面板不再同时显示「已停止自动重试」与两小时倒计时这两句矛盾的话(人工处理优先)。
|
|
78
|
+
- 内部:节流窗口机制(`auth` 块两字段、parked 不倒计时、播种只延后)见 `docs/PITFALLS.md` §52 与 `docs/ADR.md` ADR-010;契约文档见 `docs/API.md`。
|
|
79
|
+
- 影响面:`src/client/{snapshot,account-form,i18n}.ts`、`test/{panel.test.mjs,panel-decision.js}`、`client.js`。
|
|
80
|
+
|
|
81
|
+
### 插件卡补上图标:Plugins 页不再裸显示包名 + 一段英文
|
|
82
|
+
|
|
83
|
+
- **新增 `icon.svg`**:Plugins 页的插件卡此前只有文字;卡片图标由 DSH Host 读 `package.json` 的 `icon` 字段渲染,不提供就缺一块。图标沿用面板的「积分币」母题(品牌蓝),几何与兄弟插件 `dsh-connect-sensenova-token-plan` 保持一致。
|
|
84
|
+
- **图标读取是硬校验**:必须是相对路径、限 SVG/PNG/JPEG/WebP、落在 `files` 白名单内、体积 ≤ 256 KiB,任一不满足会让整条插件元数据报错——因此 `icon.svg` 同时进 `files` 白名单。
|
|
85
|
+
- 影响面:`icon.svg`、`package.json`。
|
|
50
86
|
|
|
51
87
|
## [0.10.0] — 2026-10-04
|
|
52
88
|
|
|
@@ -295,9 +331,9 @@
|
|
|
295
331
|
|
|
296
332
|
- **面板第三个 tab「小浣熊」**(`src/client/raccoon-tab.ts`):开关、微信扫码登录、积分余额、模型花名册四块。文案中英双语(`raccoon.*` 17 键)。
|
|
297
333
|
- **Host 半边 peer-free 协议层**(`src/host/raccoon.ts`):扫码登录走查、信封解析(成功判据是 `code === 0`,用普通 `Number` 比较——共享的 `num` 助手会把 `0` 当假值拒掉)、一次性 refresh-token 轮换、余额与目录读取、两态思考档位映射。
|
|
298
|
-
- **凭据走 DSH 凭据服务**(`src/host/raccoon-store.ts`):存的是凭据服务引用而非明文;轮换后的新 pair
|
|
334
|
+
- **凭据走 DSH 凭据服务**(`src/host/raccoon-store.ts`):存的是凭据服务引用而非明文;轮换后的新 pair 在续期时**回写**。
|
|
299
335
|
- **开关按 profile 分段**(`src/host/raccoon-switch-store.ts`):与 provider/draw 同一套文件-backed 纪律。
|
|
300
|
-
- **第二个独立 publisher**(`src/host/raccoon-publish.ts` + `raccoon-llm-adapter.ts`):与 Token Plan
|
|
336
|
+
- **第二个独立 publisher**(`src/host/raccoon-publish.ts` + `raccoon-llm-adapter.ts`):与 Token Plan 的注册完全隔离。
|
|
301
337
|
- **自包含 QR 编码器**(`src/client/qr.ts`,455 行,零外部依赖):byte mode、纠错等级 M、v1–10,登录 URL 直接在面板内编码成图。
|
|
302
338
|
- **测试**:`test/raccoon.test.mjs`(离线,覆盖协议、两个 store、描述符映射、publisher 状态机、QR 编码器、开关 store),已进 `npm test` 与 CI offline 档。
|
|
303
339
|
|
|
@@ -308,24 +344,24 @@
|
|
|
308
344
|
- **QR 要等下一轮 60s 轮询才出现**:登录入口像没反应。
|
|
309
345
|
- **`fontSize` / `marginTop` 泄漏成 DOM 属性而非样式**:样式静默失效。
|
|
310
346
|
- **扫码登录拿到的昵称没存**:面板无法称呼用户,补存后正常问候。
|
|
311
|
-
- **小浣熊的积分倍率没进模型选择器**:面板花名册显示的 ×0.75 / free / ×0.2,在选择器里看不到(pi-ai 没有计费元数据通道,选择器只渲染名字)。倍率改挂进显示名——`GLM-5.3(×0.75)`、`SenseNova 6.8 Flash(free)`,倍率 1
|
|
347
|
+
- **小浣熊的积分倍率没进模型选择器**:面板花名册显示的 ×0.75 / free / ×0.2,在选择器里看不到(pi-ai 没有计费元数据通道,选择器只渲染名字)。倍率改挂进显示名——`GLM-5.3(×0.75)`、`SenseNova 6.8 Flash(free)`,倍率 1 保持裸名。
|
|
312
348
|
|
|
313
349
|
### 面板从侧边栏归位到 Plugins 页
|
|
314
350
|
|
|
315
351
|
- **去掉 `sidebar.panellist` 与 `main` 槽位注册**,只留 `plugins.bundle.config`:面板改为 Plugins 页内的**内联卡片**,不再占侧边栏一行(`src/client/panel-page.ts`、`src/client/index.ts`)。同时摘掉 layout 服务依赖与 onClose 按钮(Plugins 页自己管导航),`PanelPage` 的 `onClose` 改为按传入与否决定渲染。
|
|
316
|
-
-
|
|
352
|
+
- 解决了「装了 5 个 connect 插件 = 侧边栏 5 行噪音」的问题,与 workbuddy 的形态对齐。
|
|
317
353
|
|
|
318
354
|
### 小浣熊模型列表:行形态与 Token Plan 花名册对齐
|
|
319
355
|
|
|
320
|
-
原来每个模型只有「名字 + 一个 English
|
|
356
|
+
原来每个模型只有「名字 + 一个 English 徽章」,参数行整块缺席。数据其实**早就在手上**——网关的目录行带 `context_window` / `max_output_tokens`,`fetchRaccoonCatalog` 自首个版本就归一化了这两个字段,只有渲染组件把它们丢了:
|
|
321
357
|
|
|
322
|
-
- **补上参数行**:「256K 上下文 · 最大输出 64K」,复用 Token Plan 花名册的 `S.modelMeta` 与同两条文案模板(`llm.contextBadge` / `llm.metaOutput`)。目录没声明该字段时**不画这一段**(`num()` 对缺失值返回 `undefined
|
|
358
|
+
- **补上参数行**:「256K 上下文 · 最大输出 64K」,复用 Token Plan 花名册的 `S.modelMeta` 与同两条文案模板(`llm.contextBadge` / `llm.metaOutput`)。目录没声明该字段时**不画这一段**(`num()` 对缺失值返回 `undefined`,不兜底编数)。
|
|
323
359
|
- **倍率改为独立 chip**(`S.modelRate`,与 Token Plan 同款),`0` 显示 `free` 而不是 `×0`(零倍率是对模型的事实陈述,不是一个为零的费率);新增 `raccoon.free` 键补齐 i18n。
|
|
324
360
|
- **倍率 tooltip 不复用 `llm.rosterRateTitle`**:那句话写的是「积分消耗**伪**倍率(自定义对比用,**非官方**)」,因为 Token Plan 的倍率确实是操作者在插件里配的;而小浣熊的倍率是**网关目录直接声明的字段**,借那句 tooltip 等于给真数据贴上"编的"标签。新增 `raccoon.rateTitle`「网关目录声明的积分倍率(0 为免费)」,并加断言钉住别再用错。
|
|
325
361
|
- **`· vision` 硬编码英文改为 `llm.rosterVision`「可看图」徽章**,靠右对齐——原先那个 `" · vision"` 是拼在倍率徽章里的中文字典里的英文裸串,既没走 i18n 也没走统一徽章样式。
|
|
326
362
|
- **给列表一个框**(新增 `S.modelPanel`):与同 tab 里「已登录」块(`S.card`)同级的容器。行的分隔线样式**不变**——仓库既有原则是「section card 持有唯一的框、行不重画框」,缺的是列表这一层的容器,不是给每行描边。
|
|
327
363
|
|
|
328
|
-
`test/render.test.mjs` 补 5 条断言(150 → 155):参数行在有字段时出现、在没字段时不出现为空行、费率 chip 渲染、free 不带 `×0`,以及**思考档位必须缺席**——该 provider 注册的是 `reasoning: false`(pi-ai 发不出网关唯一有效的 `extra_body.thinking`),照抄 Token Plan 那行「思考 关闭/低/中/高」等于承诺一个 DSH
|
|
364
|
+
`test/render.test.mjs` 补 5 条断言(150 → 155):参数行在有字段时出现、在没字段时不出现为空行、费率 chip 渲染、free 不带 `×0`,以及**思考档位必须缺席**——该 provider 注册的是 `reasoning: false`(pi-ai 发不出网关唯一有效的 `extra_body.thinking`),照抄 Token Plan 那行「思考 关闭/低/中/高」等于承诺一个 DSH 选择器永远不会给的档位。
|
|
329
365
|
|
|
330
366
|
### 「接入 API」tab:卡片改名、重排、默认展开
|
|
331
367
|
|
|
@@ -337,7 +373,7 @@
|
|
|
337
373
|
|
|
338
374
|
同时修掉一处被这次重排坑到的文案漂移:`llm.rosterEmpty` 原写「在**上方**保存一次 API Key」,而它所指引的 API Key 卡已经换到**下方**——方向词在换序后必然指错,改为直接点名「API Key」卡片(中英两侧同步;`draw.off`、`llm.noKey` 那两处「上方」指的是**同卡片内**的开关与输入框,不跨卡,保持不变)。
|
|
339
375
|
|
|
340
|
-
`test/panel.test.mjs`
|
|
376
|
+
`test/panel.test.mjs` 补三条断言:三张卡的渲染顺序、默认展开集合、跨卡指引必须点卡片名而非方向词。
|
|
341
377
|
|
|
342
378
|
### 截图与市场清单对齐(`docs` 门禁新增检查 `SCREENSHOTS`)
|
|
343
379
|
|
|
@@ -345,13 +381,13 @@
|
|
|
345
381
|
|
|
346
382
|
- **清单对齐当前两张**:`assets/panel-credit.png`(「积分额度」tab)、`assets/panel-API-provider.png`(「接入 API」tab);「小浣熊」那张待补。
|
|
347
383
|
- **`docs.test.mjs` 新增检查 `SCREENSHOTS`**:清单声明的每条路径必须**真实存在于磁盘**、是图片扩展名、条目数 1–8、且为仓库根相对路径。三种破坏实测红过再还原复验绿(换回旧名 / `..` 逃逸 / 拿 `README.md` 当条目)。
|
|
348
|
-
- **`PITFALLS` 新增 §26**(条目数 25 → 26,三处引用由门禁当场抓出并同步):**清单类文件(`.json` / `.yml` / `.toml
|
|
349
|
-
- **`CONTRIBUTING` §8**
|
|
384
|
+
- **`PITFALLS` 新增 §26**(条目数 25 → 26,三处引用由门禁当场抓出并同步):**清单类文件(`.json` / `.yml` / `.toml`)不是文档,但同样是契约**——改资产名前先问「还有谁按名字引用它」。本仓库按名字引用 `assets/` 的机器消费方只有 `screenshots.json` 一处,正是「只有一处 + 又不叫 `.md`」让它成了盲区。
|
|
385
|
+
- **`CONTRIBUTING` §8** 那句「重截并推送后截图自动生效(**文件名不变**)」已修正:它藏了个未言明的前提——**改名就必须同步清单**。
|
|
350
386
|
|
|
351
387
|
### 模型花名册重排(WorkBuddy 形态)
|
|
352
388
|
|
|
353
389
|
- **行去卡内框、改用分隔线**:`modelRow` 由横向 flex 行改为纵向列(头行 + 缩进的参数行),新增 `modelRowHead` 包裹头行;徽章只标 notable 态(删「纯文本」徽章、补「额度耗尽」徽章)。工具行计数成组右置,批量按钮 32px 与搜索框等高。
|
|
354
|
-
- **每行只留会变的 per-model 事实**:参数段从「上下文 · 最大输出 · 默认思考强度」改为**本模型实际可选档位**——「思考 关闭/低/中/高/极高[/最高]」,由 Host 新导出的 `supportedThinkingLevels` 按 pi-ai `getSupportedThinkingLevels` 同一规则过滤(与 DSH 选择器同源),glm-5.2 独显「最高」。provider 级常数(默认思考强度)收进花名册头部只说一次(`llm.rosterThinkingDefault
|
|
390
|
+
- **每行只留会变的 per-model 事实**:参数段从「上下文 · 最大输出 · 默认思考强度」改为**本模型实际可选档位**——「思考 关闭/低/中/高/极高[/最高]」,由 Host 新导出的 `supportedThinkingLevels` 按 pi-ai `getSupportedThinkingLevels` 同一规则过滤(与 DSH 选择器同源),glm-5.2 独显「最高」。provider 级常数(默认思考强度)收进花名册头部只说一次(`llm.rosterThinkingDefault`),**删掉逐行重复的恒定默认档**。
|
|
355
391
|
- **`tokenSize` 修正 1049k → 1M**:千整走十进制、纯二进制走 1024、≥1M 归 M。Host 侧新增 `maxOutputLength` 投影(`0` = 未声明则整段不画,绝不猜)。
|
|
356
392
|
- **`matchMultiplier` 单一匹配器**:趋势行 ×N 与花名册 ×N 同源同值,两处显示不可能不一致。
|
|
357
393
|
|
|
@@ -365,36 +401,23 @@
|
|
|
365
401
|
|
|
366
402
|
- 账号表单标题下与 API Key 表单底部的官网链接**两种状态都显示**:无账号时「前往官网注册」,已有账号时「前往官网管理额度 / 获取 API Key」(新键 `auth.portalHint`,中英双语;URL 入 `const.ts`)。
|
|
367
403
|
|
|
368
|
-
### 思考档位收敛到「实测过 200
|
|
369
|
-
|
|
370
|
-
面板花名册每行原来把 `low/medium/xhigh` 对**所有**商汤模型都画出来,但冻结契约表
|
|
371
|
-
|
|
372
|
-
`max`
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
**2026-09-30 探针补测后**:`test/live-contract.mjs` 扩了 `reasoning_effort:low/medium`
|
|
379
|
-
探针(2s 退避;429 记 INDEFINITE 不当判读——限流是节奏问题不是参数拒绝,只有 4xx 才
|
|
380
|
-
算"不支持"的负证据)。首跑实锤 200 的格子:sensenova-6.8-flash-lite(low+medium)、
|
|
381
|
-
**deepseek-v4-flash(low+medium,你原问的那行——低中档平台真支持)**、glm-5.2(low+medium)、
|
|
382
|
-
deepseek-flash(medium)、kimi-k3(medium)→ 这些格已翻 `true`,对应面板行放出低/中档。
|
|
383
|
-
仍 INDEFINITE 的(429 rpm 窗口,非 400,保持关、重跑再翻):deepseek-v4-pro 的 low+medium、
|
|
384
|
-
deepseek-flash 的 low、kimi-k3 的 low。
|
|
385
|
-
|
|
386
|
-
测试同步:`contract` §2 加逐模型 low/medium 断言(读契约表,`true`→开、`indefinite`/`false`→关)、
|
|
387
|
-
`provider` §1(v4-flash/glm-5.2/flash-lite 的 low+medium 开、INDEFINITE 格关)、`retry` §5、
|
|
388
|
-
`routes` Q2、`render` G4(v4-flash 那行 = 关闭/低/中/高/极高)。文档同步:`API.md` 样例
|
|
389
|
-
行与字段注记、`IMPROVEMENTS.md` §7 修订、本条。
|
|
404
|
+
### 思考档位收敛到「实测过 200 才画」
|
|
405
|
+
|
|
406
|
+
面板花名册每行原来把 `low/medium/xhigh` 对**所有**商汤模型都画出来,但冻结契约表 `test/baselines/sensenova-contract.json` 里 `xhigh` 只实测过 deepseek-v4-flash(200)、`max` 只实测过 glm-5.2(200),`low`/`medium` 对任何模型都**从未实测**(代码依据只是平台 400 报错文案里出现过这两个词,而那串列表是**并集**、各模型支持面不同)——用户点了某家不支持的档就可能 400。
|
|
407
|
+
|
|
408
|
+
现把 `thinkingLevelMapFor` 改为**逐模型门控**(新常量 `PROBED_EFFORT`,数据抄自同一张冻结契约,覆盖 low/medium/high/xhigh/max 五格):`high`(平台默认,全家族实测过)保持开,`xhigh` 只对 deepseek-v4-flash 开,`max` 只对 glm-5.2 开;未收录模型默认全关。
|
|
409
|
+
|
|
410
|
+
**2026-09-30 探针补测后**:`test/live-contract.mjs` 扩了 `reasoning_effort:low/medium` 探针(2s 退避;429 记 INDEFINITE 不当判读——限流是节奏问题不是参数拒绝,只有 4xx 才算"不支持"的负证据)。首跑实锤 200 的格子:sensenova-6.8-flash-lite(low+medium)、deepseek-v4-flash(low+medium)、glm-5.2(low+medium)、deepseek-flash(medium)、kimi-k3(medium)→ 这些格已翻 `true`,对应面板行放出低/中档。仍 INDEFINITE 的(429 rpm 窗口,非 400,保持关、重跑再翻):deepseek-v4-pro 的 low+medium、deepseek-flash 的 low、kimi-k3 的 low。
|
|
411
|
+
|
|
412
|
+
测试同步:`contract` §2 加逐模型 low/medium 断言(读契约表,`true`→开、`indefinite`/`false`→关)、`provider` §1(v4-flash/glm-5.2/flash-lite 的 low+medium 开、INDEFINITE 格关)、`retry` §5、`routes` Q2、`render` G4(v4-flash 那行 = 关闭/低/中/高/极高)。文档同步:`API.md` 样例行与字段注记、`IMPROVEMENTS.md` §7 修订、本条。
|
|
390
413
|
|
|
391
414
|
### 可见性修复三连:登录态常显 + provider 注册 pending 态 + 小浣熊错误不再被开关藏起
|
|
392
415
|
|
|
393
416
|
同族问题——「状态翻成某个值后,操作入口/错误行跟着消失,用户拿不到重入路」:
|
|
394
417
|
|
|
395
|
-
- **登录态与账号编辑器无条件可见**(中间态不再是死路):此前「连接商汤控制台」区卡只在 `hasAccount || needsAccount` 时出现——中间态(已点过「清除账号」、grant 仍在静默续期)下整卡消失,要等 refresh_token 彻底失效才重新拿到重输入口。现改为**只要快照携带 auth
|
|
396
|
-
- **provider 注册 pending 态**:开关已开、服务在、无 error,但注册没落地时,原文案谎报「未注册——勾选上方开关」(指向已勾选的开关);新增 `llm.registeredPending` 直说 pending。同时修分支序:具体失败(providerError)优先于能力缺失(noService
|
|
397
|
-
- **小浣熊 tab 注册状态行不再被开关门控**:providerError 原来只在 `enabled === true` 时渲染,开关一关报错就消失;现 `state !== null`
|
|
418
|
+
- **登录态与账号编辑器无条件可见**(中间态不再是死路):此前「连接商汤控制台」区卡只在 `hasAccount || needsAccount` 时出现——中间态(已点过「清除账号」、grant 仍在静默续期)下整卡消失,要等 refresh_token 彻底失效才重新拿到重输入口。现改为**只要快照携带 auth 块就常显**,积分额度页底部永远有该卡(默认折叠、一键展开)。头部「需要重新登录」chip 的 tooltip 在 Host 没给 reason 时回落 guidance 文案。
|
|
419
|
+
- **provider 注册 pending 态**:开关已开、服务在、无 error,但注册没落地时,原文案谎报「未注册——勾选上方开关」(指向已勾选的开关);新增 `llm.registeredPending` 直说 pending。同时修分支序:具体失败(providerError)优先于能力缺失(noService)。
|
|
420
|
+
- **小浣熊 tab 注册状态行不再被开关门控**:providerError 原来只在 `enabled === true` 时渲染,开关一关报错就消失;现 `state !== null` 即渲染。
|
|
398
421
|
- **构建修复**:`qr.ts` 内 8 处 `x?.y = v`(可选链左值赋值)是解析错误,tsdown 直接挂掉——改为先索引后赋值。
|
|
399
422
|
- **测试**:`test/panel.test.mjs` B2 组翻转(中间态/死 grant 态都钉 `canManageAccount === true`);`panel-decision.js` 镜像同步去门控;`render.test.mjs` 新增 pending 态与 error 优先序 2 项 pin。
|
|
400
423
|
|
|
@@ -402,24 +425,22 @@ deepseek-flash 的 low、kimi-k3 的 low。
|
|
|
402
425
|
|
|
403
426
|
上报现象:全新装好插件打开面板,看不到三个 tab,整页只有一个登录表单——**API Key tab 和小浣熊 tab 也一起消失了**,尽管它们一个根本不读控制台、一个连的是另一个上游。
|
|
404
427
|
|
|
405
|
-
根因是**结构性设计缺陷,不是移植失误**(源版同样存在):控制台探针 `overview` 被当作**唯一致命源**,失败即整个快照走 `ok:false`;客户端又把 tab 栏放在 `data`
|
|
406
|
-
|
|
407
|
-
两层修复 + 一条诚实性补丁:
|
|
428
|
+
根因是**结构性设计缺陷,不是移植失误**(源版同样存在):控制台探针 `overview` 被当作**唯一致命源**,失败即整个快照走 `ok:false`;客户端又把 tab 栏放在 `data` 分支里,于是「控制台没登录」这一件事把三个互相独立的模块全埋了。
|
|
408
429
|
|
|
409
|
-
- **Host(`snapshot-aggregate.ts`)**:`overview` 从致命源降级为五个可降级源之一(`soft()`),新增 `quota.consoleConnected`;失败原因(`not_configured` / `auth_error` / `console_error`)走 `quota.error.code`。它仍**串行先取**——401
|
|
430
|
+
- **Host(`snapshot-aggregate.ts`)**:`overview` 从致命源降级为五个可降级源之一(`soft()`),新增 `quota.consoleConnected`;失败原因(`not_configured` / `auth_error` / `console_error`)走 `quota.error.code`。它仍**串行先取**——401 时先换新令牌,后面批量才拿活令牌出门。
|
|
410
431
|
- **客户端(`panel-page.ts`)**:tab 栏从 `data` 分支提到顶层,**第一帧就渲染**;`data === null` 时登录表单变成额度 tab 的**内容**而不是整页。控制台未连接时额度 tab 内点名原因,并一次性自动展开账号卡(用 `useRef` + `useEffect`,因为 `open` 是受控 prop,写成 `open: openSections.account || needsSetup` 会让卡片再也收不起来)。
|
|
411
|
-
- **诚实性补丁**:`quota.totals` 在读不到时是 **`null`,不是零值块**。`parseUsageOverview(null)` 的每个计数器都经 `countOf` 落到 `0`,直接渲染会把一次读取失败伪装成「0 次请求 / 0 token
|
|
432
|
+
- **诚实性补丁**:`quota.totals` 在读不到时是 **`null`,不是零值块**。`parseUsageOverview(null)` 的每个计数器都经 `countOf` 落到 `0`,直接渲染会把一次读取失败伪装成「0 次请求 / 0 token」——把失败变成测量。
|
|
412
433
|
- **顺带暴露的副作用**:未登录的 Host 现在也会去取**公开套餐目录**(它是控制台静默时唯一还剩的额度内容),`test/wiring.test.mjs` 此前从未 stub 过它,已补。
|
|
413
434
|
- **测试**:`routes` +8、`wiring` +2、`e2e` +2、`render` +2(含「第一帧就带三个 tab」的回归);`docs/API.md` / `ARCHITECTURE.md` §3 §5 同步。客户端两个 tab 的行为未变,只是重新可达。
|
|
414
435
|
|
|
415
436
|
**上线实测又挖出一个缺口(同日补)**:重启 web 后快照确实变成 `ok:true` / `consoleConnected:false` / `totals:null`,但 `quota.error.code` 是 **`login_rejected`**——而 `GUIDANCE_BY_CODE` 只覆盖了 5 个码。根因是这次降级的连带效应:`AUTH_FAILURE_CODES` 里 13 个码现在**都能**以 `quota.error.code` 抵达面板(以前它们只会变成整份 `ok:false`,面板只读顶层 `code`),表却没跟着长。后果是面板退化成泛泛的「控制台未连接」,丢掉「账号需要重新输入」这个唯一有用的信息。
|
|
416
437
|
|
|
417
438
|
- `GUIDANCE_BY_CODE` 补齐到 `AUTH_FAILURE_CODES ∪ NO_LOGIN_CODES` 全覆盖:令牌侧(`auth_error` / `jwt_expired` / `no_refresh_token` / `refresh_rejected` + 四个已死的 OIDC 期码)统一给「令牌失效,重登一次」;账号侧 `not_configured` / `missing_credentials` 给「还没配账号」;四种凭据拒绝**复用表单自己的文案**(`auth.badCredentials` / `auth.locked` / `auth.rateLimited` / `auth.verification`)——它们的下一步动作各不相同(重输 / 等解锁 / 等限频 / 完成人工验证),塌成一句「登录失败」会对其中三种给出错误建议。
|
|
418
|
-
- **补上反向检查**(`test/panel.test.mjs`):此前只断言「表里的 key
|
|
439
|
+
- **补上反向检查**(`test/panel.test.mjs`):此前只断言「表里的 key 都是真码」,现在同时断言「能抵达面板的码都有文案」。
|
|
419
440
|
|
|
420
441
|
### 修复:浏览器把保存的商汤账号填进模型搜索框
|
|
421
442
|
|
|
422
|
-
上报现象:密码管理器把 SenseNova 控制台的账号自动填进插件的输入框,**连「接入 API」tab
|
|
443
|
+
上报现象:密码管理器把 SenseNova 控制台的账号自动填进插件的输入框,**连「接入 API」tab 的模型搜索框也被塞了账号**。
|
|
423
444
|
|
|
424
445
|
**不是关键词,是我们主动声明的,而且同 origin 上还有第二个一模一样的表单**:
|
|
425
446
|
|
|
@@ -429,8 +450,8 @@ deepseek-flash 的 low、kimi-k3 的 low。
|
|
|
429
450
|
|
|
430
451
|
修法:给模型搜索框加 `autoComplete="off"` 与 `name="model-search"`。**账号表单的 `username`/`current-password` 语义刻意保留**(浏览器记住 Agnes 账号是想要的能力),本次只堵「去表单外找用户名」这条路径。
|
|
431
452
|
|
|
432
|
-
- `render.test.mjs` 新增 I2 组:渲染全部 7 个可能含输入框的组件,断言每个可填文本输入框要么 `autoComplete="off"
|
|
433
|
-
- 机制与证据写进 `docs/PITFALLS.md` §27
|
|
453
|
+
- `render.test.mjs` 新增 I2 组:渲染全部 7 个可能含输入框的组件,断言每个可填文本输入框要么 `autoComplete="off"`、要么声明凭据角色,并把「唯一声明凭据角色的是账号表单」钉死。
|
|
454
|
+
- 机制与证据写进 `docs/PITFALLS.md` §27。
|
|
434
455
|
|
|
435
456
|
### 修复:额度已经正常显示,头部却一直挂「需要重新登录」
|
|
436
457
|
|
|
@@ -439,45 +460,46 @@ deepseek-flash 的 low、kimi-k3 的 low。
|
|
|
439
460
|
- **根因**:`state.lastError` 由 `getToken()` 的 `acquire()` 路径写入、也由那条路径清除,但 `getToken()` 在缓存令牌仍然新鲜时会**提前 return**,根本不进 `acquire()`;而面板上的手动登录是**直接存令牌**的,从不经过 `acquire()`。一次失败的自动重登写上这个字符串,用户手动登录成功后节流记录被清了、**这个字符串没清**,新令牌又足够新鲜——清除路径再也不会跑到。
|
|
440
461
|
- **修法**:不逐个写入点补清除,而是把上报钉在结果上——`state()` 里 `error: isFresh(stored) ? null : …`。`auth.error` 的契约是「面板该向用户要账号」,持有一个控制台没拒绝过的令牌时就不存在当前错误。
|
|
441
462
|
- **同族**:`AccountForm` 的「已保存并登录,正在读取额度…」也从不落地(`saved` 只被「清除账号」复位),改由父组件传 `hasSnapshot` 门控——独立表单照旧显示,面板内嵌不再显示。**这条没有测试覆盖**(测试替身的 `useState` 只返回初值,进不去 `saved`),是记录在案的缺口。
|
|
442
|
-
- **测试**:`store.test.mjs` 8c 组补两处断言(parked
|
|
463
|
+
- **测试**:`store.test.mjs` 8c 组补两处断言(parked 期间必须报错、改正之后必须不报);冻结基线零漂移。机制写进 `docs/PITFALLS.md` §28。
|
|
443
464
|
|
|
444
465
|
### 运维诊断 doctor(PITFALLS §22 的欠账)
|
|
445
466
|
|
|
446
467
|
回答「这台机器的 provider / 出图开关到底开没开」——此前唯一答案在一个 JSON 状态文件里,不在任何配置文件、任何路由、任何 CLI。
|
|
447
468
|
|
|
448
|
-
- **新增 `src/host/doctor.ts`(peer-free 纯读层)+ `tools/doctor.mjs` CLI**:读 `$DSH_HOME/state/<name>/` 与每个 `<profile>/<name>/` 下的 `provider.json` / `draw.json` / `catalog.json`,报「面板保存值 >
|
|
449
|
-
-
|
|
450
|
-
- **测试**:`test/doctor.test.mjs`(23
|
|
469
|
+
- **新增 `src/host/doctor.ts`(peer-free 纯读层)+ `tools/doctor.mjs` CLI**:读 `$DSH_HOME/state/<name>/` 与每个 `<profile>/<name>/` 下的 `provider.json` / `draw.json` / `catalog.json`,报「面板保存值 > 部署默认值」的生效开关、模型允许清单、以及「文件存在但读不成」时**点名**是哪个文件。`npm run doctor`(人读)/ `npm run doctor:json`(机器读)。
|
|
470
|
+
- 它不写任何文件、不碰凭据,只在磁盘上读,Host 没起也能跑。
|
|
471
|
+
- **测试**:`test/doctor.test.mjs`(23 项,离线门禁),进 `npm test` 与 CI offline 档。
|
|
451
472
|
|
|
452
473
|
### 边界裁定:第二上游正式纳入界内(不变量 3 修订)
|
|
453
474
|
|
|
454
475
|
Token Plan 与小浣熊同为商汤旗下产品线,`sensenova` 这个名头名副其实,第二上游不再是「待定方向的破例」。
|
|
455
476
|
|
|
456
|
-
- **`ARCHITECTURE.md` §5 不变量 3 修订**:划线依据从「只吸收与商汤 **Key/账号线**强相关的能力」改为「只吸收与**商汤(SenseTime)产品线**强相关的能力」。原划法按 Key 域名 /
|
|
457
|
-
- **新增 §5.5**
|
|
477
|
+
- **`ARCHITECTURE.md` §5 不变量 3 修订**:划线依据从「只吸收与商汤 **Key/账号线**强相关的能力」改为「只吸收与**商汤(SenseTime)产品线**强相关的能力」。原划法按 Key 域名 / 认证域划线,会把同一厂商的姐妹产品线误判到界外。另两条不变量(opt-in 默认关、凭据红线)不变。
|
|
478
|
+
- **新增 §5.5** 记录裁定本身,**三条独立举证**:中证网 2026-07-19(U1 Pro 能力「在**商汤旗下的**产业级 AI『小浣熊』及 Seko 中已得到深度验证」)、商汤官方稿件 2026-09-21(「**商汤小浣熊 Raccoon Work**」由商汤科技打造)、以及本仓库既有措辞(ROADMAP §6.1 早写着「接入**商汤小浣熊**桌面 App 模型」)。
|
|
458
479
|
- **它与 Token Plan 的确切关系**(后来人据此判断还能不能再放宽):**同一厂商、不同产品线、认证域互不相通、积分口径互不算**。所以实现上必须继续是独立凭据 / 独立 publisher / 独立 provider id——共享任何一样都等于把两条产品线焊死。它是**第二上游**,与 §6.1.1 判死的**第二登录路径**不是同一件事。
|
|
459
|
-
- **防止口子被开成无限大**:本次放宽只覆盖「同一厂商下的产品线」,**跨厂商聚合**(codearts 那类一套形态融 N 家)依旧在界外。以后每纳入一条新产品线必须同时落三条——① 外部可核的厂商举证;② 与 Token Plan 的具体关系,尤其是积分与认证域是否通用;③ 齐全后才允许以 opt-in
|
|
460
|
-
- **同步**:`ROADMAP.md` §6.1.1 的「须先定方向——不默认吸收」改为**方向已定**;`AGENTS.md`
|
|
480
|
+
- **防止口子被开成无限大**:本次放宽只覆盖「同一厂商下的产品线」,**跨厂商聚合**(codearts 那类一套形态融 N 家)依旧在界外。以后每纳入一条新产品线必须同时落三条——① 外部可核的厂商举证;② 与 Token Plan 的具体关系,尤其是积分与认证域是否通用;③ 齐全后才允许以 opt-in 默认关的形态进入树干。
|
|
481
|
+
- **同步**:`ROADMAP.md` §6.1.1 的「须先定方向——不默认吸收」改为**方向已定**;`AGENTS.md` 第三条事实改为「同属商汤旗下,但认证域不相通」。
|
|
461
482
|
|
|
462
483
|
### 第二上游补复测 + 文档追平(一次自审掀开的三处「文档与代码分头走路」)
|
|
463
484
|
|
|
464
|
-
- **README 不再说谎**(它进 npm 的 `files` 白名单,是用户装完后读到的唯一说明书):此前 ① **零处**提到当期头条特性——第三个 tab「小浣熊」;② 三处仍写「侧边栏」,而代码早已迁到 Plugins
|
|
485
|
+
- **README 不再说谎**(它进 npm 的 `files` 白名单,是用户装完后读到的唯一说明书):此前 ① **零处**提到当期头条特性——第三个 tab「小浣熊」;② 三处仍写「侧边栏」,而代码早已迁到 Plugins 页,会让人**找不到入口**;③ 仍挂着「面板**只读**」的承诺,而它已经能注册推理通道、挂出图工具、写 DSH settings。三处全部改正,并补齐「出图工具」与「第二个上游:小浣熊」两个真正的能力小节(含 provider id `sensenova-raccoon`、工具挂载需重启的事实)。
|
|
465
486
|
- **`cordis.patch.yml` 头注释的同类漂移**:第 3 行同款地写着 "sidebar panel",同样进 npm 包,一并改掉。
|
|
466
|
-
- **第二上游的网关契约补复测**(新增 `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
|
|
487
|
+
- **第二上游的网关契约补复测**(新增 `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 的那份清单」属**误判,已更正**。
|
|
467
488
|
- **护栏:`docs.test.mjs` 新增两条语义检查**——原有的全是形式校验(链接 / 表格去重 / 行数上限),对面「文档断言的事是否与代码一致」毫无感知:
|
|
468
|
-
- **检查 `README_TABS`**:README 必须覆盖面板的每一个 tab。tab 名单从 `panel-page.ts` 的 `activeTab` 联合类型派生、文案从 `i18n.ts` 的 `tab.<id>`
|
|
489
|
+
- **检查 `README_TABS`**:README 必须覆盖面板的每一个 tab。tab 名单从 `panel-page.ts` 的 `activeTab` 联合类型派生、文案从 `i18n.ts` 的 `tab.<id>` 派生,**不写死任何名字**。
|
|
469
490
|
- **检查 `SELF_DESCRIPTION`**:README 与 `cordis.patch.yml` 声称的 UI 位置必须与 `src/client/*.ts` 实际注册的槽位一致。
|
|
470
491
|
- 两条都做过「故意破坏 → 必须红 → 还原 → 复绿」的双向验证(删光「小浣熊」精确报出 `raccoon(面板文案「小浣熊」)`;改回事故原文报「声称面板在侧边栏但没有 sidebar 槽位注册」)。
|
|
471
492
|
- **PITFALLS 新增 §24(GET 探活会误判)与 §25(形式门禁全绿 ≠ 文档说实话)**,总数 23 → 25;三处散落的过期引用(`README.md` / `AGENTS.md` / `docs/README.md`)同步——这批数字正是由新门禁当场揪出来的。
|
|
472
493
|
|
|
473
494
|
### 文档修正:撤销 ROADMAP §0 被证伪的前提
|
|
474
495
|
|
|
475
|
-
- [ROADMAP.md](docs/ROADMAP.md) §0 与 §2 引言原写「本插件已是双 profile 的 `agent-default-model`——即这台机器的**默认推理通道**,故障域已升级为推理可用性」。该论断 2026-09-29 已被研究原稿 §1.2 撤销(`agent-default-model` 是宿主的选择记录服务,原引用不可复现;撤销原文现见 [ARCHIVE-BOUNDARY-DECISIONS.md](docs/ARCHIVE-BOUNDARY-DECISIONS.md) A1),但 ROADMAP 未同步。现改为「**能力事实**:可注册 provider `sensenova-token-plan`;是否默认通道由 profile 与用户模型选择决定;一旦某 profile
|
|
496
|
+
- [ROADMAP.md](docs/ROADMAP.md) §0 与 §2 引言原写「本插件已是双 profile 的 `agent-default-model`——即这台机器的**默认推理通道**,故障域已升级为推理可用性」。该论断 2026-09-29 已被研究原稿 §1.2 撤销(`agent-default-model` 是宿主的选择记录服务,原引用不可复现;撤销原文现见 [ARCHIVE-BOUNDARY-DECISIONS.md](docs/ARCHIVE-BOUNDARY-DECISIONS.md) A1),但 ROADMAP 未同步。现改为「**能力事实**:可注册 provider `sensenova-token-plan`;是否默认通道由 profile 与用户模型选择决定;一旦某 profile 选它作默认,故障域才从面板升级为推理可用性(条件性爆炸半径)」。
|
|
476
497
|
|
|
477
498
|
### 文档与仓库纪律
|
|
478
499
|
|
|
479
500
|
- **消灭「离线 N 套件」数字漂移源**:文档不再背书套件数量与枚举(`AGENTS.md` 曾写十七套件、`DSH-PLUGIN.md` 曾列 17 项清单,raccoon/doctor 套件加入后双双过期)——套件清单与链的唯一事实源收敛到 `package.json scripts.test`(已有 `package.test.mjs` 钉磁盘 ↔ 链 ↔ CI 一致性),文档只指事实源不复制数字。
|
|
480
501
|
- **现状模块引用 `.js` → `.ts` 全量对齐**(64 处 / 9 文件):只改「现状引用」,保留「历史动作 / 研究档案 / 产物 / 外部」四类原文。
|
|
502
|
+
- **反模式归档**:用户锐评「恒定默认档逐行重复 = 噪音」,该反模式记于 `docs/ARCHIVE-IMPROVEMENTS-2026-09.md` §7(2026-10-05 归档)。
|
|
481
503
|
|
|
482
504
|
### 仓库结构规范化:src/ 全源码,lib/ 纯产物
|
|
483
505
|
|
|
@@ -486,7 +508,7 @@ Token Plan 与小浣熊同为商汤旗下产品线,`sensenova` 这个名头名
|
|
|
486
508
|
|
|
487
509
|
### 模态判定地基(modality.ts):出图 / 视频模型识别统一为单一出处
|
|
488
510
|
|
|
489
|
-
出图工具认不出模型的根因是「模态判定」两路分家、又都没拿到字段:Agnes 网关的 `/v1/models` 条目只带 `id/object/created/owned_by/supported_endpoint_types`,**没有任何模态字段**(真机确证 2026-10-01)。同一缺失让两个判定朝相反方向失手——`isImageGenModel` 严格方向(缺字段 = 不是出图模型)导致 `agnes_draw_image` 选不出候选,面板报「暂无出图模型」;`isChatModel` 宽松方向(缺字段 = 对话)把 4 个 image/video 模型全挂进对话选择器,一选就 400
|
|
511
|
+
出图工具认不出模型的根因是「模态判定」两路分家、又都没拿到字段:Agnes 网关的 `/v1/models` 条目只带 `id/object/created/owned_by/supported_endpoint_types`,**没有任何模态字段**(真机确证 2026-10-01)。同一缺失让两个判定朝相反方向失手——`isImageGenModel` 严格方向(缺字段 = 不是出图模型)导致 `agnes_draw_image` 选不出候选,面板报「暂无出图模型」;`isChatModel` 宽松方向(缺字段 = 对话)把 4 个 image/video 模型全挂进对话选择器,一选就 400。
|
|
490
512
|
|
|
491
513
|
- **新增 `src/host/modality.ts` 作为模态判定的唯一出处**,三级解析:`output_modalities` 字段优先(平台补字段即自动生效)→ `agnes-image-*` / `agnes-video-*` 名称段兜底(只匹配完整段,不重蹈 `dsh-draw-router` 的 `/u1-fast/i` 子串漏判)→ 默认 `text`。`isImageGenModel` 与 `isChatModel` 改为共用这一个函数,矛盾由构造消除而非靠约定维持。
|
|
492
514
|
- **真实目录验证**:出图候选 0 → 2(自动选中 `agnes-image-2.1-flash`);对话名单 7 → 3。出图端点本身无需改动——真机实测 `POST /v1/images/generations` 返回 `data[0].url`,与 `parseDrawResponse` 已对齐。
|
|
@@ -495,22 +517,22 @@ Token Plan 与小浣熊同为商汤旗下产品线,`sensenova` 这个名头名
|
|
|
495
517
|
|
|
496
518
|
### 出图工具面板开关(drawEnabled)
|
|
497
519
|
|
|
498
|
-
与 provider 开关同机制的「面板开关 +
|
|
520
|
+
与 provider 开关同机制的「面板开关 + 立即生效」:
|
|
499
521
|
|
|
500
522
|
- **面板新增「出图工具」卡片**(`client.js` 的 `DrawSwitch` 控件):勾选保存后写入插件私有状态文件 `$DSH_HOME/state/<plugin>/draw.json`,与 `provider-store.js` 走完全相同的完整性纪律。优先级:面板保存值 > `cordis.patch.yml` 的 `drawEnabled`;从未动过面板的部署,行为与 `false` 一致。
|
|
501
523
|
- **新增 `POST /api/<name>/draw` 路由**(`routes.js`):与 `/provider` 同一信任形状(同源围栏 + 4 KB body 上限),`{ enabled: true|false }` 或 `{ forget: true }`。
|
|
502
|
-
- **快照 `llm.drawEnabled` / `llm.drawSource`**:`snapshot-aggregate.js` 在 llm
|
|
524
|
+
- **快照 `llm.drawEnabled` / `llm.drawSource`**:`snapshot-aggregate.js` 在 llm 块里回显出图开关的生效值与来源。
|
|
503
525
|
- **`lifecycle.js` 的 `registerDrawTool` 改读生效值**:不再直接读 `settings.drawEnabled`,而是「面板保存值 ?? 配置默认值」。工具的实际挂载/缺席发生在**下一个 Host 启动**时(agent tools 没有 unregister 语义),开关值本身是立即生效的。
|
|
504
526
|
- **测试**:`test/provider.test.mjs` 新增 draw-store 纯逻辑组(归一、读写、版本拒绝、损坏忽略、forget);`test/routes.test.mjs` 新增 R 组(8 项,覆盖 GET/POST/forget/跨域围栏/跨 remount 持久化/配置回退);`test/wiring.test.mjs` 路由计数从 5 更新为 6。
|
|
505
527
|
|
|
506
528
|
### 视频工具面板开关(videoEnabled):V2.0 单体系,异步任务制
|
|
507
529
|
|
|
508
|
-
与出图对称,新增可选的视频生成 agent
|
|
530
|
+
与出图对称,新增可选的视频生成 agent 工具(默认关):
|
|
509
531
|
|
|
510
532
|
- **面板新增「视频工具」卡片**(`client.js` 的 `VideoSwitch` 控件):与 `DrawSwitch` 共用同一私有 `ToolSwitch` 体,保证两个工具的降级阶梯与状态不可能分叉。勾选保存写入 `$DSH_HOME/state/<plugin>/video.json`,优先级:面板保存值 > `cordis.patch.yml` 的 `videoEnabled`。
|
|
511
533
|
- **新增 `POST /api/<name>/video` 路由**(`routes.js`):与 `/draw` 共用同一处理器 `registerToolSwitchRoute`,区别只在闭包捕获的 store 与请求体键名(`drawModelId` / `videoModelId`)——键名承重,写错会让两工具静默共用一个模型;`test/routes.test.mjs` 组 S 专门钉隔离。
|
|
512
|
-
- **Host 半边 `src/host/video.ts`(V2.0 单体系,不无脑移植上游)**:走 `POST {apiBase}/videos` 建任务 → 轮询 `{host}/agnesapi` → 取 `url` 的完整状态机;`VIDEO_MAX_POLLS = 1000` 防时钟不前进时空转;**刻意不设 30s
|
|
513
|
-
- **只覆盖 V2.0 参数体系**(`width`/`height`/`num_frames`(须 8n+1)/`frame_rate`/`seed`/`negative_prompt`/`image`),与 2.5 系列(`mode`/`seconds`/`size`/`aspect_ratio`)互斥;`pickVideoModel` 只在 V2.0 家族选,2.5 进 `video25ModelIds`
|
|
534
|
+
- **Host 半边 `src/host/video.ts`(V2.0 单体系,不无脑移植上游)**:走 `POST {apiBase}/videos` 建任务 → 轮询 `{host}/agnesapi` → 取 `url` 的完整状态机;`VIDEO_MAX_POLLS = 1000` 防时钟不前进时空转;**刻意不设 30s 冷却门**。`buildVideoBody` 对非法显式值**抛错而非夹取**(夹取帧数会静默改变视频时长,分钟级生成后才发现)。
|
|
535
|
+
- **只覆盖 V2.0 参数体系**(`width`/`height`/`num_frames`(须 8n+1)/`frame_rate`/`seed`/`negative_prompt`/`image`),与 2.5 系列(`mode`/`seconds`/`size`/`aspect_ratio`)互斥;`pickVideoModel` 只在 V2.0 家族选,2.5 进 `video25ModelIds` 单独上报面板说明。
|
|
514
536
|
- **快照新增视频键**:`llm.videoEnabled` / `videoSource` / `videoModel` / `videoCandidateCount` / `videoCandidateIds` / `video25ModelIds`;`progress: 0` 走 `parseVideoQuery` 直接 `Number()` 读取(不能用坚持正值的 `num()`,否则合法 0% 被读成缺失)。
|
|
515
537
|
- **配套配置**:`cordis.patch.yml` 新增 `videoEnabled` / `videoModelId` / `videoTimeoutMs`(≥30000) / `videoWidth`(1152) / `videoHeight`(768) / `videoNumFrames`(121) / `videoFrameRate`(24) 七项;`src/host/types.ts` 的 `HostDeps` 补 `videoFetch`。
|
|
516
538
|
- **文档**:`AGNES-API.md` §7.5 整段重写为 V2.0 请求体字段与校验规则;`API.md` 补快照视频键与 `/video` 路由;`SETUP.md` 补 7 个视频配置字段;`PROVIDER-HOT-RELOAD.md` 新增 §8;`ARCHITECTURE.md` §5.4 补「视频吸收」;`README.md` 补视频工具段;`PITFALLS.md` 新增 §29(两站凭据不互通)/ §30(视频异步任务制)/ §31(`progress:0` 不能用 `num()`)。
|
|
@@ -520,8 +542,8 @@ Token Plan 与小浣熊同为商汤旗下产品线,`sensenova` 这个名头名
|
|
|
520
542
|
|
|
521
543
|
几处「不报错、但会误导或压平层级」的显示。
|
|
522
544
|
|
|
523
|
-
- **每模型消耗柱状图补图例**:柱子按「最高消耗者」归一化,top
|
|
524
|
-
- **返赠余额从药丸改为指标数字**:`返赠余额 327,904` 此前裹在与「通用池/专属池」同款的圆角药丸里,一个大数字被压成和静态类型标签同等权重的装饰。改为卡头右侧的 tabular
|
|
545
|
+
- **每模型消耗柱状图补图例**:柱子按「最高消耗者」归一化,top 模型永远填满轨道——它回答的是「谁在烧积分」,但满格会被误读成「这个模型快触顶」。卡片底部补一行说明「柱长按最高消耗相对显示,非占总额度比例」。
|
|
546
|
+
- **返赠余额从药丸改为指标数字**:`返赠余额 327,904` 此前裹在与「通用池/专属池」同款的圆角药丸里,一个大数字被压成和静态类型标签同等权重的装饰。改为卡头右侧的 tabular 数字。
|
|
525
547
|
- **注册成功不再常驻绿色**:「已向 DSH 注册提供方…」是静止常态,长期亮 `state-success-primary` 会让人误以为刚发生了好事。收敛为中性次要文字,绿色只留给「已保存」这类瞬时反馈。
|
|
526
548
|
- **去掉最内层子卡的冗余边框**:section 卡→池卡→双子窗三层等宽 `border-l1` 互相抵消、压平层级。最内层子窗改为纯靠更深的背景面(layer-2)浮起,边框只留两层。
|
|
527
549
|
- **API Key 字段标题去重**:「模型接入(API Key)」区块头与卡内输入框标签原本同名重复,标签改为「API Key」。
|
package/README.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# dsh-connect-agnes-token-plan
|
|
2
2
|
|
|
3
|
-
把 Agnes 接进 DSH
|
|
3
|
+
把 Agnes 接进 DSH:**Plugins 页**的插件卡(三个 tab),外加**会话输入框右侧的一枚用量胶囊**。**DSH** 即 **DeepSeek Harness**;**Agnes**(爱思)是全模态大模型平台,本插件对接其**控制台 API** 与**推理 API**。
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
> **第一次读这个仓库?先看这三句。**
|
|
7
7
|
>
|
|
8
|
-
> 1. **这是给 DeepSeek Harness
|
|
8
|
+
> 1. **这是给 DeepSeek Harness 用的插件**,不是独立应用;面板入口在 DSH 的 **Plugins 页**那张卡上(三个 tab,见下),另有一枚会话内的用量胶囊(见「对话框用量胶囊」)。
|
|
9
9
|
> 2. **三种「红」是正常的,不是回归**:① `test/wiring.test.mjs` 等 peer 套件报 `cannot resolve the peer dependency` —— 那是 DSH runtime 自带的包不在本仓库,属环境问题,先查 `test/peer-roots.mjs`;② 没装 `dsh` CLI 时 e2e 会 SKIP,属预期;③ 若在 **23:00–00:00** 之间单独跑 `render.test.mjs` 报红,那是历史上的午夜窗口缺陷(已在 0.10.0 修复,见 [docs/PITFALLS.md](docs/PITFALLS.md) §48),当前安装版本已含,无需升级。
|
|
10
10
|
> 3. **见到「奇怪」的写法先别定罪**——本仓多数刻意的取舍都在 [docs/PITFALLS.md](docs/PITFALLS.md) / [docs/ADR.md](docs/ADR.md) 有明文出处。**动手前先 grep 一遍 docs/**。
|
|
11
11
|
>
|
|
@@ -58,6 +58,14 @@
|
|
|
58
58
|
|
|
59
59
|
注意:检测不到登录态时,面板会逐条列出探测过哪些文件、各自为什么没成(「没装 App」「解不开密」「会话里没有令牌」是三种不同的处理);
|
|
60
60
|
|
|
61
|
+
## 对话框用量胶囊(自动出现)
|
|
62
|
+
|
|
63
|
+
输入框右侧会出现一枚用量胶囊,**画哪条上游的额度由当前会话选中的模型决定**,前缀写明是谁的:选中 `agnes-token-plan` 的模型显示控制台的 **5 小时 / 本周**已用百分比(前缀 `Token Plan`);选中 `agnescode`(桌面端)的模型显示那套**积分余额**(前缀 `AgnesCode`)。圆点分级(绿 / 黄 / 红 / 灰),余下的细节——重置时刻、账号昵称与时效 / 永久拆分、以及「为什么没有数字」——都在悬停提示里。
|
|
64
|
+
|
|
65
|
+
- 读数与面板**同源**:控制台百分比优先用平台自己报的 `usage_pct`、缺失才回落 `已用 / 上限`,**不做钳制**(超额窗口就显示 >100%,那是事实);桌面端画的是**存量**,所以**不造百分比**——网关只公布积分,没有「上限」可以当分母;
|
|
66
|
+
- 两条上游**互不借用**:`agnescode` 的会话只读它自己的路由、绝不画控制台窗口,反之亦然;切到**别的 provider**(其它插件)的模型时胶囊直接消失,也不再发任何请求;
|
|
67
|
+
- 读不到时**保留上一次数字并标「上次数据」**,不会清零或伪装成 0%;余额里的 `0` 是「烧完了」的读数(红色告警),`—` 才是「这次没读到」——这个区别是刻意的。
|
|
68
|
+
|
|
61
69
|
## 边界
|
|
62
70
|
|
|
63
71
|
- 面板**不代你操作账务**——不改套餐、不代扣额度、不碰 Key 明文;数据来自 Agnes 控制台自己的 API,与网页控制台口径一致。
|
|
@@ -104,7 +112,7 @@ npm run doctor:json # 机器读:JSON(可进你的巡检 / 工单脚本
|
|
|
104
112
|
- [docs/API.md](docs/API.md) — 路由与控制台端点
|
|
105
113
|
- [docs/AGNES-API.md](docs/AGNES-API.md) — Agnes 接口全集(控制台额度侧 + 推理侧)
|
|
106
114
|
- [docs/TESTING.md](docs/TESTING.md) — 测试体系
|
|
107
|
-
- [docs/PITFALLS.md](docs/PITFALLS.md) — 真实踩坑(
|
|
115
|
+
- [docs/PITFALLS.md](docs/PITFALLS.md) — 真实踩坑(56 条)
|
|
108
116
|
- [CHANGELOG.md](CHANGELOG.md) — 版本变化
|
|
109
117
|
|
|
110
118
|
AI 协作会话请先读 [AGENTS.md](AGENTS.md)。人类贡献者先读 [SETUP.md](docs/SETUP.md) 与 [ARCHITECTURE.md](docs/ARCHITECTURE.md) §2 理解结构与改动代价,改代码前再读 [AGENTS.md](AGENTS.md) 的红线与 [TESTING.md](docs/TESTING.md) 的 `npm test` 门禁。
|