dsh-tap 0.20.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/AGENTS.md +99 -0
- package/CHANGELOG.md +751 -0
- package/LICENSE +21 -0
- package/README.en.md +59 -0
- package/README.md +256 -0
- package/cordis.patch.yml +385 -0
- package/core/bridge.js +698 -0
- package/core/json-store.js +91 -0
- package/core/rotation.js +108 -0
- package/core/usage-meter.js +176 -0
- package/docs/diagnosis-cache-quota.md +181 -0
- package/docs/diagnosis-qoder-flash.md +67 -0
- package/docs/diagnosis-trae-3003.md +302 -0
- package/docs/goals/bridge-port-host-split.md +91 -0
- package/docs/goals/desktop-adaptation.md +106 -0
- package/docs/goals/qoder-cn-provider-design.md +308 -0
- package/docs/goals/settings-card-ux-redesign-plan.md +1680 -0
- package/docs/goals/settings-card-ux-redesign.md +162 -0
- package/docs/goals/trae-agent-v3.md +41 -0
- package/docs/goals/trae-work-cn-repair.md +44 -0
- package/docs/goals/v0.8-/351/242/235/345/272/246/345/217/257/350/247/201-/346/250/241/345/236/213/345/212/250/346/200/201/345/214/226-/345/244/232/346/234/215/345/212/241/345/225/206.md +85 -0
- package/docs/pitfalls.md +105 -0
- package/docs/reverse/trae-cloud-api.md +218 -0
- package/docs/reverse/trae-model-catalog.md +129 -0
- package/docs/reverse/traework-cn.md +520 -0
- package/docs/rules/STATE.md +198 -0
- package/docs/rules/content-moderation.md +54 -0
- package/docs/rules/dev-role-boundary.md +94 -0
- package/docs/rules/extra-providers.md +42 -0
- package/docs/rules/gateway-facts.md +91 -0
- package/docs/rules/oauth-handshake.md +76 -0
- package/docs/rules/prompt-cache.md +93 -0
- package/docs/rules/quota-signals.md +125 -0
- package/docs/rules/routing.md +84 -0
- package/docs/rules/templates/oauth-reverse-checklist.md +42 -0
- package/docs/rules/trae-surface.md +242 -0
- package/docs/rules/ua-validation.md +81 -0
- package/host-config.js +282 -0
- package/index.js +2306 -0
- package/lib/client.js +2893 -0
- package/local-scan.js +104 -0
- package/package.json +82 -0
- package/providers/ark/index.js +11 -0
- package/providers/bailian/index.js +10 -0
- package/providers/bigmodel/index.js +11 -0
- package/providers/codebuddy/agenttool.js +122 -0
- package/providers/codebuddy/catalog.js +227 -0
- package/providers/codebuddy/errors.js +44 -0
- package/providers/codebuddy/headers.js +36 -0
- package/providers/codebuddy/images.js +125 -0
- package/providers/codebuddy/index.js +123 -0
- package/providers/codebuddy/oauth.js +279 -0
- package/providers/deepseek/index.js +11 -0
- package/providers/moonshot/index.js +11 -0
- package/providers/openai-compat.js +177 -0
- package/providers/openrouter/index.js +27 -0
- package/providers/qoder/catalog.js +145 -0
- package/providers/qoder/cosy.js +419 -0
- package/providers/qoder/gateway.js +563 -0
- package/providers/qoder/index.js +116 -0
- package/providers/qoder/oauth.js +364 -0
- package/providers/qoder/qoder_auth.wasm +0 -0
- package/providers/qoder/quota.js +56 -0
- package/providers/qwen/index.js +15 -0
- package/providers/tool-pairing.js +129 -0
- package/providers/trae/catalog.js +103 -0
- package/providers/trae/errors.js +85 -0
- package/providers/trae/gateway.js +853 -0
- package/providers/trae/index.js +126 -0
- package/providers/trae/oauth.js +443 -0
- package/providers/trae/quota.js +75 -0
- package/providers/trae/remote.js +365 -0
- package/scripts/capture-cache.mjs +65 -0
- package/scripts/capture-traffic.mjs +83 -0
- package/scripts/hermes-probe-dev-role.mjs +263 -0
- package/scripts/measure-latency.mjs +253 -0
- package/scripts/probe-ark-thinking.mjs +298 -0
- package/scripts/probe-cache-decline.mjs +292 -0
- package/scripts/probe-cache-ttl.mjs +221 -0
- package/scripts/probe-cache.mjs +156 -0
- package/scripts/probe-codebuddy-efforts.mjs +355 -0
- package/scripts/probe-codebuddy-tier-wiring.mjs +244 -0
- package/scripts/probe-effort-gaps.mjs +133 -0
- package/scripts/probe-media.mjs +115 -0
- package/scripts/probe-moderation.mjs +159 -0
- package/scripts/probe-oauth.mjs +617 -0
- package/scripts/probe-qoder-attribution-arm8.mjs +92 -0
- package/scripts/probe-qoder-attribution-arm9.mjs +102 -0
- package/scripts/probe-qoder-attribution.mjs +266 -0
- package/scripts/probe-qoder-flash-confirm.mjs +94 -0
- package/scripts/probe-qoder-live.mjs +344 -0
- package/scripts/probe-qoder-matrix.mjs +274 -0
- package/scripts/probe-qoder-null-content.mjs +153 -0
- package/scripts/probe-qoder-pairing.mjs +308 -0
- package/scripts/probe-qoder-quota.mjs +162 -0
- package/scripts/probe-qoder-thinking-config.mjs +52 -0
- package/scripts/probe-qoder-thinking-efforts.mjs +269 -0
- package/scripts/probe-quota.mjs +136 -0
- package/scripts/probe-quota2.mjs +144 -0
- package/scripts/probe-routing.mjs +226 -0
- package/scripts/probe-trae-3003-diagnosis.mjs +139 -0
- package/scripts/probe-trae-agent-v3.mjs +399 -0
- package/scripts/probe-trae-efforts.mjs +149 -0
- package/scripts/probe-trae-live.mjs +147 -0
- package/scripts/probe-trae-max-effort.mjs +179 -0
- package/scripts/probe-trae-model-routing.mjs +381 -0
- package/scripts/probe-trae-thinking-scene.mjs +238 -0
- package/scripts/probe-trae-transport-outage.mjs +176 -0
- package/scripts/probe-ua.mjs +508 -0
- package/scripts/trae-model-catalog.mjs +632 -0
- package/scripts/verify-agents-md.mjs +45 -0
- package/scripts/verify-bridge.mjs +1041 -0
- package/scripts/verify-core-generic.mjs +302 -0
- package/scripts/verify-desktop-acceptance.mjs +184 -0
- package/scripts/verify-host-config.mjs +265 -0
- package/scripts/verify-models.mjs +390 -0
- package/scripts/verify-providers.mjs +255 -0
- package/scripts/verify-qoder-provider.mjs +1020 -0
- package/scripts/verify-rotation.mjs +308 -0
- package/scripts/verify-trae-model-catalog.mjs +284 -0
- package/scripts/verify-trae-provider.mjs +1451 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# 设置卡交互重设计:通道手风琴
|
|
2
|
+
|
|
3
|
+
> 状态:**已实施(0.10.0,2026-09-23)**——Task 1–9 全部落地,见 CHANGELOG 0.10.0 段与 `.superpowers/sdd/settings-card-ux-redesign-plan/`(计划 = 同名 `-plan.md`,逐任务报告 task-1..9-report.md)。
|
|
4
|
+
> 原设计状态:三节设计已与用户逐节评审通过(2026-09-23),并经一轮证据硬审查(行号/断言数/数据源逐条实测核对)。
|
|
5
|
+
> 驱动:用户"这个项目的前端页面的交互,有点麻烦。不够简单" → 痛点定位轮(多选)结论 = **找不到、太散**。
|
|
6
|
+
> 范围:`lib/client.js` 前端交互模型重写;后端路由契约零变化。目标版本 **0.10.0**(交互模型换代,非补丁)。
|
|
7
|
+
|
|
8
|
+
## 0. 实施结论(实测,2026-09-23)
|
|
9
|
+
|
|
10
|
+
- **落地面**:§3/§4 全部按设计实现(4 区块固定顺序默认全收 / 区块头状态行 = 单一真源 / 展开才挂载收起不卸载 / 通道内五分组 + `details.cbc-adv` / 三家模型组同构 / Trae·Qoder 启用开关只在区块头 / 通用区块头取样 + api-key 估算降级 / 保存提示落触发区块头);§3 硬修复清单逐条迁移未丢(迁移时 11 条;跨分支终审补第 12 条「写后读必须带请求代次」);§5 的 31 字段落点已在 `wiki/07-web-client.md` 重写时复核。§2 表里的行号(`TAB_DEFS:363`、`tabBadge:682` 等)随重写失效,作为"当时的问题证据"保留不改。
|
|
11
|
+
- **回归数字**:`card-accordion.js`(设置卡唯一套件,`card-regression.js` 同日退役)**129 通过 / 0 失败**(静态 `check(` 站点 126 + `[B2]` 循环多跑 2 次 + `[C2]` 循环多跑 1 次;迁移期 117 → 终审修复轮 118 → 残余修复轮补 `[F9]` 收起重采正向锁 119 → 复审修复轮补 `[B5]`(退避链启动点 + A2 代次门时序锁,10 条)⇒ **129**);`qoder-slot-check.js` 13/13、`qoder-tab-phase2.js` 11/11、`qoder-prefs-check.js` 37 通过 / 0 失败 / 跳过 0(静态 39 站点)、`shots-baseline.js` 10 张**元素级**基线 0 失败、`debug-inputs.js` exit 0;离线七套件全绿(含 verify-qoder 154 / trae 89 / host-config 36 / `verify-models --list` 23 模型),全程 `~/.dsh/codebuddy-plugin.json` md5 恒等 = 零真实写入。
|
|
12
|
+
- **两条反复**(教训见踩坑 #46/#47/#48):① 键盘激活补丁 `48329a7` 加了又撤回 `4dd9f52`——回归锁用 `dispatchEvent` 派发不可信 keydown 测出**伪缺陷**;② 浅色下未勾选原生控件呈深色实心块,**断言全绿、靠人工看图**才发现(`a421d35` 修)。
|
|
13
|
+
- **已知限制 / 仍开放**:a) 旧槽(≤0.1.5 `settings.plugin.item`)**无本机宿主可实测**,折叠态单芯片那一路只有代码审查覆盖;b) `qoder-e2e.js`(8 断言)与 `npm run verify`(18 次真实网关探测)**未跑**——两者都消耗用户额度,按裁定跳过,不得声称通过;c) ~~`lib/client.js` 的 `load()` 仍无请求代次标记~~ ⇒ **跨分支终审已修**(`loadGenRef` 代次 + 陈旧响应丢弃,含失败分支;另同轮修掉"通用区块头取样永不刷新"——收起边界重采一次)。修复前实况 = 脚本侧靠轮询到收敛绕过、产品侧未动;终审裁定"脚本侧绕过 ≠ 产品修好",并要求把两条都写进 §3 硬修复清单。套件随之 117 → **118**(`[C2]` 补齐 Qoder 半边,见 CHANGELOG 0.10.0 段)→ **119**(终审残余修复轮:`[F9]` 给"收起边界重采"补上正向锁——此前套件只锁得住"收起后不再轮询",把重采代码删掉照样全绿)→ **129**(复审修复轮:`[B5]` 十断言——补拉链的**启动点**当时仍读被代次门作废的回调参数,回退它套件照样全绿;新锁同时是该代次门的第一枚时序用例);d) 区块展开驱动在 5 个脚本里各存一份副本(只有 `card-accordion.js` 有共享 `openBlock`),且除 `shots-baseline.js`(1440×3000)外各套件仍是 1440×900 视口——将来加高元素的截图会复刻"下半截空白"那个坑(#48)。这一分叉自终审起在 `card-accordion.js` 头注释里**明写为口径**(DOM 断言不受视口高度影响,改套件视口反而可能引入滚动行为差异),收尾取证图也改名成 `acc-task4-groups-viewport.png` 表明它是视口图;e) **每次打开插件管理器会多 1 次上游额度只读**——通用区块头的 `action:'usage'` 取样经服务端 `quotaSnapshot` 打控制台计费路径(`catalog.js:199-209` 有 60s memoize ⇒ 最坏 ≤1 次上游只读/进程/分钟),收起区块再 +1 次。别从"零真实写入"推出"零额外上游调用":写入是零,**只读不是零**。**(0.11.0 P1 追加同口径两条**:Trae/Qoder 凭据组「余额」行各自在区块**展开/收起边界**触发一次真实上游只读——Trae `ide_user_ent_usage`(req_source=0 全量包)、Qoder `quota/usage`(openapi 裸 Bearer),两个 provider 内各有 60s memoize,未登录零请求;宿主实况对账分区**零请求**(数据源 = host-config 宿主层读取 + web 服务实例字段,不跑 `dsh --dump-config`)。**)(0.12.0 P2 追加同口径一条**:凭据组「测一下」每次点击 = 一次真实上游只读(CodeBuddy 目录面 GET /v3/config 零额度、Qoder 签名目录 GET /algo、key 型 /models 或 1-token 探针),不点不发;「重试监听」只重跑本地 listen,零上游调用;「复制诊断」纯客户端聚合,零请求。**)**
|
|
14
|
+
|
|
15
|
+
## 1. 目标与非目标
|
|
16
|
+
|
|
17
|
+
**目标(按痛点排序)**
|
|
18
|
+
|
|
19
|
+
1. 用"按通道归类"消灭"散":每个通道的凭据、模型、工具、网关全部收进该通道区块;模型管理从三处归一,网关状态从五处归一。
|
|
20
|
+
2. 用"区块头常显状态行"消灭"找不到":不展开也能读到三通道 + 通用的状态;warn/err 就地出现在所属区块头,替代独立的注意条。
|
|
21
|
+
3. 删掉为标签栏服务的三层状态补偿机制(折叠三芯片 / 注意条 / 标签徽标),状态展示收敛为单一真源。
|
|
22
|
+
|
|
23
|
+
**非目标(本轮不做)**
|
|
24
|
+
|
|
25
|
+
- 不改后端契约、不改槽位注册方式、不改 Plugin Manager summary 文案结构。
|
|
26
|
+
- 不做草稿/批量/撤销式的保存模型(用户未把"交互噪音"选为痛点,保持"失焦即保存")。
|
|
27
|
+
- 不做跨通道的全局搜索框、主题定制、用量按通道拆分(YAGNI;额度账本保持跨通道单账)。
|
|
28
|
+
- 不动 `core/`、`providers/`(纯前端)。
|
|
29
|
+
|
|
30
|
+
## 2. 现状问题(证据)
|
|
31
|
+
|
|
32
|
+
| # | 问题 | 证据 |
|
|
33
|
+
|---|------|------|
|
|
34
|
+
| 1 | 分区轴混用:Trae/Qoder 各占整页,与 CodeBuddy 的模型页同构却分居三处 | `lib/client.js:1512`(TraeSection)、`:1692`(QoderSection)、`:1070`(ModelsSection) |
|
|
35
|
+
| 2 | 模型管理散在三处,各有一套同步按钮与列表 | 同上三处各自的 `fetchList`/`syncNow`/`fetchTlist`/`fetchQlist` |
|
|
36
|
+
| 3 | 同一状态最多出现 5 处 | 折叠三芯片 `buildChips`(`:619`)、注意条 `attn`/`strip`(`:534`/`:536`)、标签徽标 `tabBadge`(`:682`)、行内 `Dot`、灰字说明 |
|
|
37
|
+
| 4 | 工程项与日常项同层 | 3 个端口、`upstreamFirstByteTimeoutMs`、`sessionHeaderFormat`、`baseURL`、4 个域名、`qoderClientId` 全平铺 |
|
|
38
|
+
| 5 | 8 个标签扁平铺开,无分组 | `TAB_DEFS`(`:363`) |
|
|
39
|
+
|
|
40
|
+
补充实测:CodeBuddy 的桥(`:3901`)在"桥与高级"页,Trae/Qoder 的翻译网关(`:3902`/`:3903`)各在自己页——同一概念三处不同位置。后端口径核对:`meter` 由三通道网关共同记账(`core/usage-meter.js:120` 的 `record()` 被 `providers/trae/gateway.js:513`/`:683`、`providers/qoder/gateway.js:450` 调用)⇒ **用量是跨通道的**;账户剩余额度(`quotaSnapshot`)是 CodeBuddy 专有。
|
|
41
|
+
|
|
42
|
+
## 3. 顶层结构(已确认)
|
|
43
|
+
|
|
44
|
+
顶层 = 4 个可展开区块,顺序固定:**CodeBuddy → TraeWork CN → Qoder CN → 通用**。默认全部收起(首屏 = 4 条状态行,即总览)。
|
|
45
|
+
|
|
46
|
+
区块头 = 唯一常显状态,格式(示例):
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
● CodeBuddy 已登录(00)· 28 模型 · 桥 :3901 ✓
|
|
50
|
+
■ TraeWork CN 未启用
|
|
51
|
+
⚠ Qoder CN 已登录 · 网关 :3903 未监听
|
|
52
|
+
○ 通用 额度 1879 credit · 服务商 3
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
状态点 tonal 沿用现有 `cbc-ok/warn/err/off` 四色;warn/err 只在所属区块头出现(原注意条的语义就地化)。
|
|
56
|
+
|
|
57
|
+
**状态行真源**:判定口径与文案直接沿用现有 `buildChips`(`lib/client.js:619`),只是从"三处重复展示"收敛为区块头一处;`tabBadge`(`:682`)随标签栏一并删除。CodeBuddy / Trae / Qoder 三家的状态行所需数据**全部在 GET 响应内**(已核 `settingsView`,`index.js:1179`:`oauth` / `bridge{running,port,lastError}` / `models.effectiveCount` / `trae.oauth`+`trae.bridge`+`trae.models{disabled,sync{at,count}}` / `qoder` 同构——通道模型数可由 `sync.count − disabled.length` 就地算出,无需额外请求);唯一例外是通用区块头的「额度 / 服务商数」——二者不在 GET 里,改为卡片挂载时各做一次 `action:'usage'` 与 `provider-list` 取样(未取到前显示 `额度 — · 服务商 —`),通用区块展开后进入原轮询/原有交互。**取样口径分两句(0.10.0 终审措辞更正,此前"一次性,不轮询"被下游读成"永不更新"、据此拒掉了一个真缺陷)**:① **不做周期轮询**——头部四行常驻,定时打 `usage` 等于每次开卡都多付一份上游额度只读,这是成本考虑,不是"数值可以过期";② **在区块收起时重采一次**——头部状态行是"首屏即总览 / 区块头 = 状态单一真源"的载体,而它正下方的展开区每 10s 轮询;只采挂载那一刻会让头部停在"打开页面那一瞬"的快照,用户加/删一个服务商或聊了一小时之后,头部与同屏正文自相矛盾 ⇒ 总览行会撒谎比没有总览行更伤。触发点 = `general` 由展开转收起的那一刻(`useEffect` deps `[!!openBlocks.general]` + `useRef` 记前值判"由开转关"),**不是**展开时(展开时正文自己会拉)。**本机凭据扫描 `credential-scan` 不上移**——仍在通用区块首次挂载时才做(它会扫本机文件,不该在每次开卡时触发)。**api-key 模式降级**:`quota.numericQuota` 为假(数值额度是 OAuth 专享,实测 401)时头部不编造数字,显示 `额度 估算`(口径同现有手填估算档)或退化为只显服务商数。
|
|
58
|
+
|
|
59
|
+
内容映射(归属原则 = 谁提供归谁,附代码证据):
|
|
60
|
+
|
|
61
|
+
| 区块 | 内容 | 证据 |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| CodeBuddy | 凭据、模型、**工具**(搜索/抓取、生图)、网关(流式桥)、高级 | 搜索/抓取走 `/agenttool/v1/*`、生图走 `/v2/images/generations`(`providers/codebuddy/agenttool.js`、`images.js`) |
|
|
64
|
+
| TraeWork CN | 凭据、模型、网关(翻译网关 :3902、聊天传输、首字节超时)、高级(域名组) | `providers/trae/gateway.js` |
|
|
65
|
+
| Qoder CN | 凭据、模型(启停 + 档位/上下文变体)、网关(:3903)、高级(域名组) | `providers/qoder/gateway.js` |
|
|
66
|
+
| 通用 | 额度与用量(跨通道计量 + CodeBuddy 账户额度)、服务商(key 型上游 + 本机凭据导入) | `core/usage-meter.js` + `providers/qoder`/`trae` 记账调用点;`providers/openai-compat.js` |
|
|
67
|
+
|
|
68
|
+
**删除**:8 标签导航(`TAB_DEFS`/tabBar/各 ARIA)、折叠三芯片、注意条、标签徽标。
|
|
69
|
+
**必须原样迁移的硬修复清单**(全量重写最容易丢的就是这些;行号为现 `lib/client.js`,逐条已核):
|
|
70
|
+
|
|
71
|
+
| 机制 | 位置 | 迁移要求 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| 保存后网关退避补拉 `settleGateways` | `GATEWAY_SETTLE_DELAYS` 延迟表 / `settleGateways()` | **踩坑 #45**:POST 同步返回而 `running` 由 `listening` 事件异步翻转 ⇒ 假「未监听」会永久驻留。新结构下状态行仍在区块头,机制必须保留(1s/2s/4s 三次,用尽停手、warn 如实留下);**启动点与续跑点两处判定同形**(读 `dataRef.current`,见下一行)。锁 = `[B4]`(续跑自愈)+ `[B5]`(启动点:本包被竞争包作废时链照旧要起来) |
|
|
74
|
+
| **写后读必须带请求代次**(0.10.0 终审补,#45 同族的另一半) | `load()`(`loadGenRef`/`dataRef` 两个 `useRef`)/ `save` 的 `.then` / `settleGateways` 的退避回调 | `load()` 的响应要能识别陈旧并丢弃:每次 `load()` 领一个自增代次(`useRef`),回包时不是最新代次就整包作废(**失败分支同样受门约束**——陈旧请求的报错不该盖住新态)。#45 上一轮只补了"异步 listen 会迟到"那一半,漏了"并发 GET 会倒序落地"这一半:`save` 的 `.then` 里必跟 `load()`,而本轮"四区块可同时展开 + 每分区各持一个 `saveIn(block)`"让 1 秒内并发保存成为**正常操作路径**,两次 POST 落在同一 GET 往返窗口(实测 ~1.0–1.3s)时先发后回的旧响应会覆掉新响应,且主视图无轮询自救。**配套纪律(复审补)**:一旦 `load()` 会返回 `null`,任何"拿返回值判接下来做什么"的站点都不能再用返回值——补拉链的**两个判定点(`save` 的 `.then` 启动点 + `settleGateways` 的续跑点)必须同形地读 `dataRef.current`**,只改一处等于把 #45 的自愈保护削掉一半(复审实测回退启动点 ⇒ 假「未监听」永久驻留)。通式:**写后的读不可当终态**,既要"补拉到收敛",也要"陈旧响应不许落地",还要"判定别看回调参数" |
|
|
75
|
+
| `fetchWithTimeout`(GET 20s / POST 30s) | `:98` | 全部 fetch 走它;AbortError 换成带时长的中文错误 |
|
|
76
|
+
| `PanelBoundary` 错误隔离 | `:296` | 粒度从"每标签"改为**每分区**(一个区块内的各分区各自隔离——模型组塌落不影响同区块的凭据组,比整区块隔离更细);`componentDidCatch` 送堆栈进 console、fallback 只显示 message(踩坑 #7) |
|
|
77
|
+
| `startOAuthFlow` 同步开窗 | `:2042` | `window.open` 必须在点击处理器内同步发起,异步调用被弹窗拦截器吃掉 |
|
|
78
|
+
| `pickComponent` 图标候选表 | `:84` | **踩坑 #44③**:宿主 0.1.7 废掉带尺寸数字后缀的图标名;按候选序取第一个存在的,全缺退原生兜底 |
|
|
79
|
+
| 幽灵输入双路径 CSS | `:214`–`:218` | 宿主 `Input` 原语把 className 落在 wrapper span、焦点在内层 input ⇒ `:focus-within` 与 `.cbc-ghost input::-webkit-*-spin-button` 两条都要留 |
|
|
80
|
+
| 同值去重 + 失败销账(4 张表) | `:1124` / `:1577` / `:1773` / `:1789` | **踩坑 #27/#32**:`useRef` 同值去重(不用时间窗——勾选往返可快过任何时间窗);失败分支必须删账,否则该模型同向操作被永久吞掉 |
|
|
81
|
+
| 字段编辑器模块级定义 | `TextField:1999` / `NumberField:2035` / `LimitInput:2060` | 组件身份随父重渲染变化会丢焦点 |
|
|
82
|
+
| 错误提示带原因 | 全文件 23 处 `e.message` 优先 | "(网络)"只是兜底;0.9.11 轮 3 收全的 13 处 catch 勿在重写中退回 |
|
|
83
|
+
| 脱敏纪律 | GET 的 `user` 字段 | Key 只回脱敏值、永不回传浏览器(踩坑 #26) |
|
|
84
|
+
| 失焦即保存 / `ResetButton` / `HelpNote` / 懒挂载 | — | 语义平移,不改行为 |
|
|
85
|
+
|
|
86
|
+
## 4. 区块内部结构与交互(已确认)
|
|
87
|
+
|
|
88
|
+
通道区块展开后 = 固定顺序分组(三家同构,CodeBuddy 多一个「工具」组):
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
凭据 → 模型 → [工具] → 网关 → 高级(details 折叠)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
- **凭据**:CodeBuddy = 登录方式 + 多 Key 管理 + 环境变量引用 + 失败冷却;Trae/Qoder = 登录/退出(二次确认)+ 令牌状态行。
|
|
95
|
+
- **模型**:操作条 `[同步目录]` + 状态文字(`上次同步 MM-DD HH:mm · 目录 N 个`);筛选框三家统一提供;行 = 勾选框 + 模型名 + ctx/输出(CodeBuddy 可编辑=幽灵输入,另两家只读)+ 档位/变体 select + 徽标(插件/目录/CLI/图/思考)。CodeBuddy 现有两按钮(刷新列表 / 立即同步)合并为 `[同步目录]`:一次点按顺序触发 `model-sync` → `model-list`;失败路径保持两侧原因分别可见(目录同步失败 vs 列表获取失败,各自照旧文案)。
|
|
96
|
+
- **工具**(仅 CodeBuddy):搜索与抓取开关 / 默认条数 / 正文上限;生图开关 / 生图模型。
|
|
97
|
+
- **网关**:状态行 + 端口 + 该通道特有项(CodeBuddy:流式桥开关、会话归因、会话头格式、并发上限;Trae:聊天传输、首字节超时)。
|
|
98
|
+
- **高级**(`<details>` 折叠,零 JS 状态):域名族、`baseURL`、`qoderClientId` 等纯工程项。
|
|
99
|
+
- **通用区块**:`额度与用量`(hero + 统计卡 + 资源包 + 轮次表,原样;轮询条件从"标签可见"改为"区块展开")+ `服务商`(列表 + 添加行 + 本机凭据行,原样)。
|
|
100
|
+
|
|
101
|
+
**交互细节**
|
|
102
|
+
|
|
103
|
+
1. **区块头结构**:`div.cbc-acc-head` = 左侧占满的展开 `button`(状态点 + 名称 + 状态行 + 箭头,`aria-expanded`/`aria-controls`)+ 右侧可选启用开关(Trae/Qoder 的 `traeEnabled`/`qoderEnabled` 唯一落点,不在展开区重复)。分开两个交互元素,避免嵌套交互。CodeBuddy 无通道级开关,头部右侧只有箭头。
|
|
104
|
+
2. **手风琴允许多开**,互不联动;展开才挂载分区内容,收起不卸载(`hidden` 保留 DOM——草稿、滚动位置、已拉目录跨展开与保存保留,语义平移自现有懒挂载纪律)。
|
|
105
|
+
3. **状态收敛**:warn/err 仅见于所属区块头;错误横幅保留卡片顶部;保存成功提示从标签栏右侧移到**触发该次保存的区块**头部右侧(1.8s 自愈)。
|
|
106
|
+
4. **键盘/ARIA**:区块头是普通 button(Enter/Space 展开/收起);删除 tablist 的 roving tabIndex、`role="tab"`、方向键逻辑与相关断言。
|
|
107
|
+
5. **模型档位/上限控件**:`LimitInput`、`effortByModel` select、Qoder `modelPrefs` 两 select 全部原样迁移(同值去重 `useRef` 纪律不变,踩坑 #27/#32)。
|
|
108
|
+
6. **旧槽折叠态**(≤0.1.5 `settings.plugin.item`):卡片头保留标题 + 一行简介;仅当存在 warn/err 时显示单枚"N 项需处理"芯片;展开卡片即进入四区块手风琴。`plugins.item` 的 summary 视图不变。
|
|
109
|
+
|
|
110
|
+
## 5. 字段落点对照(`SETTINGS_FIELDS` 全量,31 项)
|
|
111
|
+
|
|
112
|
+
| 字段 | 落点 |
|
|
113
|
+
|---|---|
|
|
114
|
+
| `authMode` `apiKeys` `activeApiKey` `apiKeyEnv` `keyCooldownMs` | CodeBuddy · 凭据 |
|
|
115
|
+
| `effortByModel`(+ 状态量 `modelSetEnabled`/`modelSetLimits`) | CodeBuddy · 模型 |
|
|
116
|
+
| `searchEnabled` `searchMaxResults` `fetchBodyCap` `imageGenEnabled` `imageGenModel` | CodeBuddy · 工具 |
|
|
117
|
+
| `bridgeEnabled` `bridgePort` `sessionHeadersEnabled` `sessionHeaderFormat` `maxConcurrentPerSession` | CodeBuddy · 网关 |
|
|
118
|
+
| `baseURL` | CodeBuddy · 高级 |
|
|
119
|
+
| `traeEnabled` | TraeWork CN · 区块头开关 |
|
|
120
|
+
| `traeChatTransport` `traeBridgePort` `upstreamFirstByteTimeoutMs` | TraeWork CN · 网关 |
|
|
121
|
+
| `traeAuthBaseURL` `traeChatBaseURL` `traeLoginHost` | TraeWork CN · 高级 |
|
|
122
|
+
| `qoderEnabled` | Qoder CN · 区块头开关 |
|
|
123
|
+
| `qoderBridgePort` | Qoder CN · 网关 |
|
|
124
|
+
| `qoderLoginHost` `qoderOpenapiBaseURL` `qoderInferBaseURL` `qoderClientId` | Qoder CN · 高级 |
|
|
125
|
+
| `quotaTotalManual` | 通用 · 额度与用量 |
|
|
126
|
+
| 其余状态量:`traeModelSetEnabled` / `qoderModelSetEnabled` / `qoderModelSetPrefs` / `provider-*` / `credential-*` | 各自通道的模型组 / 通用 · 服务商 |
|
|
127
|
+
|
|
128
|
+
## 6. 兼容、回归与影响面(已确认)
|
|
129
|
+
|
|
130
|
+
- **后端契约零变化**:GET/POST `/dsh-tap/settings` 的全部 action 与响应结构不动;槽位双注册(`plugins.item` / `settings.plugin.item`)不动。
|
|
131
|
+
- **浏览器回归**(仓库外 `dsh-ui-test/`,puppeteer + 系统 Chrome):
|
|
132
|
+
- 驱动方式从"点 `.cbc-tab` 文本 + 查 `.cbc-panel[data-tab=X]`"改为"点区块头 + 查新区块选择器"。
|
|
133
|
+
- `card-regression.js`(现 28 断言):随结构消失的断言(标签齐全/徽标/注意条/ARIA tablist/方向键)替换为——4 区块与固定顺序、默认全收、状态行口径(**独立预言机**双向对齐,沿用 0.9.11 手法)、展开才挂载、收起保留(草稿 + 滚动)、多开独立、头部开关 = 1 POST、无注意条(warn 只出现在状态行)、**挂载取样各一次且收起不轮询**(usage/provider-list 在卡片挂载时各一次,通用区块收起期间无周期请求)。⚠ 实测:现套件**没有**"未激活不轮询 / 切走即停"这条断言——原 `step25` 已随 0.9.11 回归套件重建丢失(`grep -n "切走\|不轮询" card-regression.js` 零命中),故本次是**新增**该断言,不是"承接"。
|
|
134
|
+
- `qoder-slot-check.js`(现 10 断言):Qoder CN 标签 → Qoder CN 区块;槽断言不变。
|
|
135
|
+
- `qoder-e2e.js`(8 断言)/ `qoder-prefs-check.js`(32)/ `qoder-tab-phase2.js`(8)/ `shots-baseline.js`:选择器与驱动逐个适配(断言数为本次实测 `grep -c 'check("'`)。
|
|
136
|
+
- 纪律保持:mock GET/POST、零真实写入(跑前跑后 `~/.dsh/codebuddy-plugin.json` 哈希对账)。
|
|
137
|
+
- **文档修正(实测漂移)**:`wiki/07-web-client.md` §改 UI 后的回归 说"测试驱动先用 `window.__cbc.tab('分区名')`",但 `lib/client.js` 与 `dsh-ui-test/*.js` 中**均无此钩子**(脚本实际点击 `.cbc-tab`)。重设计后统一写清新区块驱动方式与选择器清单。
|
|
138
|
+
- **文档与版本**:重写 `wiki/07-web-client.md` 卡片结构章节;更新 `AGENTS.md` 架构表 `lib/client.js` 行;`CHANGELOG.md` 记 0.10.0。
|
|
139
|
+
- **已知限制**:旧槽(≤0.1.5)无本机宿主可实测,仅代码审查覆盖;回归脚本为仓库外资产且历史上丢失过(step 系列),本次重写后把"选择器清单 + 驱动方式"固化进 wiki。
|
|
140
|
+
|
|
141
|
+
## 7. 实施顺序(供 writing-plans 展开)
|
|
142
|
+
|
|
143
|
+
1. **骨架**:4 区块 + 状态行 + 手风琴 + 懒挂载;先打通 CodeBuddy 的「凭据/模型」两组(含同步按钮合并)。
|
|
144
|
+
2. **迁移**:其余内容迁入手风琴(工具/网关/高级/额度/服务商/通用),删除三套状态层与 tablist 逻辑。
|
|
145
|
+
3. **回归**:换驱动与选择器,重写断言集,`dsh-ui-test/` 全绿(含零写入 mock 组)。
|
|
146
|
+
4. **收尾**:截图基线重拍、wiki/AGENTS/CHANGELOG 更新。
|
|
147
|
+
|
|
148
|
+
## 8. 风险与缓解
|
|
149
|
+
|
|
150
|
+
| 风险 | 缓解 |
|
|
151
|
+
|---|---|
|
|
152
|
+
| 展开态页面变长 | 默认全收 + 多开可控;模型列表保持滚动盒 |
|
|
153
|
+
| 头部开关误触(收起态直接启用/停用通道) | ~~开关即普通 checkbox、可逆;若实感不佳,回退方案 = 开关移入展开区第一行(已与用户约定)~~ ⇒ **0.13.0 已落地首选方案**:收起态第一次点击只进确认态(就地提示「再点一次确认」+ 受控框弹回 + 4s 超时复位,沿用 askConfirm 模式),展开态直切不确认;回退方案不启用。锁 = card-accordion `[C3]`(首击 0 POST / 二击恰 1 POST / 超时复位 / 展开直切) |
|
|
154
|
+
| 回归脚本重写工作量(仓库外一次重建) | 预留独立一轮(实施顺序 ③),断言集先写"独立预言机"再补细节 |
|
|
155
|
+
| 旧槽路径无宿主可测 | 保留双槽注册;旧槽逻辑仅做代码审查 + 精简(折叠态只留 1 枚按需芯片) |
|
|
156
|
+
|
|
157
|
+
## 9. 验收标准
|
|
158
|
+
|
|
159
|
+
- `lib/client.js` 全量重写后:4 区块与状态行口径正确;默认全收;展开才挂载、收起保留;多开独立;无 tablist/注意条/徽标残留代码与样式。
|
|
160
|
+
- `dsh-ui-test/` 全部脚本适配后跑绿(card-regression 重写版 + qoder 系列),零真实写入纪律可复验。
|
|
161
|
+
- `npm run verify` 与全部离线回归(verify-bridge / core-generic / rotation / providers / trae / qoder / host-config)保持绿(纯前端改动,预期零影响,作为回归保险)。
|
|
162
|
+
- 浅色/深色截图基线重拍并人工核验;wiki/AGENTS/CHANGELOG 更新到位。
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Goal:Trae 通道「额度/模型/工具环」在 DSH 闭环(agent v3 路由移植)
|
|
2
|
+
|
|
3
|
+
**立项**:2026-10-05 | **状态**:M1–M3 完成(分支 feat/trae-agent-v3),发版待用户确认
|
|
4
|
+
**完成定义**:在 dsh-tap 的 Trae 通道接入上游 agent 路由 `POST https://trae-api-cn.mchost.guru/api/agent/v3/llm_utils_chat`,使 DSH 内 Trae 订阅达到「模型可流式对话 + 工具环端到端 + 消耗本机订阅积分」闭环;证据先行、离线套件全绿。
|
|
5
|
+
|
|
6
|
+
## 关键转向(M1 探针发现)
|
|
7
|
+
|
|
8
|
+
社区两个参照实现(dsh-connect-trae / Trae2api-cn)的「agent 路由」**不是新 function 名**,而是同端点的 `function=solo_work_lite` 面——fn 名扫描(agent_chat/agent_v3/solo_agent_chat/agent/assistant_chat 均 2001 未注册)证伪了「专用 agent function」假设后,由参照源码锁定 solo_work_lite。该面与 inline_chat 同端点但方言不同(历史 tool_calls 键=function_call,踩坑 #68)。
|
|
9
|
+
|
|
10
|
+
## M1 探针结论(证据 docs/probes/trae-agent-v3-2026-10-04.jsonl,决策门 PASS)
|
|
11
|
+
|
|
12
|
+
| 臂 | 内容 | 结果 |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| A1 | 纯聊天 | 200 SSE,14 事件,finish=stop |
|
|
15
|
+
| A2 | tools+auto | 200,出 tool_calls(function_call 键,index 分片) |
|
|
16
|
+
| A3 | 两轮工具闭环 | 200,第二轮产出最终回答(首轮 function 键被拒 2001 → 换 function_call 键通过) |
|
|
17
|
+
| A4 | 并行调用 | 200,单事件双 tool_calls |
|
|
18
|
+
| A5 | reasoning_effort=high | 200 被接受但被忽略(行为同 A2) |
|
|
19
|
+
| E1 | 错模型名 | 200 静默容忍(该面宽容) |
|
|
20
|
+
| E2 | 坏参数(temperature 字符串) | 200 静默容忍 |
|
|
21
|
+
| A6 | kimi-k2.6 / DeepSeek-V4-Flash | 200,provider_model_name 恒 glm-5.2(模型位钉死) |
|
|
22
|
+
|
|
23
|
+
额度:token_usage 事件带真实计数(prompt/completion/reasoning/cache_read);pay 池差分对小探测不可见(分辨率 0.01 credit)。
|
|
24
|
+
|
|
25
|
+
## M2 实装(providers/trae/ + index.js;core/ 零 diff)
|
|
26
|
+
|
|
27
|
+
- `gateway.js`:`buildChatRequest(payload, sessionId, {fnKey})`;`handleChat` agent 分支(function=solo_work_lite、fnKey=function_call、不回退 chat_v3)
|
|
28
|
+
- `errors.js`:码表补 2001/4001/4011/4023/9074;3003 提示补 agent 出路
|
|
29
|
+
- `index.js`:`traeChatTransport` 枚举加 `'agent'`;`lib/client.js` 设置卡第三档
|
|
30
|
+
- reasoning_effort 照发不虚标;档位注入维持仅 remote 面
|
|
31
|
+
|
|
32
|
+
## M3 验证
|
|
33
|
+
|
|
34
|
+
- verify-trae-provider 131→**141** 断言全绿(agent 节 8 断言);离线十一套件全绿;core/ 零 diff
|
|
35
|
+
- 真实端到端(生产网关+真实凭据临时实例):R1 带 tools → finish_reason=tool_calls + 参数拼回;本地执行 → R2 回传 → 最终回答「当前时间是 2026年10月5日 14:30:00」;meter 记真实模型 glm-5.2
|
|
36
|
+
- probe-effort-gaps 三通道 11/11 无缺口;card-accordion 204/0 + md5 跑前后一致
|
|
37
|
+
|
|
38
|
+
## M4 收尾状态
|
|
39
|
+
|
|
40
|
+
- docs/rules/gateway-facts.md「agent 面」节、docs/diagnosis-trae-3003.md §13 销案、docs/pitfalls.md #68、AGENTS.md 速查、CHANGELOG 0.20.0、STATE.md——均已写
|
|
41
|
+
- **已决(2026-10-05 用户拍板「开始做吧」)**:默认传输档 inline→agent(`traeChatTransport` Config 默认 + 设置卡选项顺序同步);发版 0.20.0 + annotated tag + push 按确认执行。M0(装 dsh-connect-trae 对照)跳过。
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Goal:TraeWork CN 通道修复与档位出档
|
|
2
|
+
|
|
3
|
+
> 执行模式:长任务 goal。本文只定义**角色、意图、边界与验收**;实现路径由执行 agent 在边界内自主决定。
|
|
4
|
+
> 写法同构 `bridge-port-host-split.md`:角色定位 + 意图/为什么 + 分阶段意图(非逐行指令)+ 已验证事实 + 未知数(探测先行)+ 产出契约 + 边界。
|
|
5
|
+
> 必读裁判依据:`AGENTS.md`(全部踩坑)+ `docs/rules/*.md` + `docs/reverse/traework-cn.md` + `docs/reverse/trae-cloud-api.md` + `docs/reverse/trae-model-catalog.md` + `docs/diagnosis-trae-3003.md`。
|
|
6
|
+
> 进展记录:每完成一个 G 项,在 `docs/rules/STATE.md` 追加一段。
|
|
7
|
+
> 状态:**已落地(2026-10-04,G1–G4 一轮完成 + 终审修复闭环)**。驱动:用户在 dsh 设置卡点 Trae「同步目录」拿不到模型列表;实测根因 = vscdb 发现路径写死 WSL 格式(`/mnt/c/Users`),Windows 桌面端扫不到;且 `trae-model-sync` 失败时错误原因没浮到 UI(只显示泛化「未同步」)。验收实录见 docs/rules/STATE.md 同名节。
|
|
8
|
+
|
|
9
|
+
## 角色与使命(why)
|
|
10
|
+
|
|
11
|
+
你是 dsh-tap 的 **Trae 通道修复负责人**。现状:TraeWork CN 通道的 OAuth/凭据/网关转发链路在 0.19.0 已全通(设置卡显示「已登录 · 用户82411632597 · IDE 池 2432.75/2800」),但**模型目录同步在本机桌面端跑不通**——`POST /dsh-tap/settings` 的 `trae-model-sync` 返回 `ok:false`,错误原文「未发现 TRAE SOLO CN 的 state.vscdb(需要 --db 或本机安装)」,而 `state.vscdb` 实际存在于 `C:\Users\21613\AppData\Roaming\TRAE SOLO CN\User\globalStorage\state.vscdb`。
|
|
12
|
+
|
|
13
|
+
你的使命:让 Trae 通道在桌面端**同步得到目录、出得了档位**——从「装得上/登录得上」到「模型列表能拉下来、思考档位能选」。
|
|
14
|
+
|
|
15
|
+
## 已验证事实(立项前实测,出处标注)
|
|
16
|
+
|
|
17
|
+
| 事实 | 出处 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| vscdb 存在 | `C:\Users\21613\AppData\Roaming\TRAE SOLO CN\User\globalStorage\state.vscdb`(文件系统直查) |
|
|
20
|
+
| 发现逻辑写死 WSL 路径 | `scripts/trae-model-catalog.mjs:37` `DEFAULT_USERS_ROOT = '/mnt/c/Users'`;`discoverStateDbs()` 扫 `/mnt/c/Users/*/AppData/Roaming/{TRAE SOLO CN,TraeWork CN}/User/globalStorage/`(:172-194)——Windows 原生进程里 `/mnt/c` 不存在 |
|
|
21
|
+
| 桌面 dsh 是 Windows 原生进程 | `process.platform === 'win32'`,`os.homedir()` = `C:\Users\21613`,无 `/mnt/c` |
|
|
22
|
+
| `trae-model-sync` 失败但 UI 不显示原因 | 子代理实测:POST 200,响应 `{"ok":false,"sync":{"ok":false,"error":"未发现…","kept":false}}`,DOM 仍显示泛化「未同步」 |
|
|
23
|
+
| Trae 档位方言全臂 3003 | `docs/rules/gateway-facts.md` Trae 节(2026-10-04):`inline_chat` scene 把 thinking 置 disabled、模型默认档 high,组合非法;`chat_v3` 路径请求体根本没有 effort/thinking 字段——**档位出档的前提是先找到能传 thinking 的 scene** |
|
|
24
|
+
| 手风琴收放正常 | 子代理实测:可信点击后 aria-expanded/class/hidden 三态同步翻转,无 bug |
|
|
25
|
+
|
|
26
|
+
## 分阶段意图(非逐行指令)
|
|
27
|
+
|
|
28
|
+
1. **G1 修 vscdb 发现**:`discoverStateDbs()` 在 Windows 原生进程下也能找到本机 `state.vscdb`——按 `process.platform` 分支(win32 扫 `os.homedir()/AppData/Roaming/{产品目录}/User/globalStorage/`,WSL 保持 `/mnt/c/Users`),或统一用 `os.homedir()` + 平台感知拼接。验收:`trae-model-sync` 在桌面端返回 `ok:true` + 模型数 > 0。
|
|
29
|
+
2. **G2 错误浮到 UI**:`trae-model-sync` 失败时把 `sync.error` 显示在 Trae 区块的模型区(替换或追加到「未同步」文案),别让用户点了个寂寞。验收:模拟 vscdb 不存在(临时改名)→ UI 显示「未发现 state.vscdb」;恢复后 → 正常同步。
|
|
30
|
+
3. **G3 档位出档(探针门控)**:前提 = 找到能把 thinking 置 enabled 的 scene/参数组合(gateway-facts 已立项的后续课题)。方法:抓 Trae 官方客户端自己的请求看它用什么组合,或枚举 scene。找到 → `catalogToProfiles` 把 `reasoningEffortOptions` 写成 `reasoningEfforts` + index.js 镜像块补 compat + Trae 卡按 B3 同规则出档;找不到 → 文档写死「Trae 思考不可控」销案。验收:找到则 Trae 模型在宿主选择器出档位;找不到则 `gateway-facts.md` 记录终局结论。
|
|
31
|
+
4. **G4 回归零破**:离线九套件 + `verify-trae-provider` 全绿;`probe-effort-gaps` 跑通无缺口;浏览器回归 `card-accordion` 200 断言不破。
|
|
32
|
+
|
|
33
|
+
## 产出契约
|
|
34
|
+
|
|
35
|
+
- 代码:`providers/trae/catalog.js` / `scripts/trae-model-catalog.mjs` / `lib/client.js` / `index.js` 的最小改动;新探针(若 G3 找到 scene)落 `scripts/probe-trae-*.mjs`。
|
|
36
|
+
- 文档:`docs/rules/STATE.md` 追加 G 项进展;`gateway-facts.md` Trae 节按结论更新;`docs/pitfalls.md` 若踩新坑取新编号。
|
|
37
|
+
- 验证:G1/G2 桌面端实测(设置卡 Trae 区块同步出模型列表);G3 探针证据落 `docs/probes/`;G4 全量回归。
|
|
38
|
+
|
|
39
|
+
## 边界
|
|
40
|
+
|
|
41
|
+
- **不碰 OAuth/凭据链路**(0.19.0 已全通,本轮不动)。
|
|
42
|
+
- **不臆造档位拼写**(踩坑 #42)——G3 找不到 scene 就销案,不硬编。
|
|
43
|
+
- **vscdb 只读**——`copySqliteForRead` 纪律保留,绝不写回原文件。
|
|
44
|
+
- **零真实写入纪律**:改 `lib/client.js` 后跑 `card-accordion` 前对 `~/.dsh/codebuddy-plugin.json` 取 md5 对账。
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Goal:额度可见 + 模型动态化 + 多服务商凭据中心(v0.8 方向)
|
|
2
|
+
|
|
3
|
+
> 执行模式:长任务 goal。本文只定义**目标、边界、验收**;实现路径由执行 agent 自主决定。
|
|
4
|
+
> 必读裁判依据:`AGENTS.md`(全部踩坑)+ `docs/rules/*.md`(网关实测事实,勿凭记忆改)。
|
|
5
|
+
> 每完成一个 G 项,在 `docs/rules/STATE.md` 追加一行进展记录。
|
|
6
|
+
|
|
7
|
+
## 背景一句话
|
|
8
|
+
|
|
9
|
+
0.7.5 已完成 core/providers 分层重构(四项回归全绿)。下一阶段:让**额度看得见**、**模型列表跟网关走**、**电脑上所有有额度的 agent 工具都能接入 dsh**。
|
|
10
|
+
|
|
11
|
+
## 已验证事实(设计前必读,出处 docs/rules/)
|
|
12
|
+
|
|
13
|
+
| 事实 | 出处 |
|
|
14
|
+
|---|---|
|
|
15
|
+
| 计费唯一正信号 = chat SSE 每请求 `usage.credit`(usage-meter 已在记录并落盘) | quota-signals.md R-Q5 |
|
|
16
|
+
| CLI/api-key 面全网关**无数值剩余额度 API**;网页 plan API(credit/limitNum/remainCredits)走 cookie 体系 | quota-signals.md §1/§4 |
|
|
17
|
+
| WorkBuddy 与 CodeBuddy **同账户体系、同设备流**(Tencent-Cloud.coding-copilot),额度账户级共享 | AGENTS.md |
|
|
18
|
+
| OAuth 设备流四端点已规则化;11217 三态同码;token 权限边界 / refresh 轮换 / state TTL 未解,**解锁条件 = 一次真实交互登录** | oauth-handshake.md §5 |
|
|
19
|
+
| `/v3/config` 是网关自有模型目录(含 maxInputTokens / maxOutputTokens / credits 倍率),`catalog.js` 已能拉取 | routing.md + providers/codebuddy/catalog.js |
|
|
20
|
+
| 静态模型清单钉在 `cordis.patch.yml`(llm-pi-ai.providers.codebuddy.models),运行时增删走 settings.yaml 镜像 + 纯净态纪律 | index.js + 踩坑 #6 |
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 阶段一:WorkBuddy OAuth 落地 + 额度读数(先做)
|
|
25
|
+
|
|
26
|
+
### G1 完成一次真实 OAuth 登录
|
|
27
|
+
**目标**:设置卡 OAuth 区可用真实浏览器完成一次完整登录;token 落 `~/.dsh/codebuddy-plugin-auth.json`;`oauthStatus()` 显示已登录账户信息。
|
|
28
|
+
**注意**:用户在 WorkBuddy 客户端和个人中心都能看到额度 → 额度数据必有服务端来源;本阶段登录是后续探测的前提。
|
|
29
|
+
|
|
30
|
+
### G2 真实 token × 端点矩阵探测(解锁三个未解课题)
|
|
31
|
+
**目标**:用真实 token 跑只读探测矩阵(oauth-handshake.md §5 的解锁清单):
|
|
32
|
+
1. token vs `ck_` key 的端点可达差异(accounts / config / dosage-notify / agenttool / chat)。
|
|
33
|
+
2. **额度端点搜寻**:WorkBuddy 客户端与个人中心能看到的额度,其背后的 API——从 copilot.tencent.com 与 www.workbuddy.cn 两个域名找 plan / billing / credit 类端点,用 token 授权实测。网页 cookie API 若 token 进不去,诚实标注记入规则文档(可考察 OAuth 登录浏览器态与 plan API 的关系,但不下结论)。
|
|
34
|
+
3. refresh 轮换语义(旧 token 复跑观测作废码)。
|
|
35
|
+
**红线**:只读、低速率、单账号。本次额度端点探测是**用户明确授权的探测面扩展**(此前 cookie 体系按红线不碰,现在用户主动要求解锁);新发现全部写入 `docs/rules/quota-signals.md` 或新规则文档。
|
|
36
|
+
|
|
37
|
+
### G3 额度卡片(聊天页)
|
|
38
|
+
**目标**:dsh 聊天页/设置卡直观展示:本轮消耗(credit + token 拆解:prompt/缓存命中/输出)、今日合计、累计、近 N 轮趋势;数据源 `usage-meter.view()`。
|
|
39
|
+
**剩余额度**:G2 探到 API 就显示真实值;探不到就做「总额度手填 − 累计已耗」估算档,UI 必须标注"估算"。禁止假装有真实数值。
|
|
40
|
+
**低额告警**:dosage-notify 文案非空时卡片警示色 + 文案。
|
|
41
|
+
**验收**:卡片数值与 `codebuddy-plugin-usage.json` 最新 entry 一致;不阻塞聊天主链路(零行为变更纪律不变)。
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## 阶段二:模型动态化 + 上下文长度组件
|
|
46
|
+
|
|
47
|
+
### G4 模型列表动态化
|
|
48
|
+
**目标**:模型清单默认从 `/v3/config` 自动同步(启动拉取 + 设置卡手动刷新按钮),静态清单降级为离线兜底。
|
|
49
|
+
**约束**:同步写 settings.yaml 遵守踩坑 #6 纯净态纪律;拉取失败必须无感回落静态清单,绝不让模型选择器变空。
|
|
50
|
+
|
|
51
|
+
### G5 上下文长度调节组件
|
|
52
|
+
**目标**:设置卡里每个模型可调**上下文长度**(maxInputTokens 覆盖值,含 maxOutputTokens),改动同步 settings.yaml 即时生效。
|
|
53
|
+
**数据源**:`/v3/config` 的 maxInputTokens / maxOutputTokens 是每模型实际上限,作为默认值与调节上限。
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 阶段三:多服务商凭据中心(core 多上游的 UI 兑现)
|
|
58
|
+
|
|
59
|
+
### G6 服务商注册表(key 型,先落地)
|
|
60
|
+
**目标**:设置卡可添加多个 OpenAI 兼容上游(名称 + baseURL + key),每个上游一个 `providers/<name>/` 适配器实例,模型统一进选择器。
|
|
61
|
+
**已知可接 key 型上游**(用户手上就有额度):火山引擎 ark(Agent Plan key)、阿里云百炼。
|
|
62
|
+
**纪律**:新上游特化代码进 `providers/<name>/`,**core/ 零改动**(verify-core-generic 必须保持绿)。
|
|
63
|
+
|
|
64
|
+
### G7 本机登录态自动检测(登录型,渐进做)
|
|
65
|
+
**目标**:扫描本机已安装 agent 工具的登录态/凭据文件,检测到即在设置卡提示「发现 XX 凭据,一键导入」。
|
|
66
|
+
**用户点名的探测清单**(执行时逐个定位安装目录与凭据存储,以本机实际为准):TRAE、ZCode、豆包桌面端、Qoder、千问办公、Kimi、官方 CodeBuddy CLI,以及其他 agent plan 类工具。
|
|
67
|
+
**交互形态**:用户接受"一个一个登录"的渐进接入——今天导入一个、明天导入一个,互不影响;但**不做"一个一个手动配置"**——检测到就该是一键导入。
|
|
68
|
+
**红线**:只读检测;导入前逐个用户确认;凭据文件路径与内容不落日志;不碰凭据文件以外的私有数据。
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 全局验收(每阶段完成时自查)
|
|
73
|
+
|
|
74
|
+
1. 现有 CodeBuddy 链路零行为变更(UA / 错误码 / developer 重写 / 凭据来源不变)。
|
|
75
|
+
2. 四项回归全绿:`npm run verify` / `npm run verify:bridge` / `npm run verify:core` + `node scripts/verify-rotation.mjs`。
|
|
76
|
+
3. 新凭据(token/key)永不回传浏览器、不进日志(脱敏规则同现有 maskKey)。
|
|
77
|
+
4. 新网关事实写入 docs/rules/ 对应文档,STATE.md 追加进展。
|
|
78
|
+
5. UI 改动跑浏览器回归(踩坑 #4 / #15 / #16 / #18)。
|
|
79
|
+
|
|
80
|
+
## 过程指引(仅方向,不锁步骤)
|
|
81
|
+
|
|
82
|
+
- 顺序建议:阶段一 → 二 → 三。G3 依赖 G2 结论,G5 依赖 G4 数据,其余可并行处自行判断。
|
|
83
|
+
- 逆向/探测沿用六课题工作法:假设 → 预注册预测 → 实测 → 写规则文档(证据落 docs/probes/)。
|
|
84
|
+
- 遇到需要用户交互的点(浏览器登录、导入确认、手填总额度),明确停下提示,不替用户决定。
|
|
85
|
+
- 任何与本文件冲突的旧结论,以新实测为准,并更新规则文档。
|