dsh-connect-trae 1.0.1 → 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 +24 -1
- package/docs/assets/dsh-connect-trae-usage-card.png +0 -0
- package/lib/client.js +92 -54
- package/lib/index.d.ts +97 -58
- package/lib/index.js +283 -501
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,29 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
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/` 依旧不进入发布包。
|
|
4
27
|
|
|
5
28
|
## 1.0.1 (2026-08-31)
|
|
6
29
|
|
|
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
|
package/lib/index.d.ts
CHANGED
|
@@ -34,24 +34,88 @@ interface TraeDiscoveredModel {
|
|
|
34
34
|
declare function parseTraeRemoteModel(value: unknown): TraeDiscoveredModel | undefined;
|
|
35
35
|
//#endregion
|
|
36
36
|
//#region src/catalog.d.ts
|
|
37
|
+
type TraeInputModality = 'text' | 'image';
|
|
38
|
+
/**
|
|
39
|
+
* One model the adapter exposes. `contextWindow` is the effective DSH context
|
|
40
|
+
* after the user's budget; `maxContextWindow` is the native Max window Trae
|
|
41
|
+
* advertises (capability display only — never a second model entry).
|
|
42
|
+
*/
|
|
37
43
|
interface TraeModelInfo {
|
|
38
44
|
id: string;
|
|
39
45
|
name: string;
|
|
40
46
|
contextWindow?: number;
|
|
41
47
|
maxTokens?: number;
|
|
42
|
-
input?:
|
|
48
|
+
input?: TraeInputModality[];
|
|
43
49
|
creditMultiplier?: number;
|
|
44
50
|
reasoningSupported?: boolean;
|
|
45
51
|
reasoning?: TraeDiscoveredReasoning;
|
|
46
52
|
reasoningEfforts?: Partial<Record<TraeReasoningEffort, string | null>>;
|
|
47
|
-
baseModelId?: string;
|
|
48
|
-
maxContext?: boolean;
|
|
49
53
|
maxContextWindow?: number;
|
|
54
|
+
/** The `config_name` `llm_utils_chat` accepts; absent means `id` is already the wire id. */
|
|
55
|
+
wireConfigName?: string;
|
|
50
56
|
}
|
|
51
57
|
/** Bootstrap catalog: identity only where current Trae metadata has not been fetched yet. */
|
|
52
58
|
declare const FALLBACK_TRAE_MODELS: readonly TraeModelInfo[];
|
|
53
|
-
/**
|
|
54
|
-
declare function
|
|
59
|
+
/** Exact DSH modalities for one catalog entry; absent metadata is text-only. */
|
|
60
|
+
declare function traeInputModalities(model: Pick<TraeModelInfo, 'input'>): TraeInputModality[];
|
|
61
|
+
/** Apply the user's explicit image opt-ins; upstream and saved row hints are ignored. */
|
|
62
|
+
declare function applyImageSelection(models: readonly TraeModelInfo[], selected: ReadonlySet<string>): TraeModelInfo[];
|
|
63
|
+
/** One row from `get_detail_param`: the authoritative llm_utils_chat wire id + display name. */
|
|
64
|
+
interface TraeWireModel {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
contextWindow?: number;
|
|
68
|
+
maxTokens?: number;
|
|
69
|
+
reasoning?: TraeReasoningCapability;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Merge the two Trae model sources into one authoritative catalog.
|
|
73
|
+
*
|
|
74
|
+
* `remote` (the solo.trae.cn `/models` directory) is the authoritative model
|
|
75
|
+
* skeleton: it supplies the display id, display name, context windows, credit
|
|
76
|
+
* multiplier, reasoning and multimodal flags. `wire` (from `get_detail_param`)
|
|
77
|
+
* supplies the real `llm_utils_chat` `config_name` — the only id the chat
|
|
78
|
+
* endpoint actually accepts. A remote row is only callable when it maps to a
|
|
79
|
+
* wire `config_name`, so a remote row with no wire match is DROPPED (it would
|
|
80
|
+
* otherwise be sent as an invalid `config_name` and rejected with 4001
|
|
81
|
+
* "param is invalid"). Verified 2026-08-30: the Remote directory advertises
|
|
82
|
+
* `Doubao-Seed-Code` and `glm-5.3`, neither of which is a current `config_name`;
|
|
83
|
+
* both fail every request, so they must not be exposed.
|
|
84
|
+
*
|
|
85
|
+
* Joining is two-tier, in priority order:
|
|
86
|
+
* 1. `wire.id` (the `config_name`) equals the remote id — the model's display
|
|
87
|
+
* id is already its wire id (the common case: glm-5.2, DeepSeek-V4-Flash,
|
|
88
|
+
* kimi-k3, …).
|
|
89
|
+
* 2. `wire.name` (the `display_name`) equals the remote display name — for
|
|
90
|
+
* models whose display id differs from the wire id across Trae versions.
|
|
91
|
+
* When the matched wire `config_name` differs from the remote id it is recorded
|
|
92
|
+
* as `wireConfigName`; otherwise it is left undefined (id is already the wire id).
|
|
93
|
+
*/
|
|
94
|
+
declare function mergeTraeModelSources(remote: readonly TraeDiscoveredModel[], wire: readonly TraeWireModel[]): TraeModelInfo[];
|
|
95
|
+
/** Local DSH context budget per model; a value may only select an advertised window. */
|
|
96
|
+
type TraeContextBudget = number;
|
|
97
|
+
/**
|
|
98
|
+
* Apply the saved local budget. Trae advertises two windows per model (dev and
|
|
99
|
+
* Max), so the budget may only switch a model to its own advertised Max value —
|
|
100
|
+
* never to a fabricated number. Everything else keeps the dev window.
|
|
101
|
+
*/
|
|
102
|
+
declare function applyContextBudgets(catalog: readonly TraeModelInfo[], budgets?: Readonly<Record<string, TraeContextBudget | undefined>>): TraeModelInfo[];
|
|
103
|
+
/** Convert Trae metadata into text-only model rows; image support is user-owned configuration. */
|
|
104
|
+
declare function discoveredCatalog(models: readonly TraeDiscoveredModel[]): TraeModelInfo[];
|
|
105
|
+
/**
|
|
106
|
+
* Drop rows saved by older releases that generated `@1m` variant models, so a
|
|
107
|
+
* stale configuration cannot resurrect a variant the runtime no longer builds.
|
|
108
|
+
*/
|
|
109
|
+
declare function sanitizeCatalog(catalog: readonly TraeModelInfo[]): TraeModelInfo[];
|
|
110
|
+
/**
|
|
111
|
+
* Derive the runtime catalog from the last refreshed Trae directory plus the
|
|
112
|
+
* user's explicit selection and context budgets. An empty selection falls back
|
|
113
|
+
* to the whole directory: a plugin that has never been configured must still
|
|
114
|
+
* serve models rather than nothing. This is the single source of truth for
|
|
115
|
+
* what DSH actually exposes, so saving only the selection and budgets is
|
|
116
|
+
* enough to rebuild it after a restart.
|
|
117
|
+
*/
|
|
118
|
+
declare function deriveCatalog(catalog: readonly TraeModelInfo[], enabled: ReadonlySet<string>, budgets?: Readonly<Record<string, TraeContextBudget | undefined>>): TraeModelInfo[];
|
|
55
119
|
declare class TraeCatalog {
|
|
56
120
|
private models;
|
|
57
121
|
current(): readonly TraeModelInfo[];
|
|
@@ -161,7 +225,6 @@ declare class TraeCredentialStore {
|
|
|
161
225
|
private storagePathOverride;
|
|
162
226
|
private edition;
|
|
163
227
|
private accountId;
|
|
164
|
-
private preferIds;
|
|
165
228
|
private readonly ownPath;
|
|
166
229
|
private readonly refresh;
|
|
167
230
|
private readonly refreshMarginMs;
|
|
@@ -169,15 +232,13 @@ declare class TraeCredentialStore {
|
|
|
169
232
|
constructor(options: TraeCredentialStoreOptions);
|
|
170
233
|
setSource(storagePath: string | undefined, edition?: TraeEdition | 'auto', accountId?: string): void;
|
|
171
234
|
selectAccount(accountId: string | undefined): void;
|
|
235
|
+
candidates(): TraeStorageCandidate[];
|
|
172
236
|
/**
|
|
173
|
-
*
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
237
|
+
* Deterministic default when no account is explicitly selected: the first
|
|
238
|
+
* discovered account. This is NOT credit-seeking — it never reorders accounts
|
|
239
|
+
* to find one with general credits. The plugin bills exactly the account the
|
|
240
|
+
* user selected, or the first account when nothing has been selected yet.
|
|
177
241
|
*/
|
|
178
|
-
setPreferAccountIds(ids: readonly string[]): void;
|
|
179
|
-
candidates(): TraeStorageCandidate[];
|
|
180
|
-
/** First credential matching the preferred ordering, else the first live one. */
|
|
181
242
|
private preferred;
|
|
182
243
|
accounts(): Promise<TraeAccountChoice[]>;
|
|
183
244
|
current(): Promise<TraeCredential | undefined>;
|
|
@@ -611,7 +672,7 @@ interface TraeFallbackUpstreamOptions {
|
|
|
611
672
|
}>) => void;
|
|
612
673
|
}
|
|
613
674
|
/**
|
|
614
|
-
*
|
|
675
|
+
* Optional primary route first, native SOLO tool-call route second. Fallback is intentionally narrow:
|
|
615
676
|
* only definitive pre-stream schema/route incompatibilities may retry the same
|
|
616
677
|
* user request. Authentication, credit, rate, cancellation, transport/server
|
|
617
678
|
* failures, and every successful Response are never replayed.
|
|
@@ -706,6 +767,7 @@ interface TraeSoloClientOptions {
|
|
|
706
767
|
identity(): Promise<TraeIdentity>;
|
|
707
768
|
baseUrl?: string;
|
|
708
769
|
fetchImpl?: typeof fetch;
|
|
770
|
+
log?: (message: string, detail?: unknown) => void;
|
|
709
771
|
}
|
|
710
772
|
declare class TraeSoloUpstreamClient {
|
|
711
773
|
private readonly options;
|
|
@@ -718,58 +780,39 @@ declare class TraeSoloUpstreamClient {
|
|
|
718
780
|
//#region src/solo-bridge.d.ts
|
|
719
781
|
/** Convert Trae's named SSE events into OpenAI chat-completion SSE chunks. */
|
|
720
782
|
declare function bridgeTraeSoloStream(response: Response, model: string): Response;
|
|
783
|
+
/** Resolves a display model id to the real llm_utils_chat config_name. */
|
|
784
|
+
type TraeWireResolver = (displayId: string) => string | undefined;
|
|
721
785
|
/** Native SOLO client wrapper used by the loopback OpenAI adapter. */
|
|
722
786
|
declare class TraeSoloBridge implements TraeUpstreamClient {
|
|
723
787
|
private readonly upstream;
|
|
724
|
-
|
|
788
|
+
private readonly catalog?;
|
|
789
|
+
private readonly wireResolver?;
|
|
790
|
+
constructor(upstream: TraeUpstreamClient, catalog?: Pick<TraeCatalog, "current"> | undefined, wireResolver?: TraeWireResolver | undefined);
|
|
725
791
|
chatStream(bodyJson: string, signal?: AbortSignal): Promise<TraeChatResult>;
|
|
726
792
|
}
|
|
727
793
|
//#endregion
|
|
728
794
|
//#region src/solo-remote.d.ts
|
|
729
795
|
declare const TRAE_SOLO_REMOTE_BASE = "https://solo.trae.cn/api/remote/v1";
|
|
730
|
-
|
|
731
|
-
name: string;
|
|
732
|
-
displayName: string;
|
|
733
|
-
multimodal: boolean;
|
|
734
|
-
}[];
|
|
735
|
-
interface TraeSoloRemoteOptions {
|
|
796
|
+
interface TraeSoloRemoteCatalogOptions {
|
|
736
797
|
credential(): Promise<TraeCredential>;
|
|
737
798
|
fetchImpl?: typeof fetch;
|
|
738
799
|
baseUrl?: string;
|
|
739
|
-
pollIntervalMs?: number;
|
|
740
|
-
timeoutMs?: number;
|
|
741
|
-
}
|
|
742
|
-
interface TraeRemoteInputMessage {
|
|
743
|
-
role: string;
|
|
744
|
-
content: string;
|
|
745
800
|
}
|
|
746
|
-
|
|
801
|
+
/**
|
|
802
|
+
* Read-only model catalog client for the SOLO Web API.
|
|
803
|
+
*
|
|
804
|
+
* This deliberately has no chat/session method: the Remote session protocol
|
|
805
|
+
* only exposes a final answer and cannot preserve DSH's structured tool loop.
|
|
806
|
+
*/
|
|
807
|
+
declare class TraeSoloRemoteCatalogClient {
|
|
747
808
|
private readonly options;
|
|
748
809
|
private readonly fetchImpl;
|
|
749
810
|
private readonly baseUrl;
|
|
750
|
-
|
|
751
|
-
private readonly timeoutMs;
|
|
752
|
-
constructor(options: TraeSoloRemoteOptions);
|
|
811
|
+
constructor(options: TraeSoloRemoteCatalogOptions);
|
|
753
812
|
private headers;
|
|
754
|
-
chat(messages: readonly TraeRemoteInputMessage[], model: string, signal?: AbortSignal): Promise<{
|
|
755
|
-
content: string;
|
|
756
|
-
sessionId: string;
|
|
757
|
-
}>;
|
|
758
813
|
fetchModels(signal?: AbortSignal): Promise<TraeDiscoveredModel[]>;
|
|
759
814
|
}
|
|
760
815
|
//#endregion
|
|
761
|
-
//#region src/solo-remote-bridge.d.ts
|
|
762
|
-
/**
|
|
763
|
-
* Bridges the SOLO remote polling-based API into the shim's stream interface.
|
|
764
|
-
* The remote API uses create-session + poll-messages rather than raw SSE,
|
|
765
|
-
* so this bridge converts the final result into a synthetic OpenAI SSE stream.
|
|
766
|
-
*/
|
|
767
|
-
declare class TraeSoloRemoteBridge implements TraeUpstreamClient {
|
|
768
|
-
private readonly remote;
|
|
769
|
-
constructor(remote: TraeSoloRemoteClient);
|
|
770
|
-
chatStream(bodyJson: string, signal?: AbortSignal): Promise<TraeChatResult>;
|
|
771
|
-
}
|
|
772
|
-
//#endregion
|
|
773
816
|
//#region src/delegating-upstream.d.ts
|
|
774
817
|
/** Stable shim dependency whose delegate can be replaced after async setup. */
|
|
775
818
|
declare class TraeDelegatingUpstreamClient implements TraeUpstreamClient {
|
|
@@ -897,10 +940,7 @@ interface TraeWebModel {
|
|
|
897
940
|
supported: string[];
|
|
898
941
|
defaultEffort?: string;
|
|
899
942
|
};
|
|
900
|
-
baseModelId?: string;
|
|
901
|
-
maxContext?: boolean;
|
|
902
943
|
maxContextWindow?: number;
|
|
903
|
-
maxContextEnabled?: boolean;
|
|
904
944
|
}
|
|
905
945
|
/** Daily check-in status rendered by the card. */
|
|
906
946
|
interface TraeWebCheckin {
|
|
@@ -935,7 +975,6 @@ type TraeWebUsage = {
|
|
|
935
975
|
accounts: readonly TraeWebAccount[];
|
|
936
976
|
models: readonly TraeWebModel[];
|
|
937
977
|
enabledModelIds: readonly string[];
|
|
938
|
-
enabled1mModelIds: readonly string[];
|
|
939
978
|
rawChat?: {
|
|
940
979
|
state: 'disabled' | 'unchecked' | 'available' | 'protocol-gated' | 'authentication' | 'credit' | 'rate' | 'transport' | 'server';
|
|
941
980
|
checkedAtMs?: number;
|
|
@@ -953,12 +992,10 @@ type TraeWebUsage = {
|
|
|
953
992
|
interface TraeUsageRouteOptions {
|
|
954
993
|
store: TraeCredentialStore;
|
|
955
994
|
client: TraeUsageClient;
|
|
956
|
-
/** The last-refreshed Trae raw directory (
|
|
995
|
+
/** The last-refreshed Trae raw directory (one entry per upstream model) for card display. */
|
|
957
996
|
displayModels(): readonly TraeModelInfo[];
|
|
958
|
-
/** The user's
|
|
997
|
+
/** The user's model selection stored as model id (= Trae name). */
|
|
959
998
|
enabledModelIds(): readonly string[];
|
|
960
|
-
/** The user's 1M selection stored as base-model id. */
|
|
961
|
-
enabled1mModelIds(): readonly string[];
|
|
962
999
|
discoverModels?(signal?: AbortSignal): Promise<readonly TraeModelInfo[]>;
|
|
963
1000
|
rawDiagnostic?(): TraeRawDiagnostic;
|
|
964
1001
|
}
|
|
@@ -984,12 +1021,14 @@ interface Config {
|
|
|
984
1021
|
lastCatalog?: TraeModelInfo[];
|
|
985
1022
|
/** The user's ordinary-model selection, as model id (= Trae name). */
|
|
986
1023
|
enabledModelIds?: string[];
|
|
987
|
-
/**
|
|
988
|
-
|
|
1024
|
+
/** Local DSH context budget per model; a value may only select an advertised window. */
|
|
1025
|
+
contextBudgets?: Record<string, number>;
|
|
1026
|
+
/** Models the user explicitly enabled for image input; text is always enabled. */
|
|
1027
|
+
imageModelIds?: string[];
|
|
989
1028
|
/** Legacy generated runtime catalog; kept for backwards compatibility. */
|
|
990
1029
|
models?: TraeModelInfo[];
|
|
991
1030
|
}
|
|
992
1031
|
declare const Config: z<Config>;
|
|
993
1032
|
declare function apply(ctx: Context, config: Config): void;
|
|
994
1033
|
//#endregion
|
|
995
|
-
export { Config, FALLBACK_TRAE_MODELS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROVIDER, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE,
|
|
1034
|
+
export { Config, FALLBACK_TRAE_MODELS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROVIDER, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_SETTINGS_NS, TRAE_SOLO_CHAT_PATH, TRAE_SOLO_FUNCTION, TRAE_SOLO_MODELS_PATH, TRAE_SOLO_REMOTE_BASE, TRAE_STREAM_IDLE_TIMEOUT_MS, TRAE_USAGE_PATH, TRAE_VERSION_CODE_FALLBACK, type TraeActivityRule, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinStatus, type TraeContextBudget, type TraeCredential, TraeCredentialStore, TraeDelegatingUpstreamClient, type TraeDiscoveredModel, type TraeDiscoveredReasoning, type TraeEdition, TraeFallbackUpstreamClient, type TraeFallbackUpstreamOptions, type TraeFusionRawChatEnvelope, TraeGatedUpstreamClient, type TraeGatedUpstreamOptions, type TraeIdentity, type TraeInputModality, type TraeModelDetailRequest, type TraeModelInfo, type TraeObservedModelConfig, TraeRawCapabilityController, type TraeRawCapabilityControllerOptions, type TraeRawCapabilitySnapshot, TraeRawCapabilityState, type TraeRawChatBehaviorConfig, type TraeRawChatCapability, type TraeRawChatClientOptions, type TraeRawChatConfig, type TraeRawChatFailureReason, type TraeRawChatRuntimeConfig, TraeRawChatUpstreamClient, type TraeRawDiagnostic, type TraeRawDiagnosticState, type TraeRawGateway, type TraeRawGatewayOptions, type TraeRawResolverResult, type TraeReasoningCapability, type TraeReasoningEffort, type TraeShim, TraeSoloBridge, type TraeSoloClientOptions, TraeSoloRemoteCatalogClient, type TraeSoloRemoteCatalogOptions, TraeSoloUpstreamClient, type TraeStorageCandidate, type TraeStreamEvent, type TraeUpstreamClient, TraeUsageClient, type TraeUsageOptions, type TraeUsagePack, type TraeUsageRouteOptions, type TraeUsageSnapshot, type TraeUsageSummary, type TraeUsageView, type TraeWebActivity, type TraeWebCheckin, type TraeWebCredits, type TraeWebUsage, type TraeWireModel, UnconfiguredTraeUpstreamClient, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyTraeRawChatFailure, createTraeAdapter, createTraeRawGateway, createTraeShim, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, discoveredCatalog, hashTraeRawChatArg, identityHeaders, inject, mergeTraeModelSources, name, normalizeTraeCredential, normalizeTraeVersionCode, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, prepareSoloBody, probeTraeRawChatCapability, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeIdentity, refreshTraeCredential, registerTraeUsageRoute, resolveTraeRawRuntime, sanitizeCatalog, traeEndpoint, traeInputModalities, traeOwnAuthPath, traeRawChatExtraInfo, traeStorageCandidates, traeWebUsage };
|