dsh-connect-trae 4.5.1 → 4.5.2
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 +41 -0
- package/lib/client.js +7 -0
- package/lib/index.d.ts +17 -1
- package/lib/index.js +108 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.5.2 (2026-10-25)
|
|
4
|
+
|
|
5
|
+
> **思考档位不再被吞,也不再被谎报。** 插件原先只认识三档,未知档位一律按 `high`
|
|
6
|
+
> 发出去——用户选 Max、实际收到 high,无报错也无日志。这一版把词表与 Trae 客户端
|
|
7
|
+
> 对齐(`low / medium / high / extra_high / max`),并把「不认识的档位」从谎报改成
|
|
8
|
+
> 丢弃,让上游用它自己的默认值。
|
|
9
|
+
>
|
|
10
|
+
> 词表变宽,**声称没变**:能选哪些档位仍然只取决于上游为该模型实际下发的
|
|
11
|
+
> `options`,所以今天只发三档的模型不会凭空多出 Max。
|
|
12
|
+
|
|
13
|
+
### 修复
|
|
14
|
+
|
|
15
|
+
- **思考档位词表配平,未知档位不再静默降档成 high**(#60)。
|
|
16
|
+
- **三处吞档位**:解析侧 `EFFORT_MAP` / `TRAE_REASONING_EFFORTS` 缺 `medium` 与
|
|
17
|
+
`max`;`toPiModel` 的 `thinkingLevelMap` 把 `minimal / medium / max` 硬编码成
|
|
18
|
+
`null`;反向映射写成三元链
|
|
19
|
+
`effort === 'low' ? 'light' : effort === 'xhigh' ? 'extra_high' : 'high'`。
|
|
20
|
+
- **最坏的是第三处**:任何未预期档位都被映射成 `high` 发给上游。Trae 客户端自己
|
|
21
|
+
认识五档(`reasoning_effort.{low,medium,high,extra_high,max}`),并按 agent model
|
|
22
|
+
灰度下发,所以上游哪天发 `max`,用户选 Max 就会被静默降成 high。**静默降档比
|
|
23
|
+
不给选择器更坏**——它给出一个便宜了、但用户没要的答案。
|
|
24
|
+
- **改法**:反向映射抽成 `WIRE_EFFORT_MAP` 查表 + `wireEffortsOf()`,三处调用点
|
|
25
|
+
统一走它(报告人点到两处,第三处在 wire 行提升的分支里,一起改才不会有同一份
|
|
26
|
+
目录两种行为)。查不到即**丢弃**,而不是猜一个默认值。
|
|
27
|
+
- **实测**(2026-10-25,本机 CN 凭据,98 行目录):当前 `options` 只有
|
|
28
|
+
`["light","high"]`、`["high","extra_high"]`、`["light","high","extra_high"]`
|
|
29
|
+
三种,`max` 尚未下发——所以这是「今天就备好、明天才用上」,不是伪造档位。
|
|
30
|
+
- 测试:新增 10 例(词表、丢弃未知档位、既有三档逐字不变、`discoveredCatalog`
|
|
31
|
+
同步、不伪造档位、`thinkingLevelMap` 按模型而非硬编码)。三处均做变异验证:
|
|
32
|
+
恢复旧映射 → 5 例红;恢复硬编码 `null` → 1 例红;去掉解析侧新键 → 1 例红。
|
|
33
|
+
- 贡献者:[@ahian-lee](https://github.com/ahian-lee)(issue #60,附诊断与补丁)。
|
|
34
|
+
|
|
35
|
+
### 文档
|
|
36
|
+
|
|
37
|
+
- **卡片模型栏写明「上下文预算只影响 DSH 侧」**(#60 的顺带问题)。
|
|
38
|
+
- 每行显示的是 Trae 自己公布的最大窗口,而下面的预算单选只写 DSH 的本地预算;
|
|
39
|
+
请求体里既没有窗口字段、也没有 `max_mode`,所以把预算提到 1M 并不会让上游按
|
|
40
|
+
1M 服务。原先的标签读起来像「已经放开到 1M」。
|
|
41
|
+
- 上游是否接受 `v2_max_mode_enabled` 这类字段**尚未取证**,所以这次不动请求体
|
|
42
|
+
(乱加字段可能让每次请求 400),只把事实说出来:常驻说明,不用悬停提示。
|
|
43
|
+
|
|
3
44
|
## 4.5.1 (2026-10-25)
|
|
4
45
|
|
|
5
46
|
> **只在租户池上架的模型不再隐形。** 插件的模型目录只问了 `solo.trae.cn` 一处,
|
package/lib/client.js
CHANGED
|
@@ -5659,6 +5659,7 @@ window.__ModuleLoader__.load({
|
|
|
5659
5659
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("fieldset", {
|
|
5660
5660
|
className: "dsm-trae-context-budget",
|
|
5661
5661
|
"aria-label": t("row.contextBudget"),
|
|
5662
|
+
title: t("row.contextBudgetHint"),
|
|
5662
5663
|
children: contextBudgetOptions(model).map((option) => {
|
|
5663
5664
|
const selectable = model.maxContextWindow !== void 0;
|
|
5664
5665
|
const checked = (activeContextBudgets[model.id] ?? model.contextWindow) === option;
|
|
@@ -5726,6 +5727,10 @@ window.__ModuleLoader__.load({
|
|
|
5726
5727
|
})
|
|
5727
5728
|
]
|
|
5728
5729
|
}),
|
|
5730
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5731
|
+
className: "dsm-trae-model-capability-note",
|
|
5732
|
+
children: t("row.contextBudgetHint")
|
|
5733
|
+
}),
|
|
5729
5734
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
5730
5735
|
className: "dsm-trae-model-capability-note",
|
|
5731
5736
|
children: t("row.modelCapabilityPending")
|
|
@@ -6898,6 +6903,7 @@ window.__ModuleLoader__.load({
|
|
|
6898
6903
|
"row.veilSaving": "Saving changes…",
|
|
6899
6904
|
"row.modelContext": "Max context {context}",
|
|
6900
6905
|
"row.contextBudget": "DSH context budget",
|
|
6906
|
+
"row.contextBudgetHint": "Affects the DSH-side context budget only. The plugin does not send a window or Max-mode field upstream, so this does not change the window Trae serves the request with.",
|
|
6901
6907
|
"row.modelOutput": "Output {output}",
|
|
6902
6908
|
"row.modelImage": "Image",
|
|
6903
6909
|
"row.modelImageAuto": "Enabled automatically: Trae marks this model multimodal.",
|
|
@@ -7277,6 +7283,7 @@ window.__ModuleLoader__.load({
|
|
|
7277
7283
|
"row.veilSaving": "正在保存更改…",
|
|
7278
7284
|
"row.modelContext": "最大上下文 {context}",
|
|
7279
7285
|
"row.contextBudget": "DSH 上下文预算",
|
|
7286
|
+
"row.contextBudgetHint": "只影响 DSH 侧的上下文预算。插件不会向上游发送窗口或 Max 模式字段,所以这不会改变 Trae 实际服务这次请求所用的窗口。",
|
|
7280
7287
|
"row.modelOutput": "最大输出 {output}",
|
|
7281
7288
|
"row.modelImage": "图片",
|
|
7282
7289
|
"row.modelImageAuto": "已自动开启:Trae 把该模型标为多模态。",
|
package/lib/index.d.ts
CHANGED
|
@@ -44,7 +44,23 @@ interface TraeActivityDiscount {
|
|
|
44
44
|
}
|
|
45
45
|
//#endregion
|
|
46
46
|
//#region src/reasoning.d.ts
|
|
47
|
-
|
|
47
|
+
/**
|
|
48
|
+
* The DSH thinking levels this plugin can carry, in ascending order.
|
|
49
|
+
*
|
|
50
|
+
* `max` is the fifth level Trae's own client advertises — its bundle ships the
|
|
51
|
+
* i18n keys `trae-chat-core.model.reasoning_effort.{low,medium,high,extra_high,max}`
|
|
52
|
+
* and `ai.model.reasoning_effort.{low,medium,high,xhigh,max}`, and publishes the
|
|
53
|
+
* per-model list from a remote config (`AI.agent.model.reasoning_effort_level_by_agent_model_v2`).
|
|
54
|
+
* Leaving it out of this list meant a level the vendor could start serving was
|
|
55
|
+
* filtered away at PARSE time, before anything downstream could decide (issue
|
|
56
|
+
* #60). Listing it does not fabricate the level: `supported` is still built
|
|
57
|
+
* only from what the upstream response actually contains, so a model that does
|
|
58
|
+
* not advertise `max` never offers it.
|
|
59
|
+
*
|
|
60
|
+
* `minimal` is kept for the same reason in reverse — it is a DSH level, so the
|
|
61
|
+
* type must be able to represent it even though no CN model has advertised it.
|
|
62
|
+
*/
|
|
63
|
+
declare const TRAE_REASONING_EFFORTS: readonly ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
48
64
|
type TraeReasoningEffort = typeof TRAE_REASONING_EFFORTS[number];
|
|
49
65
|
interface TraeReasoningCapability {
|
|
50
66
|
supported: readonly TraeReasoningEffort[];
|
package/lib/index.js
CHANGED
|
@@ -282,6 +282,53 @@ function displayKey(name) {
|
|
|
282
282
|
return name.trim().toLowerCase();
|
|
283
283
|
}
|
|
284
284
|
/**
|
|
285
|
+
* DSH thinking level -> the `reasoning_effort` name Trae's wire accepts.
|
|
286
|
+
*
|
|
287
|
+
* The INVERSE of `EFFORT_MAP` in `model-metadata.ts`, and it must stay an exact
|
|
288
|
+
* mirror of it: a level this table does not name has no wire spelling, so it is
|
|
289
|
+
* DROPPED rather than guessed (issue #60).
|
|
290
|
+
*
|
|
291
|
+
* The previous form was a ternary chain ending in a bare `'high'`:
|
|
292
|
+
*
|
|
293
|
+
* effort === 'low' ? 'light' : effort === 'xhigh' ? 'extra_high' : 'high'
|
|
294
|
+
*
|
|
295
|
+
* so EVERY unnamed level was sent as `high`. That is not a harmless default: it
|
|
296
|
+
* is a silent downgrade. Trae's own vocabulary carries five levels
|
|
297
|
+
* (`low / medium / high / extra_high / max`, verified in the client bundle's
|
|
298
|
+
* `reasoning_effort` i18n keys), and its remote config publishes the list per
|
|
299
|
+
* model (`AI.agent.model.reasoning_effort_level_by_agent_model_v2`). The day
|
|
300
|
+
* upstream starts advertising `max`, a user picking Max would have sent `high`
|
|
301
|
+
* — no error, no log, and a cheaper answer than the one they asked for. A
|
|
302
|
+
* dropped field lets the upstream apply its own default, which is at least the
|
|
303
|
+
* model's real behaviour instead of a wrong claim about it.
|
|
304
|
+
*
|
|
305
|
+
* Measured 2026-10-25 on a live CN credential (98 directory rows): options are
|
|
306
|
+
* `["light","high"]`, `["high","extra_high"]`, `["light","high","extra_high"]`
|
|
307
|
+
* or absent — `max` is not published YET, which is exactly why this must not
|
|
308
|
+
* wait for it to be.
|
|
309
|
+
*/
|
|
310
|
+
const WIRE_EFFORT_MAP = {
|
|
311
|
+
low: "light",
|
|
312
|
+
medium: "medium",
|
|
313
|
+
high: "high",
|
|
314
|
+
xhigh: "extra_high",
|
|
315
|
+
max: "max"
|
|
316
|
+
};
|
|
317
|
+
/**
|
|
318
|
+
* Map a model's advertised levels to their wire names, dropping unnamed ones.
|
|
319
|
+
*
|
|
320
|
+
* `flatMap` rather than `map` + a placeholder: an unmappable level must not
|
|
321
|
+
* produce an entry at all, because every consumer reads "is there a value here"
|
|
322
|
+
* as "may this level be sent" (see `thinkingLevelMap` in `adapter.ts` and the
|
|
323
|
+
* `delete input['reasoning_effort']` fallback in `solo-bridge.ts`).
|
|
324
|
+
*/
|
|
325
|
+
function wireEffortsOf(supported) {
|
|
326
|
+
return Object.fromEntries(supported.flatMap((effort) => {
|
|
327
|
+
const wire = WIRE_EFFORT_MAP[effort];
|
|
328
|
+
return wire === void 0 ? [] : [[effort, wire]];
|
|
329
|
+
}));
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
285
332
|
* Merge the two Trae model sources into one authoritative catalog.
|
|
286
333
|
*
|
|
287
334
|
* `remote` (the solo.trae.cn `/models` directory) is the authoritative model
|
|
@@ -360,7 +407,7 @@ function mergeTraeModelSources(remote, wire) {
|
|
|
360
407
|
reasoningSupported: model.reasoningSupported,
|
|
361
408
|
...model.reasoning === void 0 ? {} : {
|
|
362
409
|
reasoning: model.reasoning,
|
|
363
|
-
reasoningEfforts:
|
|
410
|
+
reasoningEfforts: wireEffortsOf(model.reasoning.supported)
|
|
364
411
|
},
|
|
365
412
|
...wireModel !== void 0 && wireModel.id !== "" && wireModel.id !== model.id ? { wireConfigName: wireModel.id } : {},
|
|
366
413
|
...wireFunction === void 0 ? {} : { wireFunction }
|
|
@@ -433,7 +480,7 @@ function mergeTraeModelSources(remote, wire) {
|
|
|
433
480
|
supported: [...wireModel.reasoning.supported],
|
|
434
481
|
...wireModel.reasoning.defaultEffort === void 0 ? {} : { defaultEffort: wireModel.reasoning.defaultEffort }
|
|
435
482
|
},
|
|
436
|
-
reasoningEfforts:
|
|
483
|
+
reasoningEfforts: wireEffortsOf(wireModel.reasoning.supported)
|
|
437
484
|
},
|
|
438
485
|
...wireModel.function === void 0 ? {} : { wireFunction: wireModel.function }
|
|
439
486
|
});
|
|
@@ -507,7 +554,7 @@ function discoveredCatalog(models) {
|
|
|
507
554
|
reasoningSupported: model.reasoningSupported,
|
|
508
555
|
...model.reasoning === void 0 ? {} : {
|
|
509
556
|
reasoning: model.reasoning,
|
|
510
|
-
reasoningEfforts:
|
|
557
|
+
reasoningEfforts: wireEffortsOf(model.reasoning.supported)
|
|
511
558
|
}
|
|
512
559
|
});
|
|
513
560
|
return result;
|
|
@@ -836,14 +883,28 @@ function toPiModel(info, baseUrl, providerId, withRate = true) {
|
|
|
836
883
|
cacheWrite: 0
|
|
837
884
|
},
|
|
838
885
|
reasoning: info.reasoningEfforts !== void 0,
|
|
839
|
-
...info.reasoningEfforts === void 0 ? {} : {
|
|
886
|
+
...info.reasoningEfforts === void 0 ? {} : {
|
|
887
|
+
/**
|
|
888
|
+
* Which DSH levels this model may be asked for, and under which wire name.
|
|
889
|
+
*
|
|
890
|
+
* Every level is read from the model's OWN advertised capability, never
|
|
891
|
+
* hardcoded. `minimal / medium / max` used to be pinned to `null`, so a
|
|
892
|
+
* level the upstream published could not be selected even after it was
|
|
893
|
+
* parsed — the second of the three places issue #60 reported. `null`
|
|
894
|
+
* still means "not offered", which is what a model that does not
|
|
895
|
+
* advertise the level reports: nothing here fabricates a level.
|
|
896
|
+
*
|
|
897
|
+
* `off` stays `null` deliberately: Trae's wire has no "no reasoning"
|
|
898
|
+
* spelling, so an explicit off is not something this provider can send.
|
|
899
|
+
*/
|
|
900
|
+
thinkingLevelMap: {
|
|
840
901
|
off: null,
|
|
841
|
-
minimal: null,
|
|
902
|
+
minimal: info.reasoningEfforts.minimal ?? null,
|
|
842
903
|
low: info.reasoningEfforts.low ?? null,
|
|
843
|
-
medium: null,
|
|
904
|
+
medium: info.reasoningEfforts.medium ?? null,
|
|
844
905
|
high: info.reasoningEfforts.high ?? null,
|
|
845
906
|
xhigh: info.reasoningEfforts.xhigh ?? null,
|
|
846
|
-
max: null
|
|
907
|
+
max: info.reasoningEfforts.max ?? null
|
|
847
908
|
} },
|
|
848
909
|
...info.contextWindow === void 0 ? {} : { contextWindow: info.contextWindow },
|
|
849
910
|
...info.maxTokens === void 0 ? {} : { maxTokens: info.maxTokens },
|
|
@@ -4752,12 +4813,29 @@ function parseTraeActivityDiscount(value) {
|
|
|
4752
4813
|
}
|
|
4753
4814
|
//#endregion
|
|
4754
4815
|
//#region src/reasoning.ts
|
|
4816
|
+
/**
|
|
4817
|
+
* The DSH thinking levels this plugin can carry, in ascending order.
|
|
4818
|
+
*
|
|
4819
|
+
* `max` is the fifth level Trae's own client advertises — its bundle ships the
|
|
4820
|
+
* i18n keys `trae-chat-core.model.reasoning_effort.{low,medium,high,extra_high,max}`
|
|
4821
|
+
* and `ai.model.reasoning_effort.{low,medium,high,xhigh,max}`, and publishes the
|
|
4822
|
+
* per-model list from a remote config (`AI.agent.model.reasoning_effort_level_by_agent_model_v2`).
|
|
4823
|
+
* Leaving it out of this list meant a level the vendor could start serving was
|
|
4824
|
+
* filtered away at PARSE time, before anything downstream could decide (issue
|
|
4825
|
+
* #60). Listing it does not fabricate the level: `supported` is still built
|
|
4826
|
+
* only from what the upstream response actually contains, so a model that does
|
|
4827
|
+
* not advertise `max` never offers it.
|
|
4828
|
+
*
|
|
4829
|
+
* `minimal` is kept for the same reason in reverse — it is a DSH level, so the
|
|
4830
|
+
* type must be able to represent it even though no CN model has advertised it.
|
|
4831
|
+
*/
|
|
4755
4832
|
const TRAE_REASONING_EFFORTS = [
|
|
4756
4833
|
"minimal",
|
|
4757
4834
|
"low",
|
|
4758
4835
|
"medium",
|
|
4759
4836
|
"high",
|
|
4760
|
-
"xhigh"
|
|
4837
|
+
"xhigh",
|
|
4838
|
+
"max"
|
|
4761
4839
|
];
|
|
4762
4840
|
function parseReasoningCapability(value) {
|
|
4763
4841
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
@@ -5863,10 +5941,31 @@ function parseFeatures(value) {
|
|
|
5863
5941
|
return;
|
|
5864
5942
|
}
|
|
5865
5943
|
}
|
|
5944
|
+
/**
|
|
5945
|
+
* Trae's wire effort name -> the DSH thinking level.
|
|
5946
|
+
*
|
|
5947
|
+
* The FORWARD half of the mapping; `WIRE_EFFORT_MAP` in `catalog.ts` is its
|
|
5948
|
+
* exact inverse. Both halves must name the same levels, or a level survives one
|
|
5949
|
+
* direction and vanishes in the other.
|
|
5950
|
+
*
|
|
5951
|
+
* `medium` and `max` are here because Trae's own client advertises them
|
|
5952
|
+
* (`reasoning_effort.{low,medium,high,extra_high,max}` in its i18n bundle) and
|
|
5953
|
+
* publishes the per-model list remotely — so the day upstream starts sending
|
|
5954
|
+
* either, the parser must not filter it away before anything can use it (issue
|
|
5955
|
+
* #60). Measured 2026-10-25 on a live CN credential, the published options were
|
|
5956
|
+
* only `light / high / extra_high`; these entries are therefore inert today and
|
|
5957
|
+
* ready tomorrow, not a claim that the levels are served now.
|
|
5958
|
+
*
|
|
5959
|
+
* An unknown name is deliberately ABSENT rather than defaulted: `parse` drops
|
|
5960
|
+
* it, and the reverse map drops it too, so an unrecognised level can never be
|
|
5961
|
+
* reported to the user or sent upstream under a name the vendor never said.
|
|
5962
|
+
*/
|
|
5866
5963
|
const EFFORT_MAP = {
|
|
5867
5964
|
light: "low",
|
|
5965
|
+
medium: "medium",
|
|
5868
5966
|
high: "high",
|
|
5869
|
-
extra_high: "xhigh"
|
|
5967
|
+
extra_high: "xhigh",
|
|
5968
|
+
max: "max"
|
|
5870
5969
|
};
|
|
5871
5970
|
/**
|
|
5872
5971
|
* Parse only capabilities explicitly advertised by Trae's remote model API.
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-trae",
|
|
3
3
|
"displayName": "DSH Connect Trae",
|
|
4
4
|
"description": "把本机登录的 Trae 模型接入 DeepSeek Harness:国内版与国际版双供应商并行,提供用量/积分概览与每日签到领取。",
|
|
5
|
-
"version": "4.5.
|
|
5
|
+
"version": "4.5.2",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|