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.
Files changed (121) hide show
  1. package/AGENTS.md +99 -0
  2. package/CHANGELOG.md +751 -0
  3. package/LICENSE +21 -0
  4. package/README.en.md +59 -0
  5. package/README.md +256 -0
  6. package/cordis.patch.yml +385 -0
  7. package/core/bridge.js +698 -0
  8. package/core/json-store.js +91 -0
  9. package/core/rotation.js +108 -0
  10. package/core/usage-meter.js +176 -0
  11. package/docs/diagnosis-cache-quota.md +181 -0
  12. package/docs/diagnosis-qoder-flash.md +67 -0
  13. package/docs/diagnosis-trae-3003.md +302 -0
  14. package/docs/goals/bridge-port-host-split.md +91 -0
  15. package/docs/goals/desktop-adaptation.md +106 -0
  16. package/docs/goals/qoder-cn-provider-design.md +308 -0
  17. package/docs/goals/settings-card-ux-redesign-plan.md +1680 -0
  18. package/docs/goals/settings-card-ux-redesign.md +162 -0
  19. package/docs/goals/trae-agent-v3.md +41 -0
  20. package/docs/goals/trae-work-cn-repair.md +44 -0
  21. 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
  22. package/docs/pitfalls.md +105 -0
  23. package/docs/reverse/trae-cloud-api.md +218 -0
  24. package/docs/reverse/trae-model-catalog.md +129 -0
  25. package/docs/reverse/traework-cn.md +520 -0
  26. package/docs/rules/STATE.md +198 -0
  27. package/docs/rules/content-moderation.md +54 -0
  28. package/docs/rules/dev-role-boundary.md +94 -0
  29. package/docs/rules/extra-providers.md +42 -0
  30. package/docs/rules/gateway-facts.md +91 -0
  31. package/docs/rules/oauth-handshake.md +76 -0
  32. package/docs/rules/prompt-cache.md +93 -0
  33. package/docs/rules/quota-signals.md +125 -0
  34. package/docs/rules/routing.md +84 -0
  35. package/docs/rules/templates/oauth-reverse-checklist.md +42 -0
  36. package/docs/rules/trae-surface.md +242 -0
  37. package/docs/rules/ua-validation.md +81 -0
  38. package/host-config.js +282 -0
  39. package/index.js +2306 -0
  40. package/lib/client.js +2893 -0
  41. package/local-scan.js +104 -0
  42. package/package.json +82 -0
  43. package/providers/ark/index.js +11 -0
  44. package/providers/bailian/index.js +10 -0
  45. package/providers/bigmodel/index.js +11 -0
  46. package/providers/codebuddy/agenttool.js +122 -0
  47. package/providers/codebuddy/catalog.js +227 -0
  48. package/providers/codebuddy/errors.js +44 -0
  49. package/providers/codebuddy/headers.js +36 -0
  50. package/providers/codebuddy/images.js +125 -0
  51. package/providers/codebuddy/index.js +123 -0
  52. package/providers/codebuddy/oauth.js +279 -0
  53. package/providers/deepseek/index.js +11 -0
  54. package/providers/moonshot/index.js +11 -0
  55. package/providers/openai-compat.js +177 -0
  56. package/providers/openrouter/index.js +27 -0
  57. package/providers/qoder/catalog.js +145 -0
  58. package/providers/qoder/cosy.js +419 -0
  59. package/providers/qoder/gateway.js +563 -0
  60. package/providers/qoder/index.js +116 -0
  61. package/providers/qoder/oauth.js +364 -0
  62. package/providers/qoder/qoder_auth.wasm +0 -0
  63. package/providers/qoder/quota.js +56 -0
  64. package/providers/qwen/index.js +15 -0
  65. package/providers/tool-pairing.js +129 -0
  66. package/providers/trae/catalog.js +103 -0
  67. package/providers/trae/errors.js +85 -0
  68. package/providers/trae/gateway.js +853 -0
  69. package/providers/trae/index.js +126 -0
  70. package/providers/trae/oauth.js +443 -0
  71. package/providers/trae/quota.js +75 -0
  72. package/providers/trae/remote.js +365 -0
  73. package/scripts/capture-cache.mjs +65 -0
  74. package/scripts/capture-traffic.mjs +83 -0
  75. package/scripts/hermes-probe-dev-role.mjs +263 -0
  76. package/scripts/measure-latency.mjs +253 -0
  77. package/scripts/probe-ark-thinking.mjs +298 -0
  78. package/scripts/probe-cache-decline.mjs +292 -0
  79. package/scripts/probe-cache-ttl.mjs +221 -0
  80. package/scripts/probe-cache.mjs +156 -0
  81. package/scripts/probe-codebuddy-efforts.mjs +355 -0
  82. package/scripts/probe-codebuddy-tier-wiring.mjs +244 -0
  83. package/scripts/probe-effort-gaps.mjs +133 -0
  84. package/scripts/probe-media.mjs +115 -0
  85. package/scripts/probe-moderation.mjs +159 -0
  86. package/scripts/probe-oauth.mjs +617 -0
  87. package/scripts/probe-qoder-attribution-arm8.mjs +92 -0
  88. package/scripts/probe-qoder-attribution-arm9.mjs +102 -0
  89. package/scripts/probe-qoder-attribution.mjs +266 -0
  90. package/scripts/probe-qoder-flash-confirm.mjs +94 -0
  91. package/scripts/probe-qoder-live.mjs +344 -0
  92. package/scripts/probe-qoder-matrix.mjs +274 -0
  93. package/scripts/probe-qoder-null-content.mjs +153 -0
  94. package/scripts/probe-qoder-pairing.mjs +308 -0
  95. package/scripts/probe-qoder-quota.mjs +162 -0
  96. package/scripts/probe-qoder-thinking-config.mjs +52 -0
  97. package/scripts/probe-qoder-thinking-efforts.mjs +269 -0
  98. package/scripts/probe-quota.mjs +136 -0
  99. package/scripts/probe-quota2.mjs +144 -0
  100. package/scripts/probe-routing.mjs +226 -0
  101. package/scripts/probe-trae-3003-diagnosis.mjs +139 -0
  102. package/scripts/probe-trae-agent-v3.mjs +399 -0
  103. package/scripts/probe-trae-efforts.mjs +149 -0
  104. package/scripts/probe-trae-live.mjs +147 -0
  105. package/scripts/probe-trae-max-effort.mjs +179 -0
  106. package/scripts/probe-trae-model-routing.mjs +381 -0
  107. package/scripts/probe-trae-thinking-scene.mjs +238 -0
  108. package/scripts/probe-trae-transport-outage.mjs +176 -0
  109. package/scripts/probe-ua.mjs +508 -0
  110. package/scripts/trae-model-catalog.mjs +632 -0
  111. package/scripts/verify-agents-md.mjs +45 -0
  112. package/scripts/verify-bridge.mjs +1041 -0
  113. package/scripts/verify-core-generic.mjs +302 -0
  114. package/scripts/verify-desktop-acceptance.mjs +184 -0
  115. package/scripts/verify-host-config.mjs +265 -0
  116. package/scripts/verify-models.mjs +390 -0
  117. package/scripts/verify-providers.mjs +255 -0
  118. package/scripts/verify-qoder-provider.mjs +1020 -0
  119. package/scripts/verify-rotation.mjs +308 -0
  120. package/scripts/verify-trae-model-catalog.mjs +284 -0
  121. package/scripts/verify-trae-provider.mjs +1451 -0
@@ -0,0 +1,302 @@
1
+ # 诊断报告:`trae 3003 all models failed`(PI_AI_ERROR)
2
+
3
+ **日期**:2026-08-24 | **现象报告**:用户经 dsh-codebuddy-plugin 使用 TraeWork CN
4
+ 模型,报 `trae 3003 all models failed`,宿主以 `PI_AI_ERROR` 包装。
5
+ **结论先行**:**Trae 服务端 inline_chat 面的模型解析层故障**(该面对一切 model 名
6
+ 返回业务错误 `3003 "all models failed"`),不是插件缺陷,与用户凭据/额度无关。
7
+
8
+ ## 1. 错误传播链(每一环都有实证)
9
+
10
+ ```
11
+ dsh(pi-ai) ──OpenAI方言──▶ 插件 Trae 网关(127.0.0.1:3902, providers/trae/gateway.js)
12
+ settings: traeEnabled=true, traeChatTransport="inline"(默认), traeChatBaseURL=mchost
13
+ ──POST /api/agent/v3/llm_utils_chat (function=inline_chat)──▶ trae-api-cn.mchost.guru
14
+ Trae 云端:HTTP 200 SSE,事件流 = error{"code":3003,"message":"all models failed"} + done
15
+ 网关映射 → 502 {"error":{"message":"trae 3003 all models failed","code":3003}}
16
+ pi-ai 收到非 2xx → 包装为 PI_AI_ERROR 呈现给用户
17
+ ```
18
+
19
+ `PI_AI_ERROR` 只是宿主 LLM 层对上游非 2xx 的通用包装;真正的内容是网关透传的
20
+ Trae 业务码 3003。
21
+
22
+ ## 2. 根因判定:服务端 inline 面故障
23
+
24
+ 对照实验(同凭据、同头组、同信封 `buildChatRequest`,唯一变量=模型名/function;
25
+ 证据 `docs/probes/trae-3003-diagnosis-1787564352939.json`、`…4582671.json`):
26
+
27
+ | 实验 | function | model | 结果 |
28
+ |---|---|---|---|
29
+ | A | inline_chat | glm-5.3(非默认) | SSE error **3003** "all models failed" |
30
+ | B | inline_chat | kimi-k2.6(文档记载的账户默认) | SSE error **3003** |
31
+ | B' | inline_chat | kimi-k2.7-code / Doubao-Seed-Code / 不带 model 字段 | 均 **3003** |
32
+ | C | chat_v3 | glm-5.3 | **200 正常回答**("成功"),信封/鉴权全链路健康 |
33
+
34
+ **排除项(逐一证伪)**:
35
+ - **非凭据问题**:GetUserInfo 有效、同 JWT 在 chat_v3 面完整走通对话。
36
+ - **非配额问题**:`ide_user_ent_usage` 实测 IDE 池(endpoint=0)主包 2000 只用
37
+ 0.63 credits;work 池(endpoint=1)1803/2000 且另有十余个 200-credit 包在期。
38
+ - **非限流**:raw 面 4011 会显式报 "requests have exceeded the rate limit",
39
+ 且 C 实验紧随 A/B 成功。
40
+ - **非信封/头组回归**:同一构造器产出的请求 chat_v3 通过;0.8.4 已用真实端到端
41
+ 双绿锁定过信封形态(CHANGELOG 0.8.4)。
42
+ - **非插件路由代码缺陷**:网关对 3003 的映射路径(SSE error → 502 结构化错误)
43
+ 与 mock 回归一致;失败流里连 `timing_cost` 都没有——服务端根本没走到选模型
44
+ 成功的那一步。
45
+
46
+ **服务端行为三阶段时间线(时变!)**:
47
+ 1. ≤08-23 深夜 UTC:inline_chat 对任意 model 名返回 200 并静默改派到账户默认
48
+ (证据 `docs/probes/trae-chat-live-17875277*.json`:glm-5.2/glm-5.3/V4-Pro 全通)。
49
+ 2. 08-24 ~08:06 UTC:改为硬错——仅非默认模型 3003(证据 `trae-model-routing3-*`,
50
+ 即 CHANGELOG 0.8.4 记录的"function 位钉死")。
51
+ 3. 08-24 ~09:39–10:05+ UTC:**扩大到一切 model 名(含默认、含缺省 model 字段)**
52
+ (本诊断 A/B/B' 复现三次,跨约 30 分钟)。remote 面同时段出现间歇性边缘故障(§3)。
53
+
54
+ ## 3. 次要发现(同日取证)
55
+
56
+ - **remote create_session 间歇性裸 404**:`/api/remote/v1/chat_sessions` 在
57
+ TLB/nginx 节点间路由表漂移——带凭据请求命中缺路由节点时返回**裸文本**
58
+ `404 Not Found`(content-type: text/plain);无凭据探测同路径则稳定 401 JSON
59
+ (业务鉴权层正常)。该 404 与请求头组/体内容无关(逐头逐字段二分均复现/消失
60
+ 与节点有关),数分钟窗口后自愈。**业务级拒绝恒为 JSON 信封**——这是判别
61
+ 边缘层 vs 应用层的可靠指纹。
62
+ - **边缘 WAF 动态拦截**:高频探测触发全路径 403 空体(含无凭据请求),冷却
63
+ 数分钟自愈。联调节奏必须克制。
64
+ - **991502 并发门**:`solo_agent_parallel_limit` 用满时报业务 429;只创建会话
65
+ 不消费事件流的僵尸会话同样占位,只能等沙箱 TTL 自灭(stop 端点对未运行
66
+ 会话回 409 "chat session is not running")。
67
+ - remote 模型清单出现新默认位(solo_agent_remote 默认=Doubao-Seed-Code、
68
+ solo_design_remote 默认=kimi-k2.7-code,证据 `trae-remote-models-*`),
69
+ 印证服务端当日在大规模调整模型注册表——与 inline 面故障时段吻合。
70
+
71
+ ## 4. 已落地的加固(0.8.5)
72
+
73
+ 1. **errors.js**:码表新增 3003/991502 语义;新导出 `formatTraeErrorMessage`,
74
+ 对已知码在透传消息后追加**可操作处置提示**(如 3003 → 建议切 remote 通道)。
75
+ 2. **gateway.js**:三处错误文案(inline 非 OK 上游 / inline SSE error /
76
+ remote SSE error)统一走 `formatTraeErrorMessage`。
77
+ 3. **remote.js**:`createRemoteSession` 对**裸文本 404/403(边缘漂移指纹)**
78
+ 自动短退避重试一次(创建失败不产生会话,幂等安全);持续失败时报文带自愈指引。
79
+ 4. **verify-trae-provider.mjs** 新增 4 断言锁以上形态(77 项断言全绿):
80
+ mock 云端发 3003 → 网关消息含提示且 code 透传;mock 首次裸 404 → 重试成功;
81
+ 持续裸 404 → 文案带指引;formatTraeErrorMessage 单元三态。
82
+ 5. 规范化诊断脚本 `scripts/probe-trae-3003-diagnosis.mjs`(可重跑复现本轮实验)。
83
+
84
+ ## 5. 用户侧操作指引
85
+
86
+ - **立即恢复可用**:设置卡 TraeWork CN 分区把「聊天传输」从 `inline` 切为
87
+ `remote`(真模型路由;注意耗 work 额度池、不支持 OpenAI tools)。
88
+ - 或:稍后重试 inline 通道等服务端恢复(该面历史上多次自愈/翻转)。
89
+ - 若 remote 报"边缘节点路由漂移"提示:等几分钟再试(TLB 节点自愈)。
90
+ - 报 991502:等待存活会话过期或在 Trae 端手动停止会话。
91
+
92
+ ## 6. 第二轮追踪(2026-08-24 ~10:18–10:36 UTC,证据 docs/probes/trae-e2e-validation-*.json)
93
+
94
+ 服务端故障在诊断后约 2.5 小时仍未自愈,且波及面扩大:
95
+
96
+ - **inline 面**:kimi-k2.6 持续 3003(09:39 / 10:05 / 10:20 / 10:33 / 10:36 五次采样一致)。
97
+ - **remote 面**:create_session 的节点漂移 404 持续间歇(09:46→404、09:52→200、
98
+ 10:05→404、10:20→404、10:26→404、10:36→404)。关键旁证:**同窗口内 GET 类
99
+ 路由(list/detail)稳定可用、仅 POST create 漂移**——按端点粒度的节点路由
100
+ 不稳,进一步支持 TLB 节点表漂移判定(非账号级封禁:无凭据探测同时段可复现
101
+ 业务级 401 JSON)。
102
+ - **0.8.5 加固已在真实故障中验证**:`createRemoteSession` 的自动重试与"边缘
103
+ 节点路由漂移…可稍后重试或改用 inline 通道"指引文案均按设计触发并透传到
104
+ 用户可见错误中。
105
+ - 当日实践建议更新:两端同时受影响时,**唯一正确动作是退避重试**(本插件网关
106
+ 已对 remote create 自动重试一次;调用方层面的长间隔重试同样安全——失败请求
107
+ 不产生会话、不耗额度)。
108
+
109
+ ## 7. 第三/四轮追踪(2026-08-24 ~12:47–12:50 UTC):加固已部署到用户真实路径
110
+
111
+ - **运行时发现**:本机 dsh web 实例从开发目录加载本插件(进程包装命令可见
112
+ `cd /root/dev/dsh-codebuddy-plugin`)。故障期间运行的两个实例均为旧代码;
113
+ 经 `code/restart-dsh.sh` 重启后单实例(3080)加载 **v0.8.5**,3901/3902 桥、
114
+ settings 路由、`GET /v1/models` 目录全部健康。
115
+ - **用户真实路径复现 → 修复对照**(同一请求 `POST 127.0.0.1:3902/v1/chat/completions`):
116
+ - 重启前(旧代码):`502 {"error":{"message":"trae 3003 all models failed","code":3003}}`
117
+ ——即用户报告的原始形态,pi-ai 包装为 PI_AI_ERROR。
118
+ - 重启后(v0.8.5):同一错误现在携带完整自助指引——
119
+ `"trae 3003 all models failed (Trae 服务端 inline 通道当前对该模型名返回此错——非凭据/配额问题;…请在插件设置卡把「聊天传输」切为 remote,详见 docs/diagnosis-trae-3003.md)"`
120
+ - **事故时长**:inline 面 3003 自 ~08:06 UTC 起持续未自愈(最后一次采样
121
+ 12:51 UTC,约 4.8 小时,经运行网关实测);remote
122
+ create 的节点漂移窗口同样间歇存在(12:49 仍 404,重试+指引按设计触发)。
123
+ 两面同时受影响期间,插件侧已无更多可为——错误可读、重试自动、指引明确。
124
+ - **运维提示**:插件 JS 层修复需重启 dsh 生效;`traeChatTransport` 等设置项
125
+ 为逐请求热读取,切换传输无需重启。
126
+ - **操作入口验证(round 5)**:重启后的实例 settings 视图含 `traeChatTransport`
127
+ (当前 inline)/`traeEnabled`/`traeChatBaseURL`——指引中"设置卡切 remote"
128
+ 的控件真实可用,闭环成立。
129
+
130
+ ## 8. 第六轮:第三种失败模式(本地代理死态→无限挂起)与超时护栏
131
+
132
+ - **实测现象**(12:50–12:53 UTC):网关 POST 偶发**无限挂起**(GET 路由正常、
133
+ 进程事件循环正常)。排查:直连 Trae 云端同一信封 385ms 即回(云端无恙);
134
+ 运行实例环境继承了桌面代理 `http_proxy=127.0.0.1:7890` 且 no_proxy 不含
135
+ trae 域——代理对 trae POST 存在"收下请求不回应"的间歇死态。
136
+ - **插件缺陷定级**:inline 上游 fetch 与 remote create 此前**均无客户端超时**
137
+ ——任何"连上不出头"的死态都会转化为用户请求无限挂死。属真实健壮性缺陷,
138
+ 与本次服务端事故相互独立、但被其放大暴露。
139
+ - **修复(0.8.5 追加)**:
140
+ - gateway.js inline 上游 fetch 加**首字节护栏**:响应头 45s 未达即 abort 并
141
+ 回结构化错误(文案带自助指引);头到达后计时即清除,SSE 长流不受影响。
142
+ 可经设置 `upstreamFirstByteTimeoutMs`(1000–300000ms)覆盖,默认 45s。
143
+ - remote.js `createRemoteSession` 整体限时 20s(测试可 `{timeoutMs}` 覆盖),
144
+ 超时报错带指引;边缘漂移重试逻辑不变。
145
+ - `code/restart-dsh.sh` 启动 dsh 时清除四个代理变量——宿主上游不再依赖
146
+ 桌面代理的健康度。
147
+ - **回归**:verify-trae-provider 新增 2 断言(mock 零字节挂死 → inline 限时
148
+ 502 带指引 / remote create 限时失败带指引),79 项断言全绿。
149
+ - **round-7 部署验证**:新代码已在运行实例生效(settings 视图出现
150
+ `upstreamFirstByteTimeoutMs:45000`);经运行网关实测 POST 365ms 即回
151
+ 结构化错误。运维注:重启脚本会 pkill 全部 dsh web——若助手会话自身宿主于
152
+ dsh,重启即中断该会话(本轮两次工具调用中断的直接原因),但 setsid 先行
153
+ 脱离,脚本效果不受影响;代理变量的彻底剥离留待宿主侧下次常规重启。
154
+
155
+ ## 9. 第八轮追踪(2026-08-24 ~14:12–14:16 UTC):事故持续 ~6h;v0.8.5 回退端到端验证 + tools 边界确认为用户可见根因
156
+
157
+ - **事故仍在持续**:规范化诊断脚本重跑(证据 `docs/probes/trae-3003-diagnosis-1787581361787.json`
158
+ )——inline_chat 对 glm-5.3 与账户默认 kimi-k2.6 一律 SSE error 3003(267/616ms,
159
+ 无 timing_cost),同信封 chat_v3 正常出文本(改派 seed-code-lite-dev-0602-v1-part1)
160
+ ;双额度池健康(IDE 主包 2000 只用 0.64、work 池 1809.6/2000)。自 ~08:06 起
161
+ 未自愈。
162
+ - **v0.8.5 自动回退经运行实例端到端验证生效**:对运行网关
163
+ `POST 127.0.0.1:3902/v1/chat/completions` 发无 tools 流式请求(模型名
164
+ DeepSeek-V4-Flash-Official),HTTP 200 真实回答 + `: trae-reroute requested=… actual=seed-code-lite-dev-…`
165
+ 注释行——inline 首试 3003 后自动落 chat_v3,改派诚实披露按设计工作。
166
+ - **用户仍见裸错误的机制定位**:回退条件含 `!hasTools`(gateway.js:604)——dsh
167
+ 主聊天请求恒带 agent 工具表 → 永不回退 → 网关 502 `{code:3003}` → pi-ai 包装
168
+ PI_AI_ERROR。实测复现:带 tools 请求返回
169
+ `"trae 3003 all models failed (Trae 服务端 inline 通道当前对该模型名返回此错——…请把「聊天传输」切为 remote…)"`。
170
+ 即:**用户报告的报错形态 = 服务端 inline 面故障 × 带工具请求不静默降级的设计边界**;
171
+ 0.8.5 起该错误已携带完整自助指引(旧进程时代看到的是无指引裸文案)。
172
+ - **remote create 边缘漂移同窗口间歇存在**(诊断脚本 [R] 步 404 Not Found 裸文本
173
+ )——此刻切 remote 也可能先撞漂移(自动重试一次已内置),两面同时受影响时唯一
174
+ 正确动作仍是退避重试。
175
+ - **次要风险复核**:运行实例(21:43 CST 启动)环境仍继承桌面代理变量
176
+ (`http(s)_proxy=127.0.0.1:7890`,no_proxy 不含 trae 域)——restart 脚本的剥离
177
+ 修复未及本进程;首字节护栏(45s,已确认在运行代码内)兜住挂死风险,但代理死态
178
+ 会表现为 45s 超时而非快速失败。宿主侧下次常规重启可彻底清除。
179
+
180
+ ## 10. 第九轮:逆向漏项重审(2026-08-24 ~14:40–15:10 UTC)——结论:逆向无漏,但补了两条实证 + 一条兼容增强
181
+
182
+ **用户怀疑**:`trae 3003 all models failed` 会不会是**逆向漏了什么**(字段/端点/版本号)。
183
+ 重审方法:官方客户端当日网络日志取证 + 二进制头组差异比对 + 两域名/版本号头/逐头二分实测。
184
+
185
+ **结论先行**:**没有漏**。① 官方客户端当日也用同一端点(llm_utils_chat)、同一
186
+ 307 重定向目标(api5-normal.mchost.guru)、同一认证形态;② 官方主聊天走 remote
187
+ 通道(当日 `chat_sessions` 提及 576 次 vs `llm_utils_chat` 20 次),官方自己在
188
+ 事故期也不依赖 inline 面;③ 实测两域名同信封同为 3003、逐头二分加回官方头组
189
+ 均无行为差异 → 域名/版本号头/头组**均非** 3003 根因。**逆向没有漏掉"能绕开
190
+ 3003"的东西**——服务端 inline 面确实故障,与上轮判定一致。
191
+
192
+ **新增实证**:
193
+ - **官方 307 重定向**:官方 llm_utils_chat 请求经 TTNet 内部 307 从
194
+ `trae-api-cn` 落到 `api5-normal.mchost.guru`(当日 586 次 307 全落该域)。
195
+ 但 api5-normal 直连实测同样 3003 → 不是"官方连的节点好、插件连的节点坏"。
196
+ - **官方头组清单**(从官方网络日志逐头提取,token 已脱敏):version-code 用
197
+ 当日构建号 `20260811`(插件钉死 `20260401`)、`x-app-version:"default"`、
198
+ `x-ide-version:"0.1.52"`、`x-bridge-transport:"aha"`、`x-request-pin` +
199
+ `x-requested-at`(**成对**,缺 `x-request-pin` 会 400 "x-request-pin or
200
+ x-requested-at is empty")、`request-traffic-type:"prod"`、
201
+ `user-agent:"TraeClient/TTNet"`、`x-lgw-req-sdk-type:"3"`、`x-lscbd-*`、
202
+ `x-net-sdk-domain-dispatch:"1"`、`package-type:"stable_cn"` 等。逐头加回
203
+ 二分:**均不改变 3003 行为**;唯一有响应差异的是 `x-request-pin`/
204
+ `x-requested-at` 成对(缺了就 400,与 3003 无关)。
205
+ - **官方日志的 SUCCESS 不可作为"官方未撞 3003"的证据**:网络日志只记录链路层
206
+ (307→200),响应体被 TTNet 吞掉不落盘;官方 UI 走 remote 通道,inline 面
207
+ 官方自己也不跑。
208
+
209
+ **关键纠偏(临时波动警示)**:同信封同 token 同内容,chat_v3 曾短暂返回
210
+ **1005 套餐门**(`extra:{"plan":1}`,kimi/glm/DeepSeek 三模型全中)——若据此
211
+ 判定"账号套餐到期"就错了。数分钟内自愈回 200(内容二分证伪:同 `回复成功`
212
+ 现在 200 成功)。**单次 1005 不可作账号级套餐判定**,需重试交叉验证。这也说明
213
+ 故障期服务端在该域名下有多重不稳定(3003 持续 / 1005 闪断 / 超时)。
214
+
215
+ **落地增强(v0.8.6 候选)**:网关 inline 出站**跟随官方 307 重定向**
216
+ (fetch redirect:'follow',官方 TTNet 即此语义),并补齐 `request-traffic-type`/
217
+ `package-type`/`x-lgw-req-sdk-type` 三个无害指纹头(实测对响应无影响)。
218
+ **不**伪造 `x-request-pin`/`x-requested-at` 对——服务端见 pin 头即强制 base64
219
+ 校验,外部复刻者无官方密钥无法生成合法 pin,发了必 400 `base64 decode failed`
220
+ (round 9 逐格式实测:官方日志原值 89532a712e043c54 直接复用也 400)。
221
+ 3003 根因仍在服务端 inline 面,无客户端可绕;**切 remote 传输仍是唯一真模型
222
+ 选择 + 恢复路径**。
223
+
224
+ ## 11. GitHub 调研与可用的工程解法(round 6–7)
225
+ - `autumnsentiment/Trae2api-cn`(★10,最后更新 2026-08-20):生产参照。默认
226
+ `UPSTREAM_MODE=raw` 只直连 `llm_utils_chat`——其协议/信封与本插件完全一致;
227
+ remote 模式同我们 chat_sessions 协议。其回退链含 `/api/ide/v1/chat` 与
228
+ `/api/agent/v3/create_agent_task`(后者参考 laojichao/trae-local-api)。
229
+ - `ProjectEio/trae2api`(★12,Go,2026-07):以 **create_agent_task 为唯一聊
230
+ 天端点**,模型用内部 config_name(如 gemini_2.5_flash_premium),带模板渲
231
+ 染/mcp 工具表/history_id_list 的完整 IDE agent 协议。
232
+ - **结论:无现成"绕过 3003"的社区解**——事故晚于所有社区更新(8-20 后)。
233
+
234
+ **本轮实测收敛出的可用通道**:
235
+ - `create_agent_task` 信封绑定字段已逐字段探明(conversation_id/user_id/
236
+ device_id/agent_type/model_name/config_name/ide_version/user_input)→
237
+ HTTP 200 SSE,但报 `4001 config item is empty`——solo_agent_lite 的模型
238
+ 配置注册表同样为空(含 ProjectEio 目录里的老名字),与 inline_chat 同根。
239
+ - **chat_v3 是当前唯一活着的面**:同信封实测正常出文本(改派 seed-code-lite,
240
+ timing_cost 可证)。inline_chat 连已知存在的 seed-code-lite 名也 3003 ——
241
+ 该面的解析层整体故障,而非注册表缺项。
242
+
243
+ **落地修复(0.8.5 追加):inline 3003 事故回退**
244
+ - 网关在 inline_chat 遇 SSE error 3003 且请求无 tools 时,自动以 chat_v3 重
245
+ 试一次;回答照常返回,改派由既有机制诚实披露(SSE 注释行 / message.note
246
+ / 计量记真实模型),绝不假装请求模型被服务。
247
+ - 带 tools 的请求不静默降级(工具语义不可靠),维持原错误透传。
248
+ - 回归 +2 断言(81 项全绿):mock 仅对 inline_chat 注入 3003 → 客户端拿到真
249
+ 实文本、note 标注 served-by/requested、两次上游调用、计量记真实模型。
250
+
251
+ **2026-10-04 补记:内层错误签名已明确(思考档位课题取证时复现)**
252
+
253
+ - 复跑 `node scripts/probe-trae-efforts.mjs`(默认模型)与
254
+ `node scripts/probe-trae-live.mjs --chat` 均得同一 498 字节 SSE:`event:error`
255
+ `code 3003`,内层 400 为
256
+ `{"code":"InvalidParameter","message":"Invalid combination of reasoning_effort and thinking type: high + disabled"}`。
257
+ - 判读:inline_chat 这个 scene 把 **thinking 置为 disabled**,而这些模型
258
+ (glm-5.3 / Doubao-Seed-2.1-Pro 等)**默认档是 high** ⇒ 组合非法。**与请求里
259
+ 带没带 `reasoning_effort` 无关**(基线臂同样 3003),且与旧结论「inline_chat
260
+ 面对一切 model 名恒 3003」一致——这次拿到了内层真因。
261
+ - 影响:Trae 通道的**思考档位**无从验证(唯一携带该字段的 inline_chat 面不通,
262
+ 可用的 chat_v3 面请求体没有 effort/thinking 字段)⇒ 路由维持不开 `compat`、
263
+ 不出档位。证据 `docs/probes/trae-efforts-*.json` +
264
+ `docs/probes/trae-chat-live-1791083764857.json`;事实表见
265
+ docs/rules/gateway-facts.md「TraeWork CN 通道事实」。后续课题 = 找能把
266
+ thinking 置 enabled 的 scene/参数组合。
267
+
268
+ ## 12. 第十二轮:用户复报「还是不能用」(2026-10-04 复诊)——inline 仍 3003,三传输出路实测
269
+
270
+ - **复现**:用户桌面实例主聊天报 3003(内层同款 `high + disabled`,Request id
271
+ `0217911103827…`)。规范化诊断重跑(`docs/probes/` 当日落盘):inline_chat 对
272
+ glm-5.3 与默认 kimi-k2.6 全臂 3003——**自 08-24 起第 6 周仍未自愈**(scene
273
+ thinking=disabled × 模型默认档 high 的组合非法,与请求内容无关)。
274
+ - **三传输出路探测**(`scripts/probe-trae-transport-outage.mjs`,证据
275
+ `docs/probes/trae-transport-outage-1791110859199.json`):
276
+ - **remote 面(chat_sessions):健康**——create/events 双 200、真实文本、
277
+ `actualModel=glm-5.3`(真模型路由),21s;
278
+ - **chat_v3 面:本次也 3003**——内层 500 `ModelLoading`(60s 慢失败,glm-5.3
279
+ 服务端加载故障),8 月「唯一活面」结论**不持续**,该面时好时坏;
280
+ - **chat_v3 + tools:同样 ModelLoading**——tools 行为无从判定。
281
+ - **用户侧真实处境(本轮澄清的结构性边界)**:dsh 主聊天恒带 agent 工具表 ⇒
282
+ ① inline=3003(服务端);② remote=网关诚实拒(`remote-no-tools` 400——云端
283
+ 沙箱 agent 无法驱动本地工具环,放开只会静默断工具);③ chat_v3=时坏。
284
+ **带工具环的 agent 对话在 Trae 通道当前整体不可用,插件侧无解**;纯文本会话
285
+ 切 remote 即恢复。
286
+ - **本轮处置**:①用户文件层 `traeChatTransport` 已由 inline 切 **remote**
287
+ (逐请求热读取,免重启;经运行网关实测:无 tools → 200 真实流式回答,
288
+ 带 tools → 400 remote-no-tools);②3003 处置提示文案补上 remote 工具环边界
289
+ (`providers/trae/errors.js`,避免「切了 remote 还是不能用」的二次困惑——
290
+ errors.js 属服务端代码,**重启 dsh 后生效**;verify-trae-provider 109 项全绿
291
+ 含新断言锁)。
292
+ - **后续课题(未决)**:inline 全臂 3003 已 6 周,`traeChatTransport` 默认值
293
+ `inline` 是否改 `remote` 属产品决策(remote 耗 work 池、不支持工具环、会话
294
+ ~20s 慢启动),需用户拍板,本轮不动默认值。
295
+
296
+ ## 13. 销案(2026-10-05):agent 面(solo_work_lite)探针证实可用并落地——「插件侧无解」结论终结
297
+
298
+ - **结论更新**:§12 的「带 dsh 工具环的 agent 对话在 Trae 通道当前整体不可用,插件侧无解」在 2026-10-05 被推翻——同一端点 `llm_utils_chat` 的 `function=solo_work_lite` 面(社区参照:dsh-connect-trae SOLO_ROUTE_DECISION / Trae2api-cn build_llm_chat_body)经 8 臂真实探针(`scripts/probe-trae-agent-v3.mjs`,证据 `docs/probes/trae-agent-v3-*.jsonl`)证实:**纯聊天 200 流式、接受 OpenAI tools + tool_choice=auto、返回结构化 tool_calls(function_call 键、按 index 增量)、并行调用单事件双发、role:tool 回传后产出最终回答**。决策门(纯聊天臂 + 两轮工具闭环臂)PASS。
299
+ - **落地**:`traeChatTransport` 新增第三档 `'agent'`(设置卡可选,逐请求热读取免重启);出站历史 assistant.tool_calls 键=function_call(该面 proto 硬要求,误用 OpenAI function 键报 2001「required field Name is not set」);3003 事故回退不适用于 agent 面(不回退 chat_v3);错误码表补 2001/4001/4011/4023/9074;verify-trae-provider 131→**141** 断言。
300
+ - **如实标注的边界(不虚标,踩坑 #42 纪律)**:①**模型路由仍被 function 位钉死**——agent 面任何 model 名都 200 但 timing_cost.provider_model_name 恒为 glm-5.2(A6 臂 kimi-k2.6/DeepSeek-V4-Flash 实测),改派由 SSE 注释行/message.note 诚实披露;「模型可用」在该面 = 「目录模型名可发、实际由 glm-5.2 服务」。②**reasoning_effort 被忽略**(A5 臂与 A2 同形态)——档位注入仅保留在 remote 面。③E1 错模型名/E2 坏参数被静默容忍(该面宽容)。④**inline 面 3003 本身未愈**(本日未复测,第 6 周+)——agent 面是绕路而非修复。
301
+ - **额度**:token_usage SSE 事件携带真实计数(含 reasoning_tokens / cache_read_input_tokens)如实计量;pay 池差分分辨率(0.01 credit)对小探测不可见(前=后=430.394),与 Qoder 族「小额探测取整吞掉」同现象,扣费事实以 token_usage 计数为准。
302
+ - **后续课题(未决更新)**:§12 的「默认值是否改 remote」问题现在有了第三选项 agent(支持工具环);默认值决策仍需用户拍板,本 goal 不动默认值。
@@ -0,0 +1,91 @@
1
+ # Goal:桥端口按宿主环境分流(web UI 线 / 桌面 GUI 线)
2
+
3
+ > 执行模式:长任务 goal。本文只定义**角色、意图、边界与验收**;实现路径由执行 agent 在边界内自主决定。
4
+ > goal 写法参照 GitHub 官方 agentic-workflows 范式(`githubnext/agentics`)+ 本仓库 desktop-adaptation.md 同构:
5
+ > **角色定位 + 意图/为什么 + 分阶段意图(非逐行指令)+ 已验证事实 + 未知数(探测先行)+ 产出契约 + 边界 + 裁判纪律**。
6
+ > 必读裁判依据:`AGENTS.md`(全部踩坑)+ `docs/rules/*.md` + `host-config.js` 头注释 + `docs/goals/desktop-adaptation.md`(desktop 接入全案)。
7
+ > 进展记录:每完成一个 G 项,在 `docs/rules/STATE.md` 追加一段。
8
+ > 状态:**已落地(G3–G7 一轮完成,0.16.0)**(2026-10-03:desktop Qoder 3913 / Trae 3912 独立监听、web 3902/3903 不变,机制证据 docs/probes/port-split-2026-10-03.json、G5 共存端到端证据 docs/probes/coexist-e2e-port-split-2026-10-03.json——desktop 经 3913 真实聊天、关 web 后桌面独立成立、web 重启两线各自持桥零 EADDRINUSE;G6 离线九套件全 PASS;G7 文档四件套同日收尾)。
9
+ > 驱动:用户要求"window 版本的适配,版本控制分 web ui 还有 Gui";0.15.1 已修诊断口径(借桥不再报成故障),本 goal 消除借桥本身。
10
+
11
+ ## 角色与使命(why)
12
+
13
+ 你是 dsh-tap 的**宿主分流负责人**。现状:desktop(Electron GUI,:19387)与 web(:3090)是**两个进程、共享同一份配置** `~/.dsh/codebuddy-plugin.json`,桥端口写死(`bridgePort:3901`/`traeBridgePort:3902`/`qoderBridgePort:3903`)。两实例同跑时先占方持有桥、后到者 `EADDRINUSE` 退避、聊天路由先占方——**桌面 GUI 的 Qoder/Trae 可用性绑死在 web 实例在线**(用户关掉 web,桌面这两条通道就瘫)。
14
+
15
+ 你的使命:让桥端口**按宿主环境分流**——web 线与桌面 GUI 线各自独立监听、互不借桥,桌面成为能独立站立的应用。这是 0.15.x desktop 适配的自然延伸(从"装得上/看得见/用得了"到"独立得了")。
16
+
17
+ ## 意图(要达成什么,而非怎么做)
18
+
19
+ 1. **桌面独立**:desktop 的 Qoder/Trae 网关监听自己的端口(**3902→3912、3903→3913**),不再借 web 的桥;web 线端口不变(3901/3902/3903)。
20
+ 2. **互不干扰**:web 与 desktop 同跑,各自持有各自桥,零 EADDRINUSE、零借桥;一方关停不影响另一方通道可用。
21
+ 3. **CodeBuddy 桥 3901 暂不动**(主聊天入口,分流动到默认模型路由,面最大风险最高;验证 Qoder/Trae 分流成立后再议是否纳入)。
22
+ 4. **零回归**:web 线行为与端口完全不变;desktop 既有适配(0.15.x 落地)不破。
23
+
24
+ ## 已验证事实(立项前实测,2026-10-03,出处标注)
25
+
26
+ | 事实 | 出处 |
27
+ |---|---|
28
+ | 三端口字段:`bridgePort` 默认 3901(index.js:108)、`traeBridgePort` 3902(:136)、`qoderBridgePort` 3903(:155),schema 可编辑 | `index.js:108/:136/:155` |
29
+ | 镜像 baseURL **跟随端口**:qoder `http://127.0.0.1:${qoderBridgePort}/v1`(:982)、trae 同构(:1083)——改端口重铺镜像即热生效 | `index.js:982/:1083` |
30
+ | 桥启停按 `s.<port>` 对账:`apply()` 读 `s.bridgePort/traeBridgePort/qoderBridgePort` 决定 listen(:1954/:1992/:2029),EADDRINUSE 落 `lastError` 不炸 | `index.js:1954/:1992/:2029` |
31
+ | `localAllowedOrigins` 字段已落地(0.15.0):通用白名单,`localGuardFailure`/`sameOrigin` 消费,desktop 文件层 `["dsh-app://app"]` 三连实测 200/200/403 | `index.js:116/:1404`、CHANGELOG 0.15.0 |
32
+ | 共享配置根:`DSH_HOME = process.env.DSH_HOME ?? ~/.dsh`(:82),web/desktop 共用 ⇒ **"按宿主不同端口"不能写进这份共享配置**(两进程读同一份仍撞) | `index.js:82` |
33
+ | desktop 宿主 = Electron 专管,`dsh --profile desktop` 被 CLI 拒(`rejectElectronProfile`,bin.js:36);host 进程命令行含 `dsh-desktop-host/lib/index.js` 与 desktop profile 目录 | dsh bin.js:36、desktop 端到端证据 |
34
+ | 借桥实证:web(:3090, PID 26028) 先占 3901/3903,desktop 桥 EADDRINUSE 让位、聊天路由先占方 | `docs/probes/desktop-e2e-2026-10-03.json`、STATE.md |
35
+
36
+ ## 核心设计约束(必须想清再动手)
37
+
38
+ **配置文件共享 ⇒ 端口必须按"运行时宿主"解析,不是按配置写死。** 两个进程读同一份 `codebuddy-plugin.json`,若分流值写进配置,两进程读到同一份还是会撞端口。故端口解析 = 进程启动时判定"我是谁(web 还是 desktop)",再决定监听哪个端口。**"我是谁"的可靠信号是本 goal 第一未知数(U1)**——候选(须实测哪个可靠,勿凭记忆选):
39
+
40
+ | 候选信号 | 依据 | 风险 |
41
+ |---|---|---|
42
+ | profile 目录/名 | desktop host 命令行含 `…\profiles\desktop`;web 实例跑 `profiles\web` | 插件进程能否读到自身 profile 名待证 |
43
+ | 宿主注入的环境变量 | desktop host 可能注入标识(Electron/ELECTRON_RUN_AS_NODE 等) | 未实测是否存在稳定变量 |
44
+ | 进程命令行 | host 命令行含 `dsh-desktop-host/lib/index.js` | 依赖宿主实现细节,脆 |
45
+ | 运行时 Origin | 设置路由见过 `dsh-app://app`(desktop)vs 浏览器 Origin(web) | 只在请求时有,启动期 listen 时无 |
46
+
47
+ **原则**:分流逻辑收进**组合根的端口解析处**(index.js 读取 `s.<port>` 的单一入口),归一为一个"解析有效端口"的函数;宿主差异按 desktop-adaptation 同款纪律收口,**不撒 `if (desktop)` 分支**(§4a 静态守卫口径延续)。
48
+
49
+ ## 顶层未知数(探测先行,勿凭记忆动手)
50
+
51
+ | # | 未知数 | 决定什么 |
52
+ |---|---|---|
53
+ | U1 | 插件进程可靠区分"我是 web 还是 desktop"的信号(见上表四候选) | 端口解析机制是否可行、怎么写 |
54
+ | U2 | 分流转置后,desktop 的镜像 baseURL(:982/:1083)是否自动跟随 3912/3913,还是需显式重铺 | 镜像写回步骤 |
55
+ | U3 | desktop 的 Origin 白名单是否需随新端口调整(`dsh-app://app` 已 allowlist;3912/3913 的 Host 回环门是否照常) | Origin 白名单改动面 |
56
+ | U4 | 用户已有配置(`qoderBridgePort:3903` 等)如何迁移:web 读 3903、desktop 读 3913 的共存语义 | 迁移与兼容 |
57
+
58
+ ## 产出契约(每阶段必须交付什么)
59
+
60
+ - **G1 侦察报告**:回答 U1——实测出可靠的宿主区分信号(给出证据:desktop/web 两进程各自的信号取值);U2/U3/U4 一并探明。**只读**,证据落 `docs/probes/`。
61
+ - **G2 分流方案**:端口解析机制(归一函数 + 信号判定)+ 迁移语义 + Origin 白名单 + 镜像写回改动点;经一次**独立评审**(换人、读过相关代码)再实施。
62
+ - **G3 端口解析落地**:归一"解析有效端口"函数,desktop 进程监听 3912/3913、web 进程仍 3902/3903;index.js 无 desktop 特化分支(§4a 口径)。
63
+ - **G4 Origin 白名单 + 镜像写回**:desktop 新端口的镜像 baseURL 正确(3912/3913),Origin 门对新端口照常;`?probe=host-config` 在两实例各自全绿。
64
+ - **G5 共存端到端**:web 与 desktop **同跑**,各自持有各自桥(netstat 实证 3902/3903 与 3912/3913 分属两进程),零 EADDRINUSE;desktop 独立(关掉 web 后 desktop 的 Qoder/Trae 仍可用);桌面 Qoder 真实聊天出正文。
65
+ - **G6 回归**:离线套件全绿(含 `verify-desktop-acceptance`,如需为其补"分流端口"断言则同步);`dsh-ui-test/` 全绿、零真实写入对账;诊断卡在分流后不再出现"另一实例代管"(因不再借桥)。
66
+ - **G7 文档收尾**:wiki/AGENTS.md(守预算闸门)/CHANGELOG/STATE.md;端口分流语义写入设置卡 HelpNote 或 wiki;release 打 annotated tag 推送。
67
+
68
+ ## 边界(非目标)
69
+
70
+ - **不分 CodeBuddy 桥 3901**(主聊天入口;验证 Qoder/Trae 分流成立后再单独立项)。
71
+ - 不改 desktop patch 里用户手写块;不动 `core/`、`providers/` 上游事实层。
72
+ - 不做"配置真正按 profile 隔离"(那是更大的架构改动;本 goal 只做"端口按运行时宿主解析")。
73
+ - 不追 web 线任何行为变化——web 端口与默认值**完全不变**。
74
+
75
+ ## 裁判纪律(执行 agent 必须遵守)
76
+
77
+ - **勿凭记忆改**:宿主信号以 G1 实测为准,不猜;网关行为以 docs/rules/*.md 为准。
78
+ - **写入永不 reject**(踩坑 #33);**零真实写入**(回归 md5 对账)。
79
+ - **index.js 无 desktop 特化分支**(§4a 静态守卫延续,分流归一函数收口)。
80
+ - **真实探测红线**:单账号、1.5s+ 间隔、只读优先、证据落 docs/probes/。
81
+ - **遇阻升级而非伪造**:宿主信号判定不可靠就如实上报,不硬选。
82
+ - **分支纪律**:长期分支只有 main;release 当场打 annotated tag 推送;永不 rebase 已推送历史。
83
+
84
+ ## 验收标准
85
+
86
+ 1. **端口分流**:desktop 进程的 Qoder/Trae 网关监听 3912/3913,web 进程仍 3902/3903;`netstat` 实证两实例各自持有各自端口。
87
+ 2. **零借桥**:web 与 desktop 同跑零 EADDRINUSE;诊断卡 Qoder/Trae 行显示"运行中 127.0.0.1:391x"(desktop 侧),不再出现"另一实例代管"。
88
+ 3. **桌面独立**:关掉 web 实例后,desktop 的 Qoder/Trae 仍监听且真实聊天出正文。
89
+ 4. **Origin + 镜像**:desktop 新端口的镜像 baseURL 正确(`?probe=host-config` providerIds/baseURL 对平),Origin 门对新端口照常(陌生 Origin 403、白名单放行)。
90
+ 5. **零回归**:web 线端口与行为完全不变;离线套件 + `dsh-ui-test/` 全绿、零真实写入;index.js 无 desktop 特化分支(§4a 绿)。
91
+ 6. **文档四件套**更新到位,release 打 tag 推送。
@@ -0,0 +1,106 @@
1
+ # Goal:dsh-tap 适配 dsh 桌面版(desktop profile)
2
+
3
+ > 执行模式:**workflow 驱动的长任务 goal**。本文是 goal 的唯一真源——定义角色、意图、边界与产出契约;
4
+ > 执行由一个 dynamic-workflow 承载(阶段化子代理 + 确定性闸门),实现路径由执行子代理在边界内自主决定。
5
+ > goal 输入写法参照 GitHub 官方 agentic-workflows 范式(`githubnext/agentics` 的 `daily-repo-goals.md`):
6
+ > **角色定位 + 意图/为什么 + 分阶段意图(非逐行指令)+ 发现优先级准则 + 产出契约 + 边界**——把判断力留给模型。
7
+ > 必读裁判依据:`AGENTS.md`(全部踩坑)+ `docs/rules/*.md`(网关实测事实,勿凭记忆改)+ `host-config.js` 头注释(0.1.7 配置换代全案)。
8
+ > 进展记录:每完成一个 G 项,在 `docs/rules/STATE.md` 追加一段(沿用既有格式)。
9
+ > 状态:**G3–G6 已落地(2026-10-03 接入实施,见文末「实施实测」节);G7 文档收尾同日完成。**
10
+
11
+ ## 角色与使命(why)
12
+
13
+ 你是 dsh-tap 的**桌面版适配负责人**。仓库现状:插件只在 web profile(`:3090` 那套 Web UI)跑通并全量回归;本机已存在 desktop profile 但**没有安装 dsh-tap**。你的使命是让插件在桌面版里**装得上、看得见、用得了**,且 web 侧零回归。
14
+
15
+ 这不是一次机械执行——desktop 侧的启动方式、UI 壳形态、宿主基座版本**都是未知数**,需要你以探测先行、证据落盘的方式边测边定。仓库的裁判纪律(勿凭记忆改、写入永不 reject、零真实写入)在桌面侧同样生效。
16
+
17
+ ## 意图(要达成什么,而非怎么做)
18
+
19
+ 1. **装得上**:desktop profile 能装载 dsh-tap,且不破坏其现有手写块(Ark / agent-default-model / ui-settings-account 等,并存不接管)。
20
+ 2. **看得见**:设置卡在 desktop UI 壳内正常渲染与交互(4 区块手风琴全量可用)。
21
+ 3. **用得了**:三通道(CodeBuddy / Trae / Qoder)与多服务商在 desktop 实例真实可用。
22
+ 4. **零回归**:web 侧七个离线套件 + `dsh-ui-test/` 全绿;新增宿主差异全部收进 `host-config.js` 选路 / UI 候选兜底,index.js 无 desktop 特化分支。
23
+
24
+ ## 已验证事实(立项前实测,2026-10-03,出处标注)
25
+
26
+ | 事实 | 出处 |
27
+ |---|---|
28
+ | desktop profile 已存在:`~/.dsh/profiles/desktop/{package.json, cordis.patch.yml, cordis.yml, pnpm-workspace.yaml}`;bundles = `dsh-base` + `dsh-web-app` + `agent-team-profile`,**dependencies 为空、无 dsh-tap** | 本机文件系统 |
29
+ | desktop patch 已有用户手写块:Ark(volces, anthropic-messages, 7 模型)、`agent-default-model → deepseek-account/deepseek-flash`、ui-settings-account;**与 codebuddy 块零交集** | `desktop/cordis.patch.yml`(providers 键实测枚举 = 仅 `volces`) |
30
+ | ~~desktop 运行时 = `dsh-base@0.1.7-rc.2`(共享 `~/.dsh/profiles/node_modules/`,pnpm hoisted)~~ **已被 recon 推翻(2026-10-03)**:宿主子进程从 asar 跑 `dsh-base@0.2.0-rc.2`;`profiles/node_modules` 的 0.1.7-rc.2 属 web 侧。seam 同代性不能凭版本号外推,须活体验证——`?probe=host-config` 实测 `mode=forms`、`formsWritable=true`,同代成立 | recon(宿主进程探查)+ 活体 probe(2026-10-03) |
31
+ | 插件 bundle patch 静态钉选路由 + `insert` 入口,UI 双槽注册(`plugins.item` + 旧槽回退),由 `host-config.js` 按宿主能力选路 | `cordis.patch.yml` / `index.js` / `host-config.js` |
32
+ | npm 上的 `dsh@1.0.1` 是 2016 年同名无关包("A shell written in JavaScript"),与 deepseek 的 dsh 无关——**别被 dist-tag 误导** | npm registry 元数据(2026-10-03 查) |
33
+ | 本机 Node = v24.19.0(≥22 满足) | `node --version` |
34
+
35
+ ## 后续补记(2026-10-04):volces 路由补 `reasoningEfforts`(宿主「推理等级」入口)
36
+
37
+ 用户报「输入框里有些模型没有思考强度」——宿主 composer 模型菜单的「推理等级」**只由模型条目的 `reasoningEfforts` 决定**(pi-ai `resolveModelReasoning` → `reasoningInfo` → `reasoning.efforts[]`;完整投影链与判据见踩坑 #64)。desktop patch 的 volces 路由原有 7 个模型里只有 `deepseek-v4.1-flash`/`ark-code-latest` 声明了档位;2026-10-04 用 Ark `/api/plan/v1/messages` 逐模型实测后补齐其余 5 个:
38
+
39
+ | 模型 | 实测(baseline / enabled / disabled) | 补的声明 |
40
+ |---|---|---|
41
+ | `glm-5.3-flash`、`glm-5.3` | 思考默认开;`thinking:{type:enabled,budget_tokens}` 接受;**`thinking:{type:disabled}` 400 `InvalidParameter`**("thinking.type `disabled` is not supported by this model") | `low/medium/high/max`(**无 off**) |
42
+ | `kimi-k3`、`doubao-seed-evolving`、`doubao-seed-2.1-lite` | 思考默认开;`enabled` 接受;`disabled` 200 且 thinking 块为空(真关思考) | `off:null` + `low/medium/high/max` |
43
+
44
+ - **`off` 必须逐模型裁**:pi-ai 对 anthropic 方言的 off 线值就是发 `thinking:{type:disabled}`(`anthropic-messages.js:902`)——给拒 disabled 的模型声明 off 等于摆一个必然 400 的档位;`off` 键缺省时 `map.off` 为 null、不发 disabled,退化为"不带 thinking 参数"= 上游默认(照常思考),安全。
45
+ - **边界(未定论)**:Ark 侧档位映射 pi-ai 预算表(low 2048 / medium 8192 / high 16384 / max 夹到 high),而这些模型是**自适应思考**——2 采样/档位下多数看不到单调差异(`glm-5.3` 2048→1713 / 16384→2219 有;`glm-5.3-flash`、`kimi-k3`、`doubao-seed-2.1-lite` 无)⇒ 档位更像"上限"而非"强度旋钮";`disabled` 是硬效果。**多采样复证(2026-10-04,`probe-ark-thinking.mjs --levels-as-arms --repeat 3`,3 模型 ×5 臂 ×3 采样 = 45 次全 200,证据 `docs/probes/ark-thinking-1791097800341.json`)**:3/3 模型仍非单调记 INCONCLUSIVE(#42);**关键内部对照——high/max 两臂线上 budget 同为 16384(载荷全同),其差异即纯采样噪声,doubao-lite 上达 2.5 倍(68.3 vs 170.7)**:噪声量级 > 任何档位间差异,预算 ×8 思考量不增反平/降 ⇒ "档位 = budget 上限、非强度旋钮"口径成立(反向"恒无差异"断言同样证据不足);档位臂 max_tokens 用 32768(真实宿主 defaultMaxTokens),否则 budget>2048 会被钳死、实验失效。
46
+ - 备份 `cordis.patch.yml.pre-effort-20261004.bak`;生效 = **重启桌面应用**(profile patch 属启动期加载)。补齐后 volces 7/7 出档。
47
+ - **不必再手工做一遍(2026-10-04 固化)**:同一套三臂判据已固化成 `node scripts/probe-ark-thinking.mjs`——`--emit yaml` 打印可粘贴的 `reasoningEfforts` 块,`--write <patch.yml>` 直接写进 profile patch(YAML 文档级读-改-写、留 `.bak`),`--from <证据.json>` 复用既有证据不打上游。**Ark 新模型进选择器 = 跑这一条命令**;证据 `docs/probes/ark-thinking-*.json`(本次 7 模型结论与上表逐字一致)。
48
+ - **写入注意**:宿主镜像会重写这个 profile patch(实测 11:00 一次重写把 models 数组**内联注释**丢掉、**值保留**)——所以脚本写的是"值",别指望内联注释长存;顶层块注释会被保留。
49
+
50
+ ## 顶层未知数(探测先行,勿凭记忆动手)
51
+
52
+ | # | 未知数 | 决定什么 |
53
+ |---|---|---|
54
+ | U1 | desktop 怎么启动(命令/参数/端口);UI 是 Electron 原生壳还是浏览器开 web 套 | 联调与回归驱动方式 |
55
+ | U2 | desktop UI 壳是否消费 `plugins.item` 槽(Plugin Manager 卡片落点是否同 web) | 设置卡可见性与 UI 适配面 |
56
+ | U3 | 宿主基座版本是否完全等于 web 侧(seam 行为 / 图标导出 / UI 原语是否一致) | host-config 是否需新增选路分支 |
57
+ | U4 | 把 dsh-tap 接入 desktop 的正路(dependencies 加 `link:` + bundles 追加,还是另有机制) | 接入步骤与持久化 |
58
+ | U5 | 凭据/桥端口在 desktop 下是否与 web 冲突(`:3901/:3902/:3903`、共享 `~/.dsh/*-plugin-auth.json`) | 共存纪律 |
59
+
60
+ ## 产出契约(每个阶段必须交付什么)
61
+
62
+ - **G1 侦察报告**:回答 U1–U3;desktop 启动方式 + UI 壳形态 + 接触面子包逐包 diff 结论;证据落 `docs/probes/desktop-baseline-<日期>.json|md`。**只读**,不改任何文件。
63
+ - **G2 适配方案**:基于 G1 事实给出 U4/U5 的接入与共存方案,标注改动点与风险。方案须经一次**独立评审**(换人复审,读过相关代码)再实施。
64
+ - **G3 接入落地**:desktop profile 装载 dsh-tap,patch 落点正确,现有手写块完好。
65
+ - **G4 组合根适配**:`attach(ctx)` 与 `host-config.js` 在 desktop 正确选路;`?probe=host-config` 全绿。
66
+ - **G5 端到端**:三通道真实可用(CodeBuddy 桥聊天出正文为基线)。
67
+ - **G6 回归**:`npm run verify` + 七离线套件绿;`dsh-ui-test/` 按 desktop 壳形态适配后绿(零真实写入对账)。
68
+ - **G7 文档收尾**:wiki / AGENTS.md(守 ≤150 行/≤12KB 闸门)/ CHANGELOG / STATE.md 更新;release 打 annotated tag 推送。
69
+
70
+ ## 边界(非目标)
71
+
72
+ - 不改 desktop patch 里用户手写块(并存,不接管)。
73
+ - 不做 desktop 专属新功能(托盘、原生通知)——本 goal 只做适配。
74
+ - 不动 `core/`、`providers/` 上游事实层(除非 G5 实测发现 desktop 特有行为,且归位到适配层)。
75
+ - 不追 web 侧既有已知限制(旧槽无宿主实测等,见 settings-card-ux-redesign.md §0)。
76
+
77
+ ## 裁判纪律(执行子代理必须遵守)
78
+
79
+ - **勿凭记忆改**:网关行为以 `docs/rules/*.md` 为准;动手前 grep 对应踩坑编号。
80
+ - **写入永不 reject**(踩坑 #33):fire-and-forget 必须落地,失败记 `lastError`。
81
+ - **零真实写入**:回归跑前跑后 `~/.dsh/codebuddy-plugin.json` 哈希对账;真实网关探测遵守探测红线(1.5s+ 间隔、单账号、只读优先、证据落 `docs/probes/`)。
82
+ - **遇阻升级而非伪造**:闸门过不去、指令互相矛盾、或需要只有用户才知道的事实时,明确上报,不要绕过或编造通过。
83
+ - **分支纪律**:长期分支只有 `main`;`chore(release)` 当场打 annotated tag 并推送;**永不 rebase 已推送历史**(STATE.md「分支拓扑」)。
84
+
85
+ ## 验收标准
86
+
87
+ **可执行验收锚点**:`node scripts/verify-desktop-acceptance.mjs` 把下列标准逐条变成机器可判断言(CI 硬闸门)。A 组离线结构性不变量任何环境可跑;B 组桌面环境断言有 desktop profile 才跑;C 组活实例断言由探针/GUI 套件承担、脚本诚实标 SKIP 不伪造。
88
+
89
+ 1. desktop 实例 `?probe=host-config` 全绿,设置卡可见可用。
90
+ 2. 三通道 desktop 下真实可用(G5 口径),多服务商热加载生效。
91
+ 3. web 侧零回归:七离线套件 + `dsh-ui-test/` 全绿(含零真实写入对账)。
92
+ 4. 宿主差异全部收进 `host-config.js` 选路 / UI 候选兜底,index.js 无 desktop 特化分支。
93
+ 5. 文档四件套更新到位,release 打 tag 推送。
94
+
95
+ ## 实施实测(2026-10-03,G3–G6 接入落地,出处 = 当日活体命令与输出)
96
+
97
+ | G 项 | 结果 | 关键事实(全部当日实测) |
98
+ |---|---|---|
99
+ | G3 接入 | **落地** | desktop CLI(`resources/runtime/cli/bin/dsh.cmd`,ELECTRON_RUN_AS_NODE shim)`plugin --profile desktop add C:/Users/21613/dev/dsh-tap`:`dependencies.dsh-tap = link:…` 与 `dsh.profile.bundles` 追加**两落点均自动写好**(无需手工补);link 实落 `profiles/desktop/node_modules/dsh-tap`(symlink → 仓库,`realpathSync` 实证),非根 hoist |
100
+ | G4 活体 | **全绿** | 冷启动后 `?probe=host-config`:`mode=forms`、`formsWritable=true`、`applies=live`、`allNamespaces` 含 `llm-pi-ai`、`legacySettingsPath=C:\Users\21613\.dsh\settings.yaml`(**DSH_HOME 未漂移**)、`attachError=null`。0.2.0-rc.2 的 settings seam 仍是 configure/describe/mutate 形态 ⇒ **host-config.js 零改动**(预写分支=凭记忆改,未发生) |
101
+ | G4 排障 | **新发现** | 首启 `providerIds=[volces,qoder]`、`lastError=ERR: llm-pi-ai: provider "codebuddy" model "default" needs an api`——**bundle patch(仓库 cordis.patch.yml)的 codebuddy 块未合并进桌面组合树**,镜像 `syncModelsToDshSettings` 只 set `providers.codebuddy.models` 子路径 ⇒ 合并树中 codebuddy 路由无 `api` ⇒ 0.2.0-rc.2 的 llm-pi-ai 校验拒绝、mutate 回滚(qoder 整块带 api 所以过了)。修复 = 按 web 用户层同构先例**手放 codebuddy 完整块**到 desktop patch(装机步骤,见 pitfalls #54),重启后 `lastError=null`、`providerIds=[volces,qoder,codebuddy]` |
102
+ | G4 Origin 门 | **实测命中→兜底落地** | 带-Origin 的 GET(零写入,守卫对 GET/POST 一体设防):`Origin: dsh-app://app` → **403**(同源对照 200、无 Origin 200)。按方案风险 3 兜底级实施:index.js 通用 `localAllowedOrigins` 配置字段(默认空 = 行为不变,零 desktop 字样,过 §4a/§4b)+ `localGuardFailure`/`sameOrigin` 两门消费(精确匹配,Host 回环门不变);desktop 侧文件层写入 `["dsh-app://app"]` 后三连 = 200/200/陌生 Origin 403。**注意**:壳内是否真的透传 `dsh-app://app` Origin 未实测(需壳内页面发起)——若不透传则无 Origin 本就放行,allowlist 冗余但无害 |
103
+ | G5 端到端 | **两通道出正文** | CodeBuddy 桥(经 :3901,先占方为 web 实例进程)`glm-5.3-flash` 真实聊天 `content:"成功"` + `finish_reason:"stop"`;Qoder 网关(:3903)`qfmodel` 流式 reasoning 正文在途。Trae 按用户设置 `traeEnabled=false` 保持禁用,未测(不代开)。OAuth 壳内 `window.open` 行为未实测(当前 OAuth 已登录、无握手需求) |
104
+ | G6 回归 | **全绿** | 离线九套件(models/host-config 36/core-generic/rotation/providers/trae 89/qoder 154/desktop-acceptance **9 ok·0 FAIL**/agents-md 预算)+ `dsh-ui-test/`:card-accordion **200**、qoder-slot-check **13**、qoder-tab-phase2 **11** 全绿,`~/.dsh/codebuddy-plugin.json` md5 跑前跑后恒 `c5cff30c…`。UI 套件跑在 :3090(web 实例,`lib/client.js` 本轮未改) |
105
+
106
+ 共存实测:web 实例(`dsh web --port 3090`)与桌面实例并存,桥端口 3901/3903 由**先起方**持有(当日 web 先占),后起实例桥 EADDRINUSE 落 lastError 不炸、聊天路由到先占方桥(凭据同源功能等价)——与 G2 方案共存纪律 ② 预言一致。凭据/镜像文件全共享,`codebuddy-plugin.json` 全程只有一次预期内写入(`localAllowedOrigins` 字段,字段级 diff 归因)。三手写块(volces/agent-default-model/ui-settings-account)与 2026-10-01 注释逐行原样(diff 备份实证)。