dsh-connect-trae 1.0.0 → 1.1.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 +39 -0
- package/README.en.md +26 -6
- package/README.md +12 -9
- package/cordis.patch.yml +1 -1
- package/docs/assets/dsh-connect-trae-usage-card.png +0 -0
- package/lib/client.js +92 -54
- package/lib/index.d.ts +121 -62
- package/lib/index.js +310 -510
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.1.0 (2026-08-30)
|
|
4
|
+
|
|
5
|
+
### Fixes
|
|
6
|
+
|
|
7
|
+
- 保持 `llm_utils_chat` / `solo_work_lite` 为模型调用主路径,继续保留 Trae 原生结构化 `tool_calls`,避免模型无法调用 DSH 本地 `read` / `write` / `bash` 工具。
|
|
8
|
+
- 删除只提取最终文本、无法返回 DSH `tool_calls` 的 `TraeSoloRemoteBridge` 及 Remote 会话调用逻辑;保留独立、只读的 `TraeSoloRemoteCatalogClient` 用于刷新完整模型能力目录,类型上不提供聊天方法,防止再次误接为模型调用主路径。
|
|
9
|
+
- 收紧 SOLO 请求为实证字段 allowlist,过滤会触发 `param is invalid` 的 OpenAI 可选字段;推理档位完成 DSH canonical → Trae wire 转换。
|
|
10
|
+
- 修复 `get_detail_param` 解析器字段名:上下文窗口改读 `model_detail_list[].prompt_max_tokens`(回退 `context_window_tokens.dev`)、最大输出改读 `model_detail_list[].max_tokens`。原代码读不存在的 `max_input_tokens` / `max_output_tokens`,导致每个模型的 contextWindow / maxTokens 恒为 undefined。
|
|
11
|
+
- 模型发现合并时剔除「Remote 目录有、但 `get_detail_param` 无对应 `config_name`」的不可调用模型(`Doubao-Seed-Code`、`glm-5.3` 均属此类,发往 `llm_utils_chat` 必返回 `4001 param is invalid`);`FALLBACK_TRAE_MODELS` 移除已下线的 `Doubao-Seed-Code`。
|
|
12
|
+
- 账号选择改为严格绑定用户显式选择:删除启动时按通用积分自动挑选账号的逻辑,未选号时仅用第一个发现的账号;账号失效时不再静默切换到其他账号,而是报「未登录」让用户重新选择,避免账单落到用户未选择的账号上。
|
|
13
|
+
|
|
14
|
+
### Changes
|
|
15
|
+
|
|
16
|
+
- 模型管理体验与 `dsh-connect-workbuddy` 对齐:一个上游模型只对应一个 DSH 模型 id,移除运行时 `@1m` 变体,改用逐模型 `contextBudgets` 在 Trae 公布的默认 / Max 窗口之间选择。
|
|
17
|
+
- 未勾选任何模型时按完整目录提供模型,避免初次配置或旧设置迁移后 provider 目录为空;旧配置中的 `@1m` 行会被自动过滤。
|
|
18
|
+
- 模型卡片改为右侧上下文预算单选或固定窗口值,并统一显示多模态标记与原始推理档位 `low / high / xhigh`。
|
|
19
|
+
- 模型发现草稿补充与适配器目录一致的 `inputModalities`;当前 DSH 版本可能在核心规范化阶段丢弃该扩展字段,但正式 PiAiAdapter 模型元数据与图片请求链路保持完整。
|
|
20
|
+
- Trae SOLO 请求改为按已验证字段构造 `llm_utils_chat` envelope,过滤 OpenAI 可选参数以避免 `param is invalid`;同时将 DSH 推理档位映射为模型声明的 Trae wire value,并继续规范化 `developer` 为 `system`。
|
|
21
|
+
- 模型发现以 Remote `/models` 目录为骨架,用 `get_detail_param` 补充 `wireConfigName`(`llm_utils_chat` 真正接受的 `config_name`),按 `config_name == id` 优先、`display_name == name` 次之两级 join;join 不到 wire 行的 remote 模型(不可调用)会被剔除,修复 Seed-Code 等模型因展示名与 wire id 不一致导致的 `param is invalid`。
|
|
22
|
+
|
|
23
|
+
### Docs
|
|
24
|
+
|
|
25
|
+
- 更新 README 顶部插件卡片截图(账号选择、积分卡片与模型列表的当前界面)。
|
|
26
|
+
- 移除仓库内开发期的一次性探测脚本(`scripts/probe-*.mjs`、`scripts/inspect-raw-chat-log.mjs`)及其只读脚本内容断言测试,保持仓库与发布包聚焦产品代码;`lib/`、`tests/` 与 `node_modules/` 依旧不进入发布包。
|
|
27
|
+
|
|
28
|
+
## 1.0.1 (2026-08-31)
|
|
29
|
+
|
|
30
|
+
### Changes
|
|
31
|
+
|
|
32
|
+
- 将 Cordis 插件运行 ID 从 `llm-trae` 统一调整为 `dsh-connect-trae`,与 npm 包名保持一致。已有 1.0.0 本地安装升级后如保留旧配置条目,需移除旧的 `llm-trae` 实例,避免重复加载。
|
|
33
|
+
|
|
34
|
+
### Windows support
|
|
35
|
+
|
|
36
|
+
- `src/identity.ts` 现按平台读取 `product.json`:macOS 保持原路径,新增 Windows 路径 `<LOCALAPPDATA>\Programs\<AppName>\resources\app\product.json`(缺失时回退 `<home>\AppData\Local`),Windows 上 `appVersion` 不再恒为 `undefined`,会随请求头发送 `x-app-version` / `x-ide-version`。
|
|
37
|
+
- `src/identity.ts` 的 `osVersion` 在 Windows 上由 `win32 <release>` 规范化为 `Windows <release>`。
|
|
38
|
+
- `src/identity.ts` / `src/model-cache.ts` 路径推导参数化(`platform` / `home` / `env` 可选注入,默认取真实环境),便于跨平台测试;所有平台判断统一使用同一平台源,避免 `x-device-type` 与 `x-os-version` 自相矛盾。
|
|
39
|
+
- `src/model-cache.ts` 的 `state.vscdb` 路径按平台推导;该模块依赖 `sqlite3` 命令行,Windows 默认未安装,Raw Chat 探测会失败并安全回退(Raw Chat 默认关闭,不影响主流程),详见 README「Windows 说明」。
|
|
40
|
+
- 新增 Windows / Linux / `sg` / `solo-sg` 的 identity 测试用例;修复 `tests/identity.spec.ts` 中依赖测试机平台类型的断言(现显式注入平台,Windows 真机与 CI 均可通过)。
|
|
41
|
+
|
|
3
42
|
## 1.0.0 (2026-08-30)
|
|
4
43
|
|
|
5
44
|
### Features
|
package/README.en.md
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/dsh-connect-trae-usage-card.png" width="860" alt="dsh-connect-trae settings panel" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">dsh-connect-trae</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center"><b>Connect locally signed-in Trae models to DeepSeek Harness with local DSH tools and a read-only credits overview.</b></p>
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="README.md">中文</a> ·
|
|
11
|
+
<a href="#install">Install</a> ·
|
|
12
|
+
<a href="#how-it-works">How it works</a> ·
|
|
13
|
+
<a href="CHANGELOG.md">Changelog</a> ·
|
|
14
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/issues">Issues</a>
|
|
15
|
+
</p>
|
|
8
16
|
|
|
9
17
|
<p align="center">
|
|
10
|
-
<img src="
|
|
18
|
+
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/v/dsh-connect-trae?style=flat-square&label=npm&color=cb3837" alt="npm version"></a>
|
|
19
|
+
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/dm/dsh-connect-trae?style=flat-square&label=downloads" alt="npm downloads"></a>
|
|
20
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/dingminhua/dsh-connect-trae/ci.yml?branch=main&style=flat-square&label=tests" alt="test status"></a>
|
|
21
|
+
<a href="LICENSE"><img src="https://img.shields.io/github/license/dingminhua/dsh-connect-trae?style=flat-square" alt="MIT license"></a>
|
|
22
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/stargazers"><img src="https://img.shields.io/github/stars/dingminhua/dsh-connect-trae?style=flat-square" alt="GitHub stars"></a>
|
|
23
|
+
<a href="https://dshfind.com/plugins/dingminhua/dsh-connect-trae"><img src="https://dshfind.com/api/badge/dingminhua/dsh-connect-trae" alt="dshfind plugin"></a>
|
|
11
24
|
</p>
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
A [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) bundle plugin that connects locally signed-in Trae CN models to the DSH model picker. Trae generates structured tool calls while DSH executes its own local tools, with a read-only Work/general credits and model-management panel.
|
|
14
27
|
|
|
15
28
|
## Features
|
|
16
29
|
|
|
@@ -50,6 +63,13 @@ npm install dsh-connect-trae
|
|
|
50
63
|
|
|
51
64
|
Restart the DSH process after install/update/uninstall.
|
|
52
65
|
|
|
66
|
+
## Windows notes
|
|
67
|
+
|
|
68
|
+
- **Account data directory**: the plugin reads `%APPDATA%\Trae CN` / `%APPDATA%\TRAE SOLO CN` → `User\globalStorage\storage.json` (unrelated to the install directory). The folder names match macOS, so no extra config is needed; if the name does not match, point the `authFile` + `edition` plugin options at the exact path.
|
|
69
|
+
- **App version headers**: the plugin reads `appVersion` from `<LOCALAPPDATA>\Programs\<AppName>\resources\app\product.json` and sends `x-app-version` / `x-ide-version`; if unreadable, those headers are omitted (same as the previous behavior).
|
|
70
|
+
- **Raw Chat probing (known limitation)**: `model-cache` depends on the `sqlite3` command-line tool, which is not installed by default on Windows; Raw Chat capability probing fails and falls back safely. Raw Chat is off by default and does not affect the main flow.
|
|
71
|
+
- See `docs/WINDOWS_TOKEN_PROBE.md` for troubleshooting.
|
|
72
|
+
|
|
53
73
|
## Development
|
|
54
74
|
|
|
55
75
|
```sh
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<
|
|
2
|
+
<img src="docs/assets/dsh-connect-trae-usage-card.png" width="860" alt="dsh-connect-trae settings panel" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">dsh-connect-trae</h1>
|
|
@@ -16,19 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
18
|
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/v/dsh-connect-trae?style=flat-square&label=npm&color=cb3837" alt="npm version"></a>
|
|
19
|
+
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/dm/dsh-connect-trae?style=flat-square&label=downloads" alt="npm downloads"></a>
|
|
20
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/dingminhua/dsh-connect-trae/ci.yml?branch=main&style=flat-square&label=tests" alt="test status"></a>
|
|
19
21
|
<a href="LICENSE"><img src="https://img.shields.io/github/license/dingminhua/dsh-connect-trae?style=flat-square" alt="MIT license"></a>
|
|
22
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/stargazers"><img src="https://img.shields.io/github/stars/dingminhua/dsh-connect-trae?style=flat-square" alt="GitHub stars"></a>
|
|
23
|
+
<a href="https://dshfind.com/plugins/dingminhua/dsh-connect-trae"><img src="https://dshfind.com/api/badge/dingminhua/dsh-connect-trae" alt="dshfind plugin"></a>
|
|
20
24
|
</p>
|
|
21
25
|
|
|
22
26
|
一个独立的 [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) bundle 插件。它把本机已登录的 Trae 中国区账号接到 DSH 的模型选择器:模型负责生成结构化工具调用,`bash` / `read` / `write` / `edit` 等工具由 DSH 本地执行;同时提供**只读**的 Work/通用积分与模型管理界面。
|
|
23
27
|
|
|
24
|
-
## 效果预览
|
|
25
|
-
|
|
26
|
-
<p align="center">
|
|
27
|
-
<img src="docs/assets/dsh-connect-trae-usage-card.png" alt="DSH Connect Trae 插件卡片:Trae 账号、Work 与通用积分以及模型管理" width="900">
|
|
28
|
-
</p>
|
|
29
|
-
|
|
30
|
-
<p align="center"><sub>设置 → 插件配置 → DSH Connect Trae:切换本机 Trae 账号、查看 Work/通用积分,并管理 DSH 中启用的 Trae 模型。</sub></p>
|
|
31
|
-
|
|
32
28
|
## 功能特性
|
|
33
29
|
|
|
34
30
|
- **Trae 模型接入** —— 把本机登录的 Trae 模型注册为 DSH 的 `trae` provider,模型选择器出现 `DeepSeek-V4-Flash`、`DeepSeek-V4-Pro` 等。
|
|
@@ -69,6 +65,13 @@ npm install dsh-connect-trae
|
|
|
69
65
|
|
|
70
66
|
安装、更新或卸载 bundle 后,需要重启对应的 DSH 进程。
|
|
71
67
|
|
|
68
|
+
## Windows 说明
|
|
69
|
+
|
|
70
|
+
- **账号数据目录**:插件读取 `%APPDATA%\Trae CN` / `%APPDATA%\TRAE SOLO CN` 下的 `User\globalStorage\storage.json`(与安装目录无关)。目录名与 macOS 一致,无需额外配置;若目录名对不上,可用插件配置项 `authFile` + `edition` 直接指定完整路径。
|
|
71
|
+
- **应用版本头**:插件从安装目录 `<LOCALAPPDATA>\Programs\<AppName>\resources\app\product.json` 读取 `appVersion`,随请求发送 `x-app-version` / `x-ide-version`;读不到时这些头不发送(与旧版行为一致)。
|
|
72
|
+
- **Raw Chat 探测(已知限制)**:`model-cache` 依赖 `sqlite3` 命令行,Windows 默认未安装,Raw Chat 能力探测会失败并安全回退。Raw Chat 默认关闭,不影响主流程。
|
|
73
|
+
- 排查指引见 `docs/WINDOWS_TOKEN_PROBE.md`。
|
|
74
|
+
|
|
72
75
|
## 开发
|
|
73
76
|
|
|
74
77
|
```sh
|
package/cordis.patch.yml
CHANGED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -101,10 +101,13 @@ window.__ModuleLoader__.load({
|
|
|
101
101
|
.dsm-trae-model-copy{display:flex;align-items:baseline;gap:8px;min-width:0}
|
|
102
102
|
.dsm-trae-model-name{display:inline-flex;align-items:baseline;gap:7px;color:var(--dsw-alias-label-primary,#e6e6e6);font-size:13px;font-weight:500;line-height:19px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
103
103
|
.dsm-trae-model-name-rate{color:var(--dsw-alias-label-tertiary,#999);font-size:11px;font-weight:400;line-height:16px;flex:none}
|
|
104
|
-
.dsm-trae-model-id{color:var(--dsw-alias-label-tertiary,#999);font-size:11px;line-height:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
105
104
|
.dsm-trae-model-meta{display:flex;align-items:center;gap:7px 12px;flex-wrap:wrap;color:var(--dsw-alias-label-tertiary,#999);font-size:11px;line-height:16px}
|
|
106
|
-
.dsm-trae-model-
|
|
107
|
-
.dsm-trae-model-
|
|
105
|
+
.dsm-trae-model-options{display:flex;align-items:center;justify-content:flex-end;gap:12px;flex:none}
|
|
106
|
+
.dsm-trae-model-image{display:inline-flex;align-items:center;gap:4px;color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:11px;line-height:16px;cursor:pointer}
|
|
107
|
+
.dsm-trae-model-image input{margin:0;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
108
|
+
.dsm-trae-context-budget{display:flex;align-items:center;justify-content:flex-end;gap:12px;flex:none;margin:0;padding:0;border:0;color:var(--dsw-alias-label-secondary,#c6c9d0);font-size:11px;line-height:16px}
|
|
109
|
+
.dsm-trae-context-budget label{display:inline-flex;align-items:center;gap:4px;cursor:pointer}
|
|
110
|
+
.dsm-trae-context-budget input{margin:0;accent-color:var(--dsw-alias-brand-primary,#5686fe)}
|
|
108
111
|
.dsm-trae-model-capability-note{margin:0;color:var(--dsw-alias-label-tertiary,#999);font-size:12px;line-height:18px}
|
|
109
112
|
.dsm-trae-model-actions{display:flex;align-items:center;justify-content:space-between;gap:12px;border-top:1px solid var(--dsw-alias-border-l2,#36373b);padding-top:12px}
|
|
110
113
|
.dsm-trae-model-actions-buttons{display:flex;align-items:center;justify-content:flex-end;gap:8px}
|
|
@@ -137,7 +140,7 @@ window.__ModuleLoader__.load({
|
|
|
137
140
|
function formatNumber(value) {
|
|
138
141
|
return new Intl.NumberFormat(void 0, {
|
|
139
142
|
minimumFractionDigits: 0,
|
|
140
|
-
maximumFractionDigits:
|
|
143
|
+
maximumFractionDigits: 0
|
|
141
144
|
}).format(value);
|
|
142
145
|
}
|
|
143
146
|
function formatDateTime(value) {
|
|
@@ -155,11 +158,6 @@ window.__ModuleLoader__.load({
|
|
|
155
158
|
if (value >= 1e3 && value % 1e3 === 0) return `${value / 1e3}K`;
|
|
156
159
|
return formatNumber(value);
|
|
157
160
|
}
|
|
158
|
-
const EFFORT_LABELS = {
|
|
159
|
-
low: "轻",
|
|
160
|
-
high: "高",
|
|
161
|
-
xhigh: "极高"
|
|
162
|
-
};
|
|
163
161
|
function dotStyle(status) {
|
|
164
162
|
return { background: status === "signed-in" ? "var(--dsw-alias-state-success-primary, #22a06b)" : status === "error" ? "var(--dsw-alias-state-error-primary, #d92d20)" : "var(--dsw-alias-label-dimmed, #9aa0a6)" };
|
|
165
163
|
}
|
|
@@ -175,7 +173,8 @@ window.__ModuleLoader__.load({
|
|
|
175
173
|
const [settingsRevision, setSettingsRevision] = (0, react.useState)(0);
|
|
176
174
|
const [draftModels, setDraftModels] = (0, react.useState)(void 0);
|
|
177
175
|
const [draftEnabledIds, setDraftEnabledIds] = (0, react.useState)(void 0);
|
|
178
|
-
const [
|
|
176
|
+
const [draftImageIds, setDraftImageIds] = (0, react.useState)(void 0);
|
|
177
|
+
const [draftContextBudgets, setDraftContextBudgets] = (0, react.useState)(void 0);
|
|
179
178
|
const [saving, setSaving] = (0, react.useState)(false);
|
|
180
179
|
const [switchingAccount, setSwitchingAccount] = (0, react.useState)(false);
|
|
181
180
|
const mounted = (0, react.useRef)(true);
|
|
@@ -269,15 +268,22 @@ window.__ModuleLoader__.load({
|
|
|
269
268
|
});
|
|
270
269
|
const body = await response.json();
|
|
271
270
|
if (!response.ok || !Array.isArray(body.models)) throw new Error(`HTTP ${response.status}`);
|
|
272
|
-
const fresh = body.models
|
|
273
|
-
const oldEnabled = status.status === "signed-in" ? new Set(status.enabledModelIds) : /* @__PURE__ */ new Set();
|
|
274
|
-
const old1m = status.status === "signed-in" ? new Set(status.enabled1mModelIds) : /* @__PURE__ */ new Set();
|
|
271
|
+
const fresh = body.models;
|
|
275
272
|
const freshIds = new Set(fresh.map((model) => model.id));
|
|
276
|
-
const stillEnabled = [...
|
|
277
|
-
const
|
|
278
|
-
|
|
273
|
+
const stillEnabled = [...activeEnabledIds].filter((id) => freshIds.has(id));
|
|
274
|
+
const stillImages = [...activeImageIds].filter((id) => freshIds.has(id));
|
|
275
|
+
const stillBudgets = {};
|
|
276
|
+
for (const id of freshIds) {
|
|
277
|
+
const budget = activeContextBudgets[id];
|
|
278
|
+
if (typeof budget === "number") stillBudgets[id] = budget;
|
|
279
|
+
}
|
|
280
|
+
setDraftModels(fresh.map((model) => ({
|
|
281
|
+
...model,
|
|
282
|
+
input: ["text"]
|
|
283
|
+
})));
|
|
279
284
|
setDraftEnabledIds(new Set(stillEnabled));
|
|
280
|
-
|
|
285
|
+
setDraftImageIds(new Set(stillImages));
|
|
286
|
+
setDraftContextBudgets(stillBudgets);
|
|
281
287
|
} catch (error) {
|
|
282
288
|
if (mounted.current) setStatus({
|
|
283
289
|
status: "error",
|
|
@@ -288,37 +294,50 @@ window.__ModuleLoader__.load({
|
|
|
288
294
|
}
|
|
289
295
|
};
|
|
290
296
|
const settingsValue = settingsScope?.getSnapshot().value;
|
|
291
|
-
|
|
297
|
+
const savedContextBudgets = typeof settingsValue === "object" && settingsValue !== null && typeof settingsValue.contextBudgets === "object" && settingsValue.contextBudgets !== null ? settingsValue.contextBudgets : {};
|
|
298
|
+
const savedImageIds = new Set(typeof settingsValue === "object" && settingsValue !== null && Array.isArray(settingsValue.imageModelIds) ? settingsValue.imageModelIds.filter((id) => typeof id === "string") : []);
|
|
292
299
|
const visibleModels = draftModels ?? (status.status === "signed-in" ? status.models : []);
|
|
293
300
|
const savedEnabledIds = status.status === "signed-in" ? new Set(status.enabledModelIds) : /* @__PURE__ */ new Set();
|
|
294
|
-
const saved1mIds = status.status === "signed-in" ? new Set(status.enabled1mModelIds) : /* @__PURE__ */ new Set();
|
|
295
301
|
const activeEnabledIds = draftEnabledIds ?? savedEnabledIds;
|
|
296
|
-
const
|
|
297
|
-
const
|
|
302
|
+
const activeImageIds = draftImageIds ?? savedImageIds;
|
|
303
|
+
const activeContextBudgets = draftContextBudgets ?? savedContextBudgets;
|
|
304
|
+
const dirty = draftModels !== void 0 || draftEnabledIds !== void 0 || draftImageIds !== void 0 || draftContextBudgets !== void 0;
|
|
298
305
|
const toggleModel = (modelId) => {
|
|
299
306
|
const next = new Set(activeEnabledIds);
|
|
300
307
|
if (!next.delete(modelId)) next.add(modelId);
|
|
301
308
|
setDraftEnabledIds(next);
|
|
302
309
|
setDraftModels([...visibleModels]);
|
|
303
310
|
};
|
|
304
|
-
const
|
|
305
|
-
const next = new Set(
|
|
311
|
+
const toggleImage = (modelId) => {
|
|
312
|
+
const next = new Set(activeImageIds);
|
|
306
313
|
if (!next.delete(modelId)) next.add(modelId);
|
|
307
|
-
|
|
314
|
+
setDraftImageIds(next);
|
|
315
|
+
setDraftModels([...visibleModels]);
|
|
316
|
+
};
|
|
317
|
+
const setContextBudget = (modelId, budget) => {
|
|
318
|
+
const next = { ...activeContextBudgets };
|
|
319
|
+
if (budget === void 0) delete next[modelId];
|
|
320
|
+
else next[modelId] = budget;
|
|
321
|
+
setDraftContextBudgets(next);
|
|
308
322
|
setDraftModels([...visibleModels]);
|
|
309
323
|
};
|
|
310
324
|
const discardModels = () => {
|
|
311
325
|
setDraftModels(void 0);
|
|
312
326
|
setDraftEnabledIds(void 0);
|
|
313
|
-
|
|
327
|
+
setDraftImageIds(void 0);
|
|
328
|
+
setDraftContextBudgets(void 0);
|
|
314
329
|
};
|
|
315
330
|
const saveModels = async () => {
|
|
316
331
|
if (settingsScope === void 0) return;
|
|
317
332
|
setSaving(true);
|
|
318
333
|
try {
|
|
319
|
-
await settingsScope.set("lastCatalog", visibleModels.
|
|
334
|
+
await settingsScope.set("lastCatalog", visibleModels.map((model) => ({
|
|
335
|
+
...model,
|
|
336
|
+
input: ["text"]
|
|
337
|
+
})));
|
|
320
338
|
await settingsScope.set("enabledModelIds", [...activeEnabledIds]);
|
|
321
|
-
await settingsScope.set("
|
|
339
|
+
await settingsScope.set("imageModelIds", [...activeImageIds].filter((id) => activeEnabledIds.has(id)));
|
|
340
|
+
await settingsScope.set("contextBudgets", activeContextBudgets);
|
|
322
341
|
discardModels();
|
|
323
342
|
await refreshUsage();
|
|
324
343
|
} finally {
|
|
@@ -507,9 +526,9 @@ window.__ModuleLoader__.load({
|
|
|
507
526
|
onChange: () => {
|
|
508
527
|
toggleModel(model.id);
|
|
509
528
|
}
|
|
510
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
529
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
511
530
|
className: "dsm-trae-model-copy",
|
|
512
|
-
children:
|
|
531
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
513
532
|
className: "dsm-trae-model-name",
|
|
514
533
|
children: [model.name, model.creditMultiplier === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
515
534
|
className: "dsm-trae-model-name-rate",
|
|
@@ -519,29 +538,48 @@ window.__ModuleLoader__.load({
|
|
|
519
538
|
"x)"
|
|
520
539
|
]
|
|
521
540
|
})]
|
|
522
|
-
})
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
541
|
+
})
|
|
542
|
+
})]
|
|
543
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
544
|
+
className: "dsm-trae-model-options",
|
|
545
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
546
|
+
className: "dsm-trae-model-image",
|
|
547
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
548
|
+
type: "checkbox",
|
|
549
|
+
checked: activeImageIds.has(model.id),
|
|
550
|
+
disabled: settingsScope?.getSnapshot().writable !== true || saving,
|
|
551
|
+
onChange: () => {
|
|
552
|
+
toggleImage(model.id);
|
|
553
|
+
}
|
|
554
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelImage") })]
|
|
555
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
556
|
+
className: "dsm-trae-context-budget",
|
|
557
|
+
"aria-label": t("row.contextBudget"),
|
|
558
|
+
children: [model.maxContextWindow !== void 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
559
|
+
type: "radio",
|
|
560
|
+
name: `context-${model.id}`,
|
|
561
|
+
checked: activeContextBudgets[model.id] !== model.maxContextWindow,
|
|
562
|
+
disabled: settingsScope?.getSnapshot().writable !== true || saving,
|
|
563
|
+
onChange: () => {
|
|
564
|
+
setContextBudget(model.id, model.contextWindow);
|
|
565
|
+
}
|
|
566
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatCapacity(model.contextWindow, t("row.modelUnknown")) })] }) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
567
|
+
type: "radio",
|
|
568
|
+
name: `context-${model.id}`,
|
|
569
|
+
checked: model.maxContextWindow === void 0 || activeContextBudgets[model.id] === model.maxContextWindow,
|
|
570
|
+
disabled: model.maxContextWindow === void 0 || settingsScope?.getSnapshot().writable !== true || saving,
|
|
571
|
+
onChange: () => {
|
|
572
|
+
setContextBudget(model.id, model.maxContextWindow);
|
|
573
|
+
}
|
|
574
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: formatCapacity(model.maxContextWindow ?? model.contextWindow, t("row.modelUnknown")) })] })]
|
|
526
575
|
})]
|
|
527
|
-
}), model.maxContextWindow === void 0 || model.maxContext === true ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
528
|
-
className: "dsm-trae-model-toggle",
|
|
529
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
530
|
-
type: "checkbox",
|
|
531
|
-
checked: active1mIds.has(model.id),
|
|
532
|
-
disabled: !activeEnabledIds.has(model.id) || settingsScope?.getSnapshot().writable !== true || busy || saving,
|
|
533
|
-
onChange: () => {
|
|
534
|
-
toggle1m(model.id);
|
|
535
|
-
}
|
|
536
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelEnable1m") })]
|
|
537
576
|
})]
|
|
538
577
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
539
578
|
className: "dsm-trae-model-meta",
|
|
540
579
|
children: [
|
|
541
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelContext", { context: formatCapacity(model.contextWindow, t("row.modelUnknown")) }) }),
|
|
580
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelContext", { context: formatCapacity(model.maxContextWindow ?? model.contextWindow, t("row.modelUnknown")) }) }),
|
|
542
581
|
model.maxTokens === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelOutput", { output: formatCapacity(model.maxTokens, t("row.modelUnknown")) }) }),
|
|
543
|
-
model.
|
|
544
|
-
model.reasoning === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelReasoning", { efforts: model.reasoning.supported.map((effort) => EFFORT_LABELS[effort] ?? effort).join(" / ") }) })
|
|
582
|
+
model.reasoning === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("row.modelReasoning", { efforts: model.reasoning.supported.join(" / ") }) })
|
|
545
583
|
]
|
|
546
584
|
})]
|
|
547
585
|
}, model.id))
|
|
@@ -640,15 +678,15 @@ window.__ModuleLoader__.load({
|
|
|
640
678
|
"row.discard": "Discard changes",
|
|
641
679
|
"row.save": "Save",
|
|
642
680
|
"row.saving": "Saving…",
|
|
643
|
-
"row.modelContext": "
|
|
681
|
+
"row.modelContext": "Max context {context}",
|
|
682
|
+
"row.contextBudget": "DSH context budget",
|
|
644
683
|
"row.modelOutput": "Output {output}",
|
|
684
|
+
"row.modelImage": "Image",
|
|
645
685
|
"row.modelRate": "{rate}x credits",
|
|
646
686
|
"row.modelReasoning": "Reasoning: {efforts}",
|
|
647
687
|
"row.modelReasoningSupported": "Reasoning: supported",
|
|
648
688
|
"row.modelUnknown": "Unknown",
|
|
649
|
-
"row.
|
|
650
|
-
"row.modelEnable1m": "Enable 1M model",
|
|
651
|
-
"row.modelCapabilityPending": "Only capabilities advertised by Trae are shown.",
|
|
689
|
+
"row.modelCapabilityPending": "Image input is enabled only for models you select.",
|
|
652
690
|
"row.cheer": "Star on GitHub"
|
|
653
691
|
};
|
|
654
692
|
const zh = {
|
|
@@ -687,15 +725,15 @@ window.__ModuleLoader__.load({
|
|
|
687
725
|
"row.discard": "放弃修改",
|
|
688
726
|
"row.save": "保存",
|
|
689
727
|
"row.saving": "保存中…",
|
|
690
|
-
"row.modelContext": "
|
|
728
|
+
"row.modelContext": "最大上下文 {context}",
|
|
729
|
+
"row.contextBudget": "DSH 上下文预算",
|
|
691
730
|
"row.modelOutput": "最大输出 {output}",
|
|
731
|
+
"row.modelImage": "图片",
|
|
692
732
|
"row.modelRate": "积分 {rate}x",
|
|
693
733
|
"row.modelReasoning": "推理强度:{efforts}",
|
|
694
734
|
"row.modelReasoningSupported": "推理:支持",
|
|
695
735
|
"row.modelUnknown": "未知",
|
|
696
|
-
"row.
|
|
697
|
-
"row.modelEnable1m": "启用 1M 模型",
|
|
698
|
-
"row.modelCapabilityPending": "仅展示 Trae 接口明确公布的模型能力。",
|
|
736
|
+
"row.modelCapabilityPending": "仅对你手动勾选的模型启用图片输入。",
|
|
699
737
|
"row.cheer": "鼓励一下"
|
|
700
738
|
};
|
|
701
739
|
//#endregion
|