dsh-multi-router 0.5.9 → 0.6.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.
Files changed (42) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +46 -6
  3. package/THIRD_PARTY_NOTICES.md +4 -0
  4. package/cordis.patch.yml +2 -2
  5. package/lib/accounts.js +4 -4
  6. package/lib/api-service.js +11 -0
  7. package/lib/api-service.js.map +7 -0
  8. package/lib/{chunk-U2MU2M5C.js → chunk-2LH6TD2U.js} +25 -115
  9. package/lib/chunk-2LH6TD2U.js.map +7 -0
  10. package/lib/chunk-4V52V5GO.js +105 -0
  11. package/lib/chunk-4V52V5GO.js.map +7 -0
  12. package/lib/chunk-625KMEYS.js +332 -0
  13. package/lib/chunk-625KMEYS.js.map +7 -0
  14. package/lib/{chunk-P43AWJ4Q.js → chunk-BSAI3SW5.js} +3 -3
  15. package/lib/{chunk-J3XO7RTF.js → chunk-DZ4ZUAYH.js} +50 -6
  16. package/lib/chunk-DZ4ZUAYH.js.map +7 -0
  17. package/lib/{chunk-MCHV2R25.js → chunk-NGVWVIBM.js} +22 -6
  18. package/lib/chunk-NGVWVIBM.js.map +7 -0
  19. package/lib/{chunk-FTM7RHQV.js → chunk-OK2T2UAZ.js} +4 -4
  20. package/lib/{chunk-S6ZQ45SS.js → chunk-VZPXRK7Q.js} +3 -3
  21. package/lib/{chunk-I4EW5TI7.js → chunk-ZQZSXCVR.js} +164 -48
  22. package/lib/chunk-ZQZSXCVR.js.map +7 -0
  23. package/lib/cli.js +7 -6
  24. package/lib/cli.js.map +1 -1
  25. package/lib/client.js +462 -44
  26. package/lib/client.js.map +2 -2
  27. package/lib/clients.js +9 -5
  28. package/lib/{host-v0.5.9.js → host-v0.6.1.js} +19 -13
  29. package/lib/host.js +19 -13
  30. package/lib/index.js +19 -13
  31. package/lib/index.js.map +2 -2
  32. package/lib/manager.js +11 -7
  33. package/lib/router.js +2 -2
  34. package/lib/shim.js +3 -3
  35. package/package.json +1 -1
  36. package/lib/chunk-I4EW5TI7.js.map +0 -7
  37. package/lib/chunk-J3XO7RTF.js.map +0 -7
  38. package/lib/chunk-MCHV2R25.js.map +0 -7
  39. package/lib/chunk-U2MU2M5C.js.map +0 -7
  40. /package/lib/{chunk-P43AWJ4Q.js.map → chunk-BSAI3SW5.js.map} +0 -0
  41. /package/lib/{chunk-FTM7RHQV.js.map → chunk-OK2T2UAZ.js.map} +0 -0
  42. /package/lib/{chunk-S6ZQ45SS.js.map → chunk-VZPXRK7Q.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。版本号从 `0.1` 起以功能迭代为主,接口在 `1.0` 前可能变化。
4
4
 
5
+ ## 0.6.1
6
+
7
+ - 保留三家模型的默认 / 最大上下文和可选档位,原始模型、预制路由及动态免费模型默认最大,不再统一限制 200K;旧隐式默认自动迁移,显式自定义预算保留。
8
+ - 模型设置集中管理名称、上下文预算、图片开关和默认推理档位;免费模型逐项选择预算。原始模型与路由独立设置,随配置导入导出。
9
+ - 路由跳过容量不足的账号,不截断会话或静默降低容量;Qoder 每次请求使用能容纳预算的真实档位,并发选择不污染共享目录。
10
+ - 增加 Qwen3.8-Max、Qwen3.8-Flash 预配置,使用已核对的 Trae / Qoder 模型 ID;补齐预配置不覆盖已有路由。
11
+ - 增加 Hy4 Preview 预配置,精确绑定 WorkBuddy 的 `hy4-preview`;容量与推理模式跟随该渠道目录,支持多个 WorkBuddy 账号切换。
12
+ - 增加手动短请求连通性测试,有超时、间隔与错误流检查,不自动发送容量探测。显示最大输出与完整推理模式,只有声明支持的模型提供图片与关闭思考选项。
13
+ - 对比 dingminhua 的 WorkBuddy / Trae 插件并记录设计取舍,更新模型设置的合成数据截图。
14
+
15
+ ## 0.6.0
16
+
17
+ - 新增左侧底部 Token 用量概览,展示今日与累计 Token,点击直达插件详情;默认显示,可在版本号旁关闭并保存到配置。仅读取本机缓存统计,每分钟更新,隐藏窗口暂停,不额外查询供应商。
18
+
19
+ - 新增默认关闭的内置 API 服务,提供 OpenAI 兼容的 `/v1/models` 与 `/v1/chat/completions`,支持 SSE / 普通 JSON、工具调用、推理参数及 usage;复用现有账号池、免费模型复核、额度和故障切换。
20
+ - 新增 API 面板:即时启停、端口、本机 / 网络访问、Base URL、独立服务 Key 生成 / 显示 / 复制 / 重置 / 撤销,以及路由开放范围选择。默认跟随展示路由,动态免费模型随目录更新,直接调用也必须满足开放范围。
21
+ - API 调用纳入 Token 明细,新增来源筛选和今日 API 汇总;不保存对话、工具参数、服务 Key 或调用客户端身份。所有 API 接口需要 Bearer Key,错误响应不泄露供应商凭证、账号 ID 或原始错误日志。
22
+ - 服务启用状态按设备保存;默认不监听端口。端口冲突显示可操作提示,关闭 / 撤销 / 卸载会取消 API 请求并释放端口。限制并发、请求与响应大小,调用中断或异常流不冒充完整 JSON 成功结果。
23
+ - 增加 API 集成回归测试,并纳入 Windows / Linux CI;迁移文件不导出本机 API Key 或自动开放网络监听。
24
+
5
25
  ## 0.5.9
6
26
 
7
27
  - 本机账号导入按供应商区域与账号身份去重,同一 Trae 登录同时出现在 CN / SOLO 缓存时只保留较新的凭证;首次安装先比较已有账号与缓存,保留名称、权重、停用及移除选择,兼容旧版移除记录。
package/README.md CHANGED
@@ -6,19 +6,20 @@
6
6
 
7
7
  一个插件内置 WorkBuddy、Trae、Qoder 的认证、模型发现和聊天传输,提供三家的多账号池及集中路由。运行不依赖原来三个 DSH 插件;三家代码随安装包一起打包。基于 MIT 上游,固定版本见 `upstream-lock.json`,许可见 `THIRD_PARTY_NOTICES.md`。
8
8
 
9
- 版本:0.5.9。适配 DSH Desktop / Web 0.2.0-rc.2,Node.js ^22.19.0 或 >=24。
9
+ 版本:0.6.1。适配 DSH Desktop / Web 0.2.0-rc.2,Node.js ^22.19.0 或 >=24。
10
10
 
11
11
  ## 在 DSH 里管理
12
12
 
13
- 打开 **插件 → dsh-multi-router 的配置页**。默认进入总览,八个页签:
13
+ 打开 **插件 → dsh-multi-router 的配置页**。默认进入总览,九个页签:
14
14
 
15
15
  - **总览与用量**:今日/累计请求与 Token、近 7 日趋势、最近请求、三家平台余额与刷新时间。平台余额后台每 5 分钟查询,面板每分钟读取本机缓存,隐藏页面暂停轮询,可关闭自动刷新;手动刷新平台用量会立即查询。
16
16
  - **Token 明细**:每次上游调用的时间、渠道、账号、路由、实际模型、输入/输出/总 Token 和结果;支持今日、近 3 日、近 7 日、近 30 日及自定义日期范围(北京时间自然日),并按账号、路由、结果筛选,每页 50 条。缓存输入和推理输出在平台返回时展示,不重复计入总量。默认滚动保留最近 30 × 24 小时,可设置 1–365 天,并随配置迁移。同时展示模型用时、工具调用用时、首 Token 平均(TTFT)和输出速度(TPS),可展开单次性能。DSH 步骤采用会话统计相同口径;TPS 按有效输出 Token / 解码秒数加权计算。性能汇总只包含成功调用,随当前筛选变化;旧记录缺少的分项显示「—」。
17
17
  - **账号与登录**:默认「全部供应商」集中展示所有账号,可按供应商 / 区域筛选、搜索、全选 / 全不选。启动时自动读取本机 WorkBuddy / Trae 已登录账号,每分钟重新检测;Trae 自动识别 CN / Global / SOLO,面板展示检测状态,并提供「重新检测本机登录」。添加账号弹窗也可一键获取;账号 ID 自动生成、显示名自动识别,重复账号会提示。Qoder 使用 PAT,可粘贴或获取本机旧连接器已保存的 PAT。新账号自动获取模型与平台用量。详情弹窗查看身份、认证类型、有效期、刷新能力、套餐与积分包;账号可命名、启停、排序和移出。
18
18
  - **积分签到**:按账号设置每日启动签到或定时签到(北京时间),保留每日执行记录、领取意图与设备限制,避免重复请求。
19
+ - **API 服务**:默认关闭,按需提供 OpenAI 兼容的模型列表和聊天接口,支持流式 / 普通 JSON、工具调用与推理参数;复用现有账号池及路由,Key 独立管理,API 用量可在 Token 明细按来源筛选。
19
20
  - **插件更新**:仅检查用户安装的 GitHub / npm 插件,包含停用插件;每 24 小时自动检查,在 DSH 任意页面弹窗提醒新版本。同一更新点击关闭或「稍后处理」后不重复提醒,更高版本 / 新提交再次提醒。可在弹窗查看并手动更新;不自动安装。检查失败不冒充发现新版本,内置组件不检查、不展示。
20
- - **模型管理**:原始模型默认隐藏,只展示统一路由;提供所有渠道「全部展示」「全部隐藏(仅路由)」,作用于现有和以后发现的模型。可搜索、获取真实模型目录,修改显示名与单模型展示开关,每家独立保存。
21
- - **路由规则**:Free 免费路由排在首位,显示各账号当前免费模型与目录检查时间,支持立即检查。列表显示路由名称、切换策略和目标;新建/编辑打开二级弹窗。「添加模型预配置」可逐个添加或补齐全部三家预配置,不覆盖已有同 ID 路由。模型可从下拉列表选择,候选 ID 和上下文长度放在高级选项中。
21
+ - **模型管理**:原始模型默认隐藏,只展示统一路由;提供所有渠道「全部展示」「全部隐藏(仅路由)」,作用于现有和以后发现的模型。可搜索、获取真实模型目录,修改显示名与单模型展示开关,每家独立保存。显示实际上下文、最大上下文、输出上限和完整推理档位;「设置」可调整上下文预算、图片输入及默认推理等级,「测试」手动发送短请求检查连通性(正常计费,不代表满上下文测试)。
22
+ - **路由规则**:Free 免费路由排在首位,显示各账号当前免费模型与目录检查时间,支持立即检查。列表显示路由名称、切换策略和目标;新建/编辑打开二级弹窗。「添加模型预配置」可逐个添加或补齐全部预配置(Qwen3.8-Max / Flash 连接已核对的 Trae、Qoder 渠道),不覆盖已有同 ID 路由。模型可从下拉列表选择,上下文默认采用目标渠道已发现的最大容量,支持手动设置较小预算;候选 ID 放在高级选项中。
22
23
 
23
24
  - **配置迁移**:导入 / 导出设置,或使用密码加密迁移账号登录凭证。
24
25
 
@@ -30,8 +31,20 @@
30
31
 
31
32
  隐藏只影响模型选择器,已有会话及路由仍可使用隐藏模型;停用账号会将其从新请求的候选池中排除。移出账号池保留独立凭证文件,且禁止移除仍被路由明确绑定的账号。
32
33
 
34
+ ### 上下文设置
35
+
36
+ 原始模型、预制路由及动态免费模型默认采用各渠道已声明的最大上下文,保留手动调低预算的选择。原始模型在「模型管理 → 设置」调整;普通路由在「编辑路由 → 上下文容量」调整;免费模型在「管理免费模型」逐项调整。旧版隐式 200K 默认会迁移为最大容量,显式自定义预算保留。
37
+
38
+ 路由只切换到能够容纳当前预算的渠道,不截断历史、不静默降低容量。Qoder 请求同步选择真实的上下文档位,且不同并发路由互不影响。最大窗口来自渠道目录,账号额度、限流或请求体限制仍可能影响实际可用长度;短请求测试不验证满窗口。
39
+
40
+ 原始模型设置和路由预算独立保存。上下文、图片、默认推理及免费模型设置均随配置迁移。
41
+
42
+ 两个参考插件的源码对比与本次处理方式见 [参考对比](docs/reference-comparison.md)。
43
+
33
44
  ### 界面预览
34
45
 
46
+ ![模型上下文和能力设置(v0.6.1,合成数据,无真实账号)](https://raw.githubusercontent.com/AndroidSix/dsh-multi-router/main/docs/screenshots/model-context.jpg)
47
+
35
48
  以下主要页面已更新为 **v0.5.9 实际面板 + 合成演示数据**。账号名称已替换,不包含真实手机号、邮箱、身份 ID、设备标识、登录凭证或会话内容;余额、用量和性能均为演示数值。
36
49
 
37
50
  | 总览与用量 | Token 明细与调用性能 |
@@ -149,6 +162,30 @@ Qoder 的 `dfmodel` 在真实目录里显示为 DeepSeek-Flash,未声明具体
149
162
  - 结果显示实际安装是否成功及是否需要重启。npm 镜像尚未同步、网络超时、版本不兼容会明确提示。GitHub 下载不会由 npm 镜像代替。
150
163
  - 本地文件 / 开发链接标记为原方式更新。不同 DSH 配置之间相互独立,只操作当前配置。
151
164
 
165
+ ## 侧栏用量概览
166
+
167
+ 左侧底部默认显示今日与累计 Token,点击打开本插件详情。可在面板版本号旁取消「侧栏用量」,设置会持久保存。今日按北京时间统计;每分钟仅读取本机统计缓存,隐藏窗口暂停,不增加平台用量请求。未返回 usage 的调用不估算 Token,悬停可查看说明。
168
+
169
+ ## API 服务(2API)
170
+
171
+ 在插件面板打开 **API 服务** → **生成 API Key** → **启用 API 服务**。默认 Base URL 为 `http://127.0.0.1:8787/v1`,在其他工具中选择 OpenAI 兼容接入,填入地址与服务 Key。服务随 DSH 运行,启用状态会保存;关闭服务、停用插件或退出 DSH 后停止监听。更改端口 / 访问范围、关闭或撤销 Key 会中断正在处理的 API 请求。
172
+
173
+ - `GET /v1/models`:返回已开放路由。默认跟随展示设置(包含动态免费模型),也可单独勾选;不开放原始供应商模型或混合 Free 别名。聊天入口也检查开放范围,不能通过直接填写隐藏 ID 绕过。
174
+ - `POST /v1/chat/completions`:支持 `stream: true` 的 SSE 与省略 / 设置 `stream: false` 的普通 JSON。模型填写 API 页展示的调用 ID;支持 `messages`、工具调用、图片及推理参数的范围取决于所选模型和上游渠道,当前仅支持 `n: 1`。
175
+ - 推理等级沿用路由默认值,可用 `reasoning_effort` 覆盖。上下文由调用客户端提交;外部工具负责执行工具调用并回传结果,不自动读取 DSH 会话。此版本不提供 Responses、Embeddings 或浏览器跨站 CORS 接口。协议参考 [OpenAI Chat Completions](https://developers.openai.com/api/reference/resources/chat)。
176
+ - 所有接口均要求 `Authorization: Bearer <服务 Key>`。Key 可显示、复制、重置及撤销;重置后旧 Key 不能再发起请求。常规面板响应只包含掩码,不包含完整 Key;凭证文件使用私有权限保存。API 配置与 Key 按设备单独保存,不随配置迁移文件导出;迁移账号和路由后,在新设备重新启用即可。
177
+ - 默认仅监听本机。按需开启「允许局域网访问」后监听所有 IPv4 网卡,页面列出网卡地址;使用 HTTP,只用于可信网络。需要外网访问时自行配置 HTTPS 和访问限制,插件不会自动修改防火墙或端口映射。
178
+ - 每次 API 上游尝试均纳入现有统计与轮换额度,来源标注「API 服务」,可按今日 / 近 3 日 / 近 7 日或自定义日期筛选。不保存请求文本、工具参数、API Key 或客户端身份;API 请求的工具执行耗时由外部客户端掌握,此处只记录模型用时、TTFT 和 TPS。服务最多处理 8 个并发 API 请求,超出返回 429。
179
+
180
+ ```bash
181
+ curl http://127.0.0.1:8787/v1/chat/completions \
182
+ -H 'Authorization: Bearer YOUR_API_KEY' \
183
+ -H 'Content-Type: application/json' \
184
+ -d '{"model":"deepseek-v4.1-flash","messages":[{"role":"user","content":"你好"}],"stream":true}'
185
+ ```
186
+
187
+ ![API 服务(合成数据,未启用)](https://raw.githubusercontent.com/AndroidSix/dsh-multi-router/main/docs/screenshots/api-service.jpg)
188
+
152
189
  ## 安装
153
190
 
154
191
  ### 方式一:npm 安装(首选)
@@ -275,9 +312,9 @@ node lib/cli.js remove --id wb1
275
312
 
276
313
  `modelVisibility` 按供应商保存新发现模型的展示默认值,省略时为 false。单模型 `visible` 优先;批量操作同时更新渠道默认值和已有单模型覆盖项,保留模型名称和路由配置。完整配置导入 / 导出也保留该默认值。
277
314
 
278
- ## 三家模型预配置(0.3.5)
315
+ ## 模型预配置
279
316
 
280
- 新增 Free 自动免费路由,并保留以下七种国内渠道共有模型路由。每条默认 WorkBuddy → Trae → Qoder,使用该渠道全部启用账号,临期优先开启,200K 上下文 / 32K 最大输出。Flash 仍采用用户已允许的三家 Flash 兼容切换;其他预配置精确绑定对应版本,不混用 GLM FlashX 等变体。目录或账号权限变化可能使目标暂不可用,预配置弹窗显示当前已发现可用渠道数。
317
+ Free 自动免费路由排在首位,以下普通预配置按表中渠道顺序切换,使用该渠道全部启用账号,默认临期优先、目录声明的最大上下文 / 32K 最大输出。Flash 仍采用用户已允许的三家 Flash 兼容切换;其他预配置精确绑定对应版本,不混用 GLM FlashX 等变体。空白渠道不参与该路由。目录或账号权限变化可能使目标暂不可用,预配置弹窗显示当前已发现可用渠道数。
281
318
 
282
319
  | 路由调用 ID | WorkBuddy 目标 ID | Trae 目标 ID | Qoder 目标 ID |
283
320
  | --- | --- | --- | --- |
@@ -288,6 +325,9 @@ node lib/cli.js remove --id wb1
288
325
  | kimi-k3 | kimi-k3-1 | kimi-k3 | kmodel_latest |
289
326
  | kimi-k2.8-preview | kimi-k2.8-preview | kimi-k2.8-preview | kmodel |
290
327
  | minimax-m2.7 | minimax-m2.7 | minimax-m2.7 | mmodel |
328
+ | qwen3.8-max | — | qwen3.8-max | qmodel_38max |
329
+ | qwen3.8-flash | — | qwen3.8-flash | qfmodel |
330
+ | hy4-preview | hy4-preview | — | — |
291
331
 
292
332
  路由内部 ID 是 DSH 查找路由所需的标识,由插件维护;用户在面板只配置路由名称。目标模型 ID 决定实际调用哪个模型。上表为预配置的稳定内部标识,新建路由自动生成独立标识。GLM-5.2 已移出预配置,原始渠道模型不受影响。
293
333
 
@@ -11,6 +11,10 @@
11
11
  - 使用或再分发本项目时,你必须**同时**遵守本项目 [`LICENSE`](./LICENSE) 与下列三个上游项目的 MIT 许可要求。
12
12
  - 上游项目的维护、更新与可用性不由本项目负责。
13
13
 
14
+ ## 设计参考(未包含代码)
15
+
16
+ 模型管理交互参考 [dingminhua/dsh-connect-workbuddy](https://github.com/dingminhua/dsh-connect-workbuddy) 与 [dingminhua/dsh-connect-trae](https://github.com/dingminhua/dsh-connect-trae) 的上下文预算、能力展示和测试反馈设计。本次管理界面与上下文路由逻辑由本项目独立实现,未复制这两个参考项目的新源码;核对的 commit 和差异见 [参考对比](docs/reference-comparison.md)。内置的 Trae 固定版本及其许可仍按下文履行。
17
+
14
18
  ## 本地集成改动 / Local Integration Changes
15
19
 
16
20
  - WorkBuddy 的共享适配器额外透传集成后 provider 目录中**显式声明**的 Minimal 推理模式;WorkBuddy 原有的模型发现逻辑与 provider 专有的档位词表未作改动。
package/cordis.patch.yml CHANGED
@@ -1,3 +1,3 @@
1
1
  - insert:
2
- - id: llm-multi-router-v2-0.5.9
3
- name: ./lib/host-v0.5.9.js
2
+ - id: llm-multi-router-v2-0.6.1
3
+ name: ./lib/host-v0.6.1.js
package/lib/accounts.js CHANGED
@@ -4,11 +4,11 @@ import {
4
4
  localAccountKey,
5
5
  normalizeLocalAccountKey,
6
6
  readPortableCredential
7
- } from "./chunk-S6ZQ45SS.js";
8
- import "./chunk-FTM7RHQV.js";
9
- import "./chunk-S5KMFAQM.js";
10
- import "./chunk-MCHV2R25.js";
7
+ } from "./chunk-VZPXRK7Q.js";
8
+ import "./chunk-OK2T2UAZ.js";
11
9
  import "./chunk-TEZ2FMEO.js";
10
+ import "./chunk-S5KMFAQM.js";
11
+ import "./chunk-NGVWVIBM.js";
12
12
  export {
13
13
  discoverLocalAccounts,
14
14
  importAccount,
@@ -0,0 +1,11 @@
1
+ import {
2
+ ApiService
3
+ } from "./chunk-625KMEYS.js";
4
+ import "./chunk-4V52V5GO.js";
5
+ import "./chunk-DNQPZMPF.js";
6
+ import "./chunk-DZ4ZUAYH.js";
7
+ import "./chunk-NGVWVIBM.js";
8
+ export {
9
+ ApiService
10
+ };
11
+ //# sourceMappingURL=api-service.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -4,24 +4,29 @@ import {
4
4
  WorkBuddyCredentialStore,
5
5
  identityHeaders,
6
6
  traeAccountId
7
- } from "./chunk-FTM7RHQV.js";
7
+ } from "./chunk-OK2T2UAZ.js";
8
+ import {
9
+ WorkBuddyUpstreamClient,
10
+ modelWithCurrentPromotion,
11
+ prepareChatBody
12
+ } from "./chunk-TEZ2FMEO.js";
8
13
  import {
9
14
  REGION_GATEWAYS,
10
15
  regionOfCredential
11
16
  } from "./chunk-S5KMFAQM.js";
17
+ import {
18
+ SseDecoder,
19
+ decodeTraeEvent
20
+ } from "./chunk-4V52V5GO.js";
12
21
  import {
13
22
  RouteError,
14
- abortable
15
- } from "./chunk-J3XO7RTF.js";
23
+ abortable,
24
+ qoderContextModel
25
+ } from "./chunk-DZ4ZUAYH.js";
16
26
  import {
17
27
  beijingDay,
18
28
  writePrivateJson
19
- } from "./chunk-MCHV2R25.js";
20
- import {
21
- WorkBuddyUpstreamClient,
22
- modelWithCurrentPromotion,
23
- prepareChatBody
24
- } from "./chunk-TEZ2FMEO.js";
29
+ } from "./chunk-NGVWVIBM.js";
25
30
 
26
31
  // src/clients.mjs
27
32
  import { readFile as readFile2 } from "node:fs/promises";
@@ -790,108 +795,6 @@ var TraeSoloRemoteCatalogClient = class {
790
795
 
791
796
  // upstream/trae/src/solo-bridge.ts
792
797
  import { randomUUID as randomUUID2 } from "node:crypto";
793
-
794
- // upstream/trae/src/sse.ts
795
- var SseDecoder = class {
796
- buffer = "";
797
- event;
798
- id;
799
- retry;
800
- data = [];
801
- push(chunk) {
802
- this.buffer += chunk;
803
- const events = [];
804
- while (true) {
805
- const match = /\r?\n/.exec(this.buffer);
806
- if (match === null || match.index === void 0) break;
807
- const line = this.buffer.slice(0, match.index);
808
- this.buffer = this.buffer.slice(match.index + match[0].length);
809
- const emitted = this.consumeLine(line);
810
- if (emitted !== void 0) events.push(emitted);
811
- }
812
- return events;
813
- }
814
- finish() {
815
- const events = [];
816
- if (this.buffer !== "") {
817
- const emitted = this.consumeLine(this.buffer);
818
- this.buffer = "";
819
- if (emitted !== void 0) events.push(emitted);
820
- }
821
- const final = this.dispatch();
822
- if (final !== void 0) events.push(final);
823
- return events;
824
- }
825
- consumeLine(line) {
826
- if (line === "") return this.dispatch();
827
- if (line.startsWith(":")) return void 0;
828
- const colon = line.indexOf(":");
829
- const field = colon === -1 ? line : line.slice(0, colon);
830
- let value = colon === -1 ? "" : line.slice(colon + 1);
831
- if (value.startsWith(" ")) value = value.slice(1);
832
- if (field === "event") this.event = value;
833
- else if (field === "data") this.data.push(value);
834
- else if (field === "id" && !value.includes("\0")) this.id = value;
835
- else if (field === "retry" && /^\d+$/.test(value)) this.retry = Number(value);
836
- return void 0;
837
- }
838
- dispatch() {
839
- if (this.data.length === 0) {
840
- this.event = void 0;
841
- this.retry = void 0;
842
- return void 0;
843
- }
844
- const result = {
845
- ...this.event === void 0 || this.event === "" ? {} : { event: this.event },
846
- data: this.data.join("\n"),
847
- ...this.id === void 0 ? {} : { id: this.id },
848
- ...this.retry === void 0 ? {} : { retry: this.retry }
849
- };
850
- this.event = void 0;
851
- this.retry = void 0;
852
- this.data = [];
853
- return result;
854
- }
855
- };
856
- function decodeTraeEvent(event) {
857
- if (event.data === "[DONE]") return { type: "done", finishReason: "stop" };
858
- let payload;
859
- try {
860
- payload = JSON.parse(event.data);
861
- } catch {
862
- return { type: "unknown", ...event.event === void 0 ? {} : { event: event.event }, data: event.data };
863
- }
864
- const record2 = typeof payload === "object" && payload !== null && !Array.isArray(payload) ? payload : {};
865
- if (event.event === "request_wait_in_queue") {
866
- return { type: "queue", ...typeof record2["position"] === "number" ? { position: record2["position"] } : {} };
867
- }
868
- if (event.event === "progress_notice") return { type: "progress", notice: payload };
869
- if (event.event === "token_usage") {
870
- return {
871
- type: "usage",
872
- ...typeof record2["prompt_tokens"] === "number" ? { inputTokens: record2["prompt_tokens"] } : {},
873
- ...typeof record2["completion_tokens"] === "number" ? { outputTokens: record2["completion_tokens"] } : {},
874
- ...typeof record2["total_tokens"] === "number" ? { totalTokens: record2["total_tokens"] } : {},
875
- ...typeof record2["reasoning_tokens"] === "number" ? { reasoningTokens: record2["reasoning_tokens"] } : {},
876
- ...typeof record2["cache_read_input_tokens"] === "number" ? { cacheReadTokens: record2["cache_read_input_tokens"] } : {},
877
- ...typeof record2["cache_creation_input_tokens"] === "number" ? { cacheWriteTokens: record2["cache_creation_input_tokens"] } : {}
878
- };
879
- }
880
- if (event.event === "done" || typeof record2["finish_reason"] === "string" && record2["response"] === void 0) {
881
- return { type: "done", finishReason: typeof record2["finish_reason"] === "string" ? record2["finish_reason"] : "stop" };
882
- }
883
- if (event.event === "output" || record2["response"] !== void 0 || record2["reasoning_content"] !== void 0) {
884
- return {
885
- type: "delta",
886
- text: typeof record2["response"] === "string" ? record2["response"] : "",
887
- ...typeof record2["reasoning_content"] === "string" ? { reasoning: record2["reasoning_content"] } : {},
888
- ...record2["tool_calls"] === void 0 || record2["tool_calls"] === null ? {} : { toolCalls: record2["tool_calls"] }
889
- };
890
- }
891
- return { type: "unknown", ...event.event === void 0 ? {} : { event: event.event }, data: payload };
892
- }
893
-
894
- // upstream/trae/src/solo-bridge.ts
895
798
  var TRAE_ERROR_HINTS = {
896
799
  1005: "Trae requires a paid plan for this model; the current account's plan does not cover it",
897
800
  4001: "Trae does not serve this model under the SOLO function the request used (config_name rejected)",
@@ -5319,14 +5222,21 @@ async function createAccountClient(account, config, attachments) {
5319
5222
  };
5320
5223
  };
5321
5224
  discover = (signal) => client.fetchModels(signal);
5322
- chat = (input, signal) => client.chatStream(JSON.stringify(input), signal);
5225
+ chat = (input, signal, options) => new QoderUpstreamClient({
5226
+ region,
5227
+ providerId: account.provider,
5228
+ getPat,
5229
+ transport,
5230
+ ...attachments ? { attachments } : {},
5231
+ catalogProvider: (id) => qoderContextModel(client.catalogModelFor(id), options?.contextWindow)
5232
+ }).chatStream(JSON.stringify(input), signal);
5323
5233
  }
5324
5234
  return {
5325
5235
  models: cachedModels(discover, config.catalogTtlMs),
5326
5236
  accountInfo,
5327
5237
  checkin,
5328
- async chat(input, signal) {
5329
- const result = await chat(input, signal);
5238
+ async chat(input, signal, options) {
5239
+ const result = await chat(input, signal, options);
5330
5240
  return result.ok ? preflightStream(result.response, signal) : result;
5331
5241
  }
5332
5242
  };
@@ -5508,4 +5418,4 @@ export {
5508
5418
  refreshWorkBuddyCheckinCredential,
5509
5419
  createWorkBuddyCheckin
5510
5420
  };
5511
- //# sourceMappingURL=chunk-U2MU2M5C.js.map
5421
+ //# sourceMappingURL=chunk-2LH6TD2U.js.map