dsh-multi-router 0.5.9 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +26 -1
- package/cordis.patch.yml +2 -2
- package/lib/accounts.js +4 -4
- package/lib/api-service.js +11 -0
- package/lib/api-service.js.map +7 -0
- package/lib/chunk-4V52V5GO.js +105 -0
- package/lib/chunk-4V52V5GO.js.map +7 -0
- package/lib/{chunk-S6ZQ45SS.js → chunk-JUOESKAK.js} +3 -3
- package/lib/{chunk-P43AWJ4Q.js → chunk-LLDJVBTQ.js} +3 -3
- package/lib/{chunk-U2MU2M5C.js → chunk-NSKCFVHP.js} +13 -111
- package/lib/chunk-NSKCFVHP.js.map +7 -0
- package/lib/{chunk-I4EW5TI7.js → chunk-OCMOMSB4.js} +46 -14
- package/lib/chunk-OCMOMSB4.js.map +7 -0
- package/lib/{chunk-FTM7RHQV.js → chunk-OK2T2UAZ.js} +4 -4
- package/lib/{chunk-J3XO7RTF.js → chunk-ROZINFTV.js} +3 -2
- package/lib/chunk-ROZINFTV.js.map +7 -0
- package/lib/chunk-SNEZMYNU.js +332 -0
- package/lib/chunk-SNEZMYNU.js.map +7 -0
- package/lib/{chunk-MCHV2R25.js → chunk-WVNY4LSL.js} +3 -1
- package/lib/{chunk-MCHV2R25.js.map → chunk-WVNY4LSL.js.map} +2 -2
- package/lib/cli.js +7 -6
- package/lib/cli.js.map +1 -1
- package/lib/client.js +340 -7
- package/lib/client.js.map +2 -2
- package/lib/clients.js +6 -5
- package/lib/{host-v0.5.9.js → host-v0.6.0.js} +18 -13
- package/lib/host.js +18 -13
- package/lib/index.js +18 -13
- package/lib/index.js.map +2 -2
- package/lib/manager.js +11 -7
- package/lib/router.js +2 -2
- package/lib/shim.js +3 -3
- package/package.json +1 -1
- package/lib/chunk-I4EW5TI7.js.map +0 -7
- package/lib/chunk-J3XO7RTF.js.map +0 -7
- package/lib/chunk-U2MU2M5C.js.map +0 -7
- /package/lib/{chunk-S6ZQ45SS.js.map → chunk-JUOESKAK.js.map} +0 -0
- /package/lib/{chunk-P43AWJ4Q.js.map → chunk-LLDJVBTQ.js.map} +0 -0
- /package/lib/{chunk-FTM7RHQV.js.map → chunk-OK2T2UAZ.js.map} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
本项目遵循 [语义化版本](https://semver.org/lang/zh-CN/)。版本号从 `0.1` 起以功能迭代为主,接口在 `1.0` 前可能变化。
|
|
4
4
|
|
|
5
|
+
## 0.6.0
|
|
6
|
+
|
|
7
|
+
- 新增左侧底部 Token 用量概览,展示今日与累计 Token,点击直达插件详情;默认显示,可在版本号旁关闭并保存到配置。仅读取本机缓存统计,每分钟更新,隐藏窗口暂停,不额外查询供应商。
|
|
8
|
+
|
|
9
|
+
- 新增默认关闭的内置 API 服务,提供 OpenAI 兼容的 `/v1/models` 与 `/v1/chat/completions`,支持 SSE / 普通 JSON、工具调用、推理参数及 usage;复用现有账号池、免费模型复核、额度和故障切换。
|
|
10
|
+
- 新增 API 面板:即时启停、端口、本机 / 网络访问、Base URL、独立服务 Key 生成 / 显示 / 复制 / 重置 / 撤销,以及路由开放范围选择。默认跟随展示路由,动态免费模型随目录更新,直接调用也必须满足开放范围。
|
|
11
|
+
- API 调用纳入 Token 明细,新增来源筛选和今日 API 汇总;不保存对话、工具参数、服务 Key 或调用客户端身份。所有 API 接口需要 Bearer Key,错误响应不泄露供应商凭证、账号 ID 或原始错误日志。
|
|
12
|
+
- 服务启用状态按设备保存;默认不监听端口。端口冲突显示可操作提示,关闭 / 撤销 / 卸载会取消 API 请求并释放端口。限制并发、请求与响应大小,调用中断或异常流不冒充完整 JSON 成功结果。
|
|
13
|
+
- 增加 API 集成回归测试,并纳入 Windows / Linux CI;迁移文件不导出本机 API Key 或自动开放网络监听。
|
|
14
|
+
|
|
5
15
|
## 0.5.9
|
|
6
16
|
|
|
7
17
|
- 本机账号导入按供应商区域与账号身份去重,同一 Trae 登录同时出现在 CN / SOLO 缓存时只保留较新的凭证;首次安装先比较已有账号与缓存,保留名称、权重、停用及移除选择,兼容旧版移除记录。
|
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
一个插件内置 WorkBuddy、Trae、Qoder 的认证、模型发现和聊天传输,提供三家的多账号池及集中路由。运行不依赖原来三个 DSH 插件;三家代码随安装包一起打包。基于 MIT 上游,固定版本见 `upstream-lock.json`,许可见 `THIRD_PARTY_NOTICES.md`。
|
|
8
8
|
|
|
9
|
-
版本:0.
|
|
9
|
+
版本:0.6.0。适配 DSH Desktop / Web 0.2.0-rc.2,Node.js ^22.19.0 或 >=24。
|
|
10
10
|
|
|
11
11
|
## 在 DSH 里管理
|
|
12
12
|
|
|
@@ -16,6 +16,7 @@
|
|
|
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
|
- **模型管理**:原始模型默认隐藏,只展示统一路由;提供所有渠道「全部展示」「全部隐藏(仅路由)」,作用于现有和以后发现的模型。可搜索、获取真实模型目录,修改显示名与单模型展示开关,每家独立保存。
|
|
21
22
|
- **路由规则**:Free 免费路由排在首位,显示各账号当前免费模型与目录检查时间,支持立即检查。列表显示路由名称、切换策略和目标;新建/编辑打开二级弹窗。「添加模型预配置」可逐个添加或补齐全部三家预配置,不覆盖已有同 ID 路由。模型可从下拉列表选择,候选 ID 和上下文长度放在高级选项中。
|
|
@@ -149,6 +150,30 @@ Qoder 的 `dfmodel` 在真实目录里显示为 DeepSeek-Flash,未声明具体
|
|
|
149
150
|
- 结果显示实际安装是否成功及是否需要重启。npm 镜像尚未同步、网络超时、版本不兼容会明确提示。GitHub 下载不会由 npm 镜像代替。
|
|
150
151
|
- 本地文件 / 开发链接标记为原方式更新。不同 DSH 配置之间相互独立,只操作当前配置。
|
|
151
152
|
|
|
153
|
+
## 侧栏用量概览
|
|
154
|
+
|
|
155
|
+
左侧底部默认显示今日与累计 Token,点击打开本插件详情。可在面板版本号旁取消「侧栏用量」,设置会持久保存。今日按北京时间统计;每分钟仅读取本机统计缓存,隐藏窗口暂停,不增加平台用量请求。未返回 usage 的调用不估算 Token,悬停可查看说明。
|
|
156
|
+
|
|
157
|
+
## API 服务(2API)
|
|
158
|
+
|
|
159
|
+
在插件面板打开 **API 服务** → **生成 API Key** → **启用 API 服务**。默认 Base URL 为 `http://127.0.0.1:8787/v1`,在其他工具中选择 OpenAI 兼容接入,填入地址与服务 Key。服务随 DSH 运行,启用状态会保存;关闭服务、停用插件或退出 DSH 后停止监听。更改端口 / 访问范围、关闭或撤销 Key 会中断正在处理的 API 请求。
|
|
160
|
+
|
|
161
|
+
- `GET /v1/models`:返回已开放路由。默认跟随展示设置(包含动态免费模型),也可单独勾选;不开放原始供应商模型或混合 Free 别名。聊天入口也检查开放范围,不能通过直接填写隐藏 ID 绕过。
|
|
162
|
+
- `POST /v1/chat/completions`:支持 `stream: true` 的 SSE 与省略 / 设置 `stream: false` 的普通 JSON。模型填写 API 页展示的调用 ID;支持 `messages`、工具调用、图片及推理参数的范围取决于所选模型和上游渠道,当前仅支持 `n: 1`。
|
|
163
|
+
- 推理等级沿用路由默认值,可用 `reasoning_effort` 覆盖。上下文由调用客户端提交;外部工具负责执行工具调用并回传结果,不自动读取 DSH 会话。此版本不提供 Responses、Embeddings 或浏览器跨站 CORS 接口。协议参考 [OpenAI Chat Completions](https://developers.openai.com/api/reference/resources/chat)。
|
|
164
|
+
- 所有接口均要求 `Authorization: Bearer <服务 Key>`。Key 可显示、复制、重置及撤销;重置后旧 Key 不能再发起请求。常规面板响应只包含掩码,不包含完整 Key;凭证文件使用私有权限保存。API 配置与 Key 按设备单独保存,不随配置迁移文件导出;迁移账号和路由后,在新设备重新启用即可。
|
|
165
|
+
- 默认仅监听本机。按需开启「允许局域网访问」后监听所有 IPv4 网卡,页面列出网卡地址;使用 HTTP,只用于可信网络。需要外网访问时自行配置 HTTPS 和访问限制,插件不会自动修改防火墙或端口映射。
|
|
166
|
+
- 每次 API 上游尝试均纳入现有统计与轮换额度,来源标注「API 服务」,可按今日 / 近 3 日 / 近 7 日或自定义日期筛选。不保存请求文本、工具参数、API Key 或客户端身份;API 请求的工具执行耗时由外部客户端掌握,此处只记录模型用时、TTFT 和 TPS。服务最多处理 8 个并发 API 请求,超出返回 429。
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
curl http://127.0.0.1:8787/v1/chat/completions \
|
|
170
|
+
-H 'Authorization: Bearer YOUR_API_KEY' \
|
|
171
|
+
-H 'Content-Type: application/json' \
|
|
172
|
+
-d '{"model":"deepseek-v4.1-flash","messages":[{"role":"user","content":"你好"}],"stream":true}'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+

|
|
176
|
+
|
|
152
177
|
## 安装
|
|
153
178
|
|
|
154
179
|
### 方式一:npm 安装(首选)
|
package/cordis.patch.yml
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
- insert:
|
|
2
|
-
- id: llm-multi-router-v2-0.
|
|
3
|
-
name: ./lib/host-v0.
|
|
2
|
+
- id: llm-multi-router-v2-0.6.0
|
|
3
|
+
name: ./lib/host-v0.6.0.js
|
package/lib/accounts.js
CHANGED
|
@@ -4,11 +4,11 @@ import {
|
|
|
4
4
|
localAccountKey,
|
|
5
5
|
normalizeLocalAccountKey,
|
|
6
6
|
readPortableCredential
|
|
7
|
-
} from "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-S5KMFAQM.js";
|
|
10
|
-
import "./chunk-MCHV2R25.js";
|
|
7
|
+
} from "./chunk-JUOESKAK.js";
|
|
8
|
+
import "./chunk-OK2T2UAZ.js";
|
|
11
9
|
import "./chunk-TEZ2FMEO.js";
|
|
10
|
+
import "./chunk-S5KMFAQM.js";
|
|
11
|
+
import "./chunk-WVNY4LSL.js";
|
|
12
12
|
export {
|
|
13
13
|
discoverLocalAccounts,
|
|
14
14
|
importAccount,
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// upstream/trae/src/sse.ts
|
|
2
|
+
var SseDecoder = class {
|
|
3
|
+
buffer = "";
|
|
4
|
+
event;
|
|
5
|
+
id;
|
|
6
|
+
retry;
|
|
7
|
+
data = [];
|
|
8
|
+
push(chunk) {
|
|
9
|
+
this.buffer += chunk;
|
|
10
|
+
const events = [];
|
|
11
|
+
while (true) {
|
|
12
|
+
const match = /\r?\n/.exec(this.buffer);
|
|
13
|
+
if (match === null || match.index === void 0) break;
|
|
14
|
+
const line = this.buffer.slice(0, match.index);
|
|
15
|
+
this.buffer = this.buffer.slice(match.index + match[0].length);
|
|
16
|
+
const emitted = this.consumeLine(line);
|
|
17
|
+
if (emitted !== void 0) events.push(emitted);
|
|
18
|
+
}
|
|
19
|
+
return events;
|
|
20
|
+
}
|
|
21
|
+
finish() {
|
|
22
|
+
const events = [];
|
|
23
|
+
if (this.buffer !== "") {
|
|
24
|
+
const emitted = this.consumeLine(this.buffer);
|
|
25
|
+
this.buffer = "";
|
|
26
|
+
if (emitted !== void 0) events.push(emitted);
|
|
27
|
+
}
|
|
28
|
+
const final = this.dispatch();
|
|
29
|
+
if (final !== void 0) events.push(final);
|
|
30
|
+
return events;
|
|
31
|
+
}
|
|
32
|
+
consumeLine(line) {
|
|
33
|
+
if (line === "") return this.dispatch();
|
|
34
|
+
if (line.startsWith(":")) return void 0;
|
|
35
|
+
const colon = line.indexOf(":");
|
|
36
|
+
const field = colon === -1 ? line : line.slice(0, colon);
|
|
37
|
+
let value = colon === -1 ? "" : line.slice(colon + 1);
|
|
38
|
+
if (value.startsWith(" ")) value = value.slice(1);
|
|
39
|
+
if (field === "event") this.event = value;
|
|
40
|
+
else if (field === "data") this.data.push(value);
|
|
41
|
+
else if (field === "id" && !value.includes("\0")) this.id = value;
|
|
42
|
+
else if (field === "retry" && /^\d+$/.test(value)) this.retry = Number(value);
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
dispatch() {
|
|
46
|
+
if (this.data.length === 0) {
|
|
47
|
+
this.event = void 0;
|
|
48
|
+
this.retry = void 0;
|
|
49
|
+
return void 0;
|
|
50
|
+
}
|
|
51
|
+
const result = {
|
|
52
|
+
...this.event === void 0 || this.event === "" ? {} : { event: this.event },
|
|
53
|
+
data: this.data.join("\n"),
|
|
54
|
+
...this.id === void 0 ? {} : { id: this.id },
|
|
55
|
+
...this.retry === void 0 ? {} : { retry: this.retry }
|
|
56
|
+
};
|
|
57
|
+
this.event = void 0;
|
|
58
|
+
this.retry = void 0;
|
|
59
|
+
this.data = [];
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
function decodeTraeEvent(event) {
|
|
64
|
+
if (event.data === "[DONE]") return { type: "done", finishReason: "stop" };
|
|
65
|
+
let payload;
|
|
66
|
+
try {
|
|
67
|
+
payload = JSON.parse(event.data);
|
|
68
|
+
} catch {
|
|
69
|
+
return { type: "unknown", ...event.event === void 0 ? {} : { event: event.event }, data: event.data };
|
|
70
|
+
}
|
|
71
|
+
const record = typeof payload === "object" && payload !== null && !Array.isArray(payload) ? payload : {};
|
|
72
|
+
if (event.event === "request_wait_in_queue") {
|
|
73
|
+
return { type: "queue", ...typeof record["position"] === "number" ? { position: record["position"] } : {} };
|
|
74
|
+
}
|
|
75
|
+
if (event.event === "progress_notice") return { type: "progress", notice: payload };
|
|
76
|
+
if (event.event === "token_usage") {
|
|
77
|
+
return {
|
|
78
|
+
type: "usage",
|
|
79
|
+
...typeof record["prompt_tokens"] === "number" ? { inputTokens: record["prompt_tokens"] } : {},
|
|
80
|
+
...typeof record["completion_tokens"] === "number" ? { outputTokens: record["completion_tokens"] } : {},
|
|
81
|
+
...typeof record["total_tokens"] === "number" ? { totalTokens: record["total_tokens"] } : {},
|
|
82
|
+
...typeof record["reasoning_tokens"] === "number" ? { reasoningTokens: record["reasoning_tokens"] } : {},
|
|
83
|
+
...typeof record["cache_read_input_tokens"] === "number" ? { cacheReadTokens: record["cache_read_input_tokens"] } : {},
|
|
84
|
+
...typeof record["cache_creation_input_tokens"] === "number" ? { cacheWriteTokens: record["cache_creation_input_tokens"] } : {}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (event.event === "done" || typeof record["finish_reason"] === "string" && record["response"] === void 0) {
|
|
88
|
+
return { type: "done", finishReason: typeof record["finish_reason"] === "string" ? record["finish_reason"] : "stop" };
|
|
89
|
+
}
|
|
90
|
+
if (event.event === "output" || record["response"] !== void 0 || record["reasoning_content"] !== void 0) {
|
|
91
|
+
return {
|
|
92
|
+
type: "delta",
|
|
93
|
+
text: typeof record["response"] === "string" ? record["response"] : "",
|
|
94
|
+
...typeof record["reasoning_content"] === "string" ? { reasoning: record["reasoning_content"] } : {},
|
|
95
|
+
...record["tool_calls"] === void 0 || record["tool_calls"] === null ? {} : { toolCalls: record["tool_calls"] }
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
return { type: "unknown", ...event.event === void 0 ? {} : { event: event.event }, data: payload };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export {
|
|
102
|
+
SseDecoder,
|
|
103
|
+
decodeTraeEvent
|
|
104
|
+
};
|
|
105
|
+
//# sourceMappingURL=chunk-4V52V5GO.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../upstream/trae/src/sse.ts"],
|
|
4
|
+
"sourcesContent": ["export interface SseEvent {\n event?: string\n data: string\n id?: string\n retry?: number\n}\n\n/** Incremental SSE decoder supporting CRLF, chunk splits and multi-line data. */\nexport class SseDecoder {\n private buffer = ''\n private event: string | undefined\n private id: string | undefined\n private retry: number | undefined\n private data: string[] = []\n\n push(chunk: string): SseEvent[] {\n this.buffer += chunk\n const events: SseEvent[] = []\n while (true) {\n const match = /\\r?\\n/.exec(this.buffer)\n if (match === null || match.index === undefined) break\n const line = this.buffer.slice(0, match.index)\n this.buffer = this.buffer.slice(match.index + match[0].length)\n const emitted = this.consumeLine(line)\n if (emitted !== undefined) events.push(emitted)\n }\n return events\n }\n\n finish(): SseEvent[] {\n const events: SseEvent[] = []\n if (this.buffer !== '') {\n const emitted = this.consumeLine(this.buffer)\n this.buffer = ''\n if (emitted !== undefined) events.push(emitted)\n }\n const final = this.dispatch()\n if (final !== undefined) events.push(final)\n return events\n }\n\n private consumeLine(line: string): SseEvent | undefined {\n if (line === '') return this.dispatch()\n if (line.startsWith(':')) return undefined\n const colon = line.indexOf(':')\n const field = colon === -1 ? line : line.slice(0, colon)\n let value = colon === -1 ? '' : line.slice(colon + 1)\n if (value.startsWith(' ')) value = value.slice(1)\n if (field === 'event') this.event = value\n else if (field === 'data') this.data.push(value)\n else if (field === 'id' && !value.includes('\\0')) this.id = value\n else if (field === 'retry' && /^\\d+$/.test(value)) this.retry = Number(value)\n return undefined\n }\n\n private dispatch(): SseEvent | undefined {\n if (this.data.length === 0) {\n this.event = undefined\n this.retry = undefined\n return undefined\n }\n const result: SseEvent = {\n ...this.event === undefined || this.event === '' ? {} : { event: this.event },\n data: this.data.join('\\n'),\n ...this.id === undefined ? {} : { id: this.id },\n ...this.retry === undefined ? {} : { retry: this.retry },\n }\n this.event = undefined\n this.retry = undefined\n this.data = []\n return result\n }\n}\n\nexport type TraeStreamEvent =\n | { type: 'queue'; position?: number }\n | { type: 'progress'; notice: unknown }\n | { type: 'delta'; text: string; reasoning?: string; toolCalls?: unknown }\n | {\n type: 'usage'\n inputTokens?: number\n outputTokens?: number\n totalTokens?: number\n reasoningTokens?: number\n /**\n * Trae's prompt-cache accounting (`cache_read_input_tokens` /\n * `cache_creation_input_tokens` on the `token_usage` event). Verified\n * 2026-09-22 (docs/ISSUE10_DIAGNOSIS.md): a byte-identical 9224-token\n * prompt reports `prompt_tokens: 9224` while `cache_read_input_tokens`\n * rises to 9216, so these are a *subset* of `prompt_tokens` \u2014 the OpenAI\n * convention, not Anthropic's exclusive one. Forwarding them as\n * `cached_tokens` is therefore arithmetically correct.\n */\n cacheReadTokens?: number\n cacheWriteTokens?: number\n }\n | { type: 'done'; finishReason: string }\n | { type: 'unknown'; event?: string; data: unknown }\n\nexport function decodeTraeEvent(event: SseEvent): TraeStreamEvent {\n if (event.data === '[DONE]') return { type: 'done', finishReason: 'stop' }\n let payload: unknown\n try { payload = JSON.parse(event.data) as unknown } catch { return { type: 'unknown', ...event.event === undefined ? {} : { event: event.event }, data: event.data } }\n const record = typeof payload === 'object' && payload !== null && !Array.isArray(payload) ? payload as Record<string, unknown> : {}\n if (event.event === 'request_wait_in_queue') {\n return { type: 'queue', ...typeof record['position'] === 'number' ? { position: record['position'] } : {} }\n }\n if (event.event === 'progress_notice') return { type: 'progress', notice: payload }\n if (event.event === 'token_usage') {\n return {\n type: 'usage',\n ...typeof record['prompt_tokens'] === 'number' ? { inputTokens: record['prompt_tokens'] } : {},\n ...typeof record['completion_tokens'] === 'number' ? { outputTokens: record['completion_tokens'] } : {},\n ...typeof record['total_tokens'] === 'number' ? { totalTokens: record['total_tokens'] } : {},\n ...typeof record['reasoning_tokens'] === 'number' ? { reasoningTokens: record['reasoning_tokens'] } : {},\n ...typeof record['cache_read_input_tokens'] === 'number' ? { cacheReadTokens: record['cache_read_input_tokens'] } : {},\n ...typeof record['cache_creation_input_tokens'] === 'number' ? { cacheWriteTokens: record['cache_creation_input_tokens'] } : {},\n }\n }\n if (event.event === 'done' || typeof record['finish_reason'] === 'string' && record['response'] === undefined) {\n return { type: 'done', finishReason: typeof record['finish_reason'] === 'string' ? record['finish_reason'] : 'stop' }\n }\n if (event.event === 'output' || record['response'] !== undefined || record['reasoning_content'] !== undefined) {\n return {\n type: 'delta',\n text: typeof record['response'] === 'string' ? record['response'] : '',\n ...typeof record['reasoning_content'] === 'string' ? { reasoning: record['reasoning_content'] } : {},\n ...record['tool_calls'] === undefined || record['tool_calls'] === null ? {} : { toolCalls: record['tool_calls'] },\n }\n }\n return { type: 'unknown', ...event.event === undefined ? {} : { event: event.event }, data: payload }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
atRestKeyProviderFor,
|
|
6
6
|
readTraeIdentity,
|
|
7
7
|
traeStorageCandidates
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-OK2T2UAZ.js";
|
|
9
9
|
import {
|
|
10
10
|
regionOfCredential
|
|
11
11
|
} from "./chunk-S5KMFAQM.js";
|
|
12
12
|
import {
|
|
13
13
|
PROVIDERS,
|
|
14
14
|
writePrivateJson
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-WVNY4LSL.js";
|
|
16
16
|
|
|
17
17
|
// src/accounts.mjs
|
|
18
18
|
import { readFile } from "node:fs/promises";
|
|
@@ -178,4 +178,4 @@ export {
|
|
|
178
178
|
readPortableCredential,
|
|
179
179
|
importAccount
|
|
180
180
|
};
|
|
181
|
-
//# sourceMappingURL=chunk-
|
|
181
|
+
//# sourceMappingURL=chunk-JUOESKAK.js.map
|
|
@@ -4,10 +4,10 @@ import {
|
|
|
4
4
|
} from "./chunk-DNQPZMPF.js";
|
|
5
5
|
import {
|
|
6
6
|
RouteError
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ROZINFTV.js";
|
|
8
8
|
import {
|
|
9
9
|
REASONING_EFFORTS
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WVNY4LSL.js";
|
|
11
11
|
|
|
12
12
|
// src/shim.mjs
|
|
13
13
|
import { createServer } from "node:http";
|
|
@@ -117,4 +117,4 @@ function createShim(router, { modelPrefix = "" } = {}) {
|
|
|
117
117
|
export {
|
|
118
118
|
createShim
|
|
119
119
|
};
|
|
120
|
-
//# sourceMappingURL=chunk-
|
|
120
|
+
//# sourceMappingURL=chunk-LLDJVBTQ.js.map
|
|
@@ -4,24 +4,28 @@ import {
|
|
|
4
4
|
WorkBuddyCredentialStore,
|
|
5
5
|
identityHeaders,
|
|
6
6
|
traeAccountId
|
|
7
|
-
} from "./chunk-
|
|
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
23
|
abortable
|
|
15
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-ROZINFTV.js";
|
|
16
25
|
import {
|
|
17
26
|
beijingDay,
|
|
18
27
|
writePrivateJson
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import {
|
|
21
|
-
WorkBuddyUpstreamClient,
|
|
22
|
-
modelWithCurrentPromotion,
|
|
23
|
-
prepareChatBody
|
|
24
|
-
} from "./chunk-TEZ2FMEO.js";
|
|
28
|
+
} from "./chunk-WVNY4LSL.js";
|
|
25
29
|
|
|
26
30
|
// src/clients.mjs
|
|
27
31
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
@@ -790,108 +794,6 @@ var TraeSoloRemoteCatalogClient = class {
|
|
|
790
794
|
|
|
791
795
|
// upstream/trae/src/solo-bridge.ts
|
|
792
796
|
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
797
|
var TRAE_ERROR_HINTS = {
|
|
896
798
|
1005: "Trae requires a paid plan for this model; the current account's plan does not cover it",
|
|
897
799
|
4001: "Trae does not serve this model under the SOLO function the request used (config_name rejected)",
|
|
@@ -5508,4 +5410,4 @@ export {
|
|
|
5508
5410
|
refreshWorkBuddyCheckinCredential,
|
|
5509
5411
|
createWorkBuddyCheckin
|
|
5510
5412
|
};
|
|
5511
|
-
//# sourceMappingURL=chunk-
|
|
5413
|
+
//# sourceMappingURL=chunk-NSKCFVHP.js.map
|