dsh-connect-trae 2.1.0 → 2.2.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 +47 -0
- package/README.en.md +19 -0
- package/README.md +19 -0
- package/lib/client.js +178 -38
- package/lib/index.d.ts +46 -1
- package/lib/index.js +98 -19
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,52 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.2.0 (2026-09-24)
|
|
4
|
+
|
|
5
|
+
### Bug Fixes
|
|
6
|
+
|
|
7
|
+
- **支持 DSH 0.1.7 线,且同一个构建同时服务 0.1.5 与 0.1.7**(修复 [issue #13](https://github.com/dingminhua/dsh-connect-trae/issues/13))。这不是「多支持一个版本」的可选增强——**在 0.1.7 上插件的浏览器半侧此前根本不激活**:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
web boot: 1 entry did not activate
|
|
11
|
+
dsh-connect-trae: pending (waiting for service: settingsScope)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
- **根因:`settingsScope` 被整个移除,而 Cordis 的依赖闸门是硬闸。** DSH **0.1.7-alpha.1** 起客户端设置服务换成 `configForms`,`settingsScope` **不再存在**(不是弃用、没有兼容层;0.1.6-alpha.2 还有,0.1.7-alpha.1 起包内已无此符号)。插件 `inject` 里仍声明它,于是 fiber 永远停在 `PENDING`——**不是某个功能坏掉,是整个客户端插件不激活**,因此「重新登录」「重装插件」一概无效。修法与 workbuddy 一致:`inject` 收窄为两条线都有的 `['slots', 'locale']`,设置面改由 `ctx.get()` **按能力软探测**(属性访问会抛 `cannot get property X without inject`,`?.` 挡不住;`ctx.get` 对缺失服务返回 `undefined`)。
|
|
15
|
+
- **0.1.7 上另有三处断裂,issue 只报了第一处。** 逐项对照 workbuddy 的实测(该仓库已用同一套适配跑通 0.1.7):
|
|
16
|
+
|
|
17
|
+
| # | 位置 | 0.1.5 | 0.1.7 |
|
|
18
|
+
|---|---|---|---|
|
|
19
|
+
| 1 | 客户端设置服务 | `settingsScope` | `configForms` |
|
|
20
|
+
| 2 | 客户端槽位名 | `settings.plugin.item` | `plugins.bundle.config` / `plugins.row.config` |
|
|
21
|
+
| 3 | 宿主端注册 | `installSection()` | `configure({auto}, owner)` |
|
|
22
|
+
| 4 | schema 可写声明 | 无需 | 必须标 `volatile()` |
|
|
23
|
+
| 5 | primitives 图标名 | `…Outline14` | `…OutlineRegular` |
|
|
24
|
+
|
|
25
|
+
- **第 2 条(槽位名)最容易被漏掉**:两条线声明的槽位集合**互不相交**(0.1.5 只有 `settings.plugin.item`;0.1.7 只有 `plugins.*`)。就算设置服务改对了,槽位名不改卡片依然渲染不出来。现在三个槽位**各自独立 try/catch** 逐个注册——一条线上不存在的槽位不能把另一条线的注册一起带走。
|
|
26
|
+
- **第 3 条(宿主端)在 0.1.7 上是静默失败**:`installSection` 被 `SettingsForms.configure()` 取代。由于该调用位于嵌套的 `ctx.inject` 回调内,抛出的 `installSection is not a function` 落在**那个子 fiber** 上——外层插件照常加载、两个 provider 照常注册,**但 `trae` 设置命名空间从未注册**,表现为卡片设置区无声消失。现在按能力探测:有 `configure` 走 `configure`,否则回落 `installSection`。
|
|
27
|
+
- **第 4 条(易失声明)**:0.1.7 的 settings 写入门要求插件 schema 把可写字段标为 volatile,否则**写入被直接拒绝**(`Plugin entry "trae" has no volatile fields`),而 `scope.set()` 却正常 resolve——用户会看到开关翻过去又静默复原。新增 `asVolatile()`:运行时探测 `schema.volatile()`,**有则调用、无则退化为 identity no-op**(`volatile()` 自 schemastery 3.18.3 起才有,0.1.5 线锁在 3.18.2)。**故意不手写 `meta.volatile = true`**——那会绕过 schemastery 自身的 `validateVolatileSchema` 校验,产出一个它自己都不认的 schema。
|
|
28
|
+
- **0.1.7 以「活引用」交付配置值。** 该线把 volatile 字段以 `{get(): T}` 形式交给消费方;不解包则 `config.regions`、`value.accounts[region]`、`config.authFile` 静默变成对象或 `undefined`,表现为「设置明明写了却读不到」。更隐蔽的是**展开一个活引用得到的是 `{get: <function>}` 而不是值**——卡片「写一个区域、保留另一个」的合并会因此**丢掉兄弟区域并把函数泄进设置文档**。新增 `unwrapVolatile()` / `unwrapVolatileDeep()` 并在所有读取与合并路径上解包,同时监听 `loader/volatile-update` 在每次写入后重读选择。
|
|
29
|
+
- **第 5 条(图标)会让整个客户端包挂掉**:两条线 primitives 的图标名不重叠(`IconChevronDownOutline14` vs `IconChevronDownOutlineRegular`),**没有任何一个静态 import 能同时服务两边**——静态导入 0.1.5 的名字会让 0.1.7 上的客户端包解析失败,整个卡片随之消失。折叠箭头改为**纯 CSS caret**(`border` + `rotate`),与版本无关。
|
|
30
|
+
- **设置写入改为「写入后回读校验」**:`set()` 的 promise resolve **不代表值已落盘**(0.1.7 上被拒绝的写入会重新加载 Host 状态然后正常返回,0.1.5 上则可能被文件占用丢弃)。四处写入(账号选择、账号重扫、区域开关、模型目录)统一走 `writeSettingsField()`:写入后回读,未落盘即抛错并在卡片上明确显示,而不是「点了没反应」。0.1.7 的 `set()` 还会返回显式布尔值,`false` 同样按拒绝处理。
|
|
31
|
+
- **卡片的 `view` 属性**:0.1.7 的插件管理器通过 owner props 向每个配置条目索取两种视图(`summary` 一句话简介 / `page` 带保存控件的完整表单)。卡片接受该属性并在 `page` 下默认展开——否则在 0.1.7 的插件页里卡片会是折叠的一行。
|
|
32
|
+
- **开发环境的 schemastery 从 3.18.2 提到 3.18.4**(`pnpm-workspace.yaml` 的 override,与 `devDependencies` 对齐)。此前 dev 树锁在 3.18.2,那里没有 `volatile()`,`asVolatile()` 退化为 no-op——**于是 volatile 真正生效的那条路径(每个 0.1.7 用户都会走的那条)在本地从未被执行过**,这类缺陷可以同时躲过评审与 CI。这与 workbuddy 记录的教训同源。
|
|
33
|
+
|
|
34
|
+
### Tests
|
|
35
|
+
|
|
36
|
+
测试总数 282 → 310。
|
|
37
|
+
|
|
38
|
+
- **新增 `tests/client-activation.spec.tsx`(3 例,本次最关键的一组)**:用真实的 cordis `Context` **启动真实的客户端入口模块**,分别对 0.1.7 形态(有 `configForms`、**无** `settingsScope`)、0.1.5 形态(有 `settingsScope`、无 `configForms`)、以及**两者都没有**的形态断言 fiber 到达 `ACTIVE`、槽位注册齐全、scope 取自正确的服务。之所以能直接导入真实入口,是因为它运行期只依赖 React 与本地文件,所有 DSH 包都是**类型导入**、构建时即被擦除。
|
|
39
|
+
- 此前 `client-fallback.spec.ts` 抓不到这个缺陷:它**手工镜像**入口函数体,因此验证的是「思路」而**从不执行真实的 `inject` 数组**——而恰恰是那个数组让 fiber 卡在 PENDING。
|
|
40
|
+
- **变异验证**:把 `inject` 改回 `['slots','locale','settingsScope']`,0.1.7 与「无设置面」两例立即变红(fiber 停在 0/1,永远到不了 `ACTIVE`),0.1.5 那例仍绿——精确复现了 issue 报的现象。
|
|
41
|
+
- **新增 `tests/dsh-017-compat.spec.ts`(13 例)**:活引用的单层/深层解包、数组与嵌套、**不就地改写调用方对象**;`regionEnabledOf` / `regionStateOf` / `regionEnabled` 穿透活引用读值;合并时**保留兄弟区域且不泄露函数**;`asVolatile()` 的两条分支按运行时能力确定性断言;以及**宿主端 `configure()` 优先于 `installSection()`**(用一个只有 `configure` 的真 Service 装配,断言走的是 `configure({auto:true})` 且没有 `installSection` 报错)。
|
|
42
|
+
- **变异验证**:把 `configure` 探测改回无保护裸调 `installSection` → 1 条立即变红;把 `nextRegionSlots` 的深解包去掉 → 1 条立即变红。
|
|
43
|
+
- `client-fallback.spec.ts` 的镜像同步更新,并补 2 例:**两条线都提供时 `configForms` 优先**(0.1.7 的写入闸门只认它),以及 **`configForms` 缺席时回落 `settingsScope.bind()`**。
|
|
44
|
+
- **`card-region-switch.spec.tsx` 新增 8 例**(渲染真组件、点真按钮):穿透活引用读区域开关;合并时**保留兄弟区域且不泄露函数**;Host 明确拒绝(`set()` 返回 `false`)与**「接受了但没落盘」**(`set()` 返回 `true` 而文档未变)两种失败都必须显式报错;0.1.5 的 `void` 返回视为成功;`view: 'page'` 时默认展开、无 `view` 时默认折叠;无设置面时渲染为只读。
|
|
45
|
+
- **变异验证**:去掉 `regionsMapOf` 的解包 → 1 条失败;去掉 `view` 判断 → 1 条失败;去掉 `false` 判断 → 0 条失败(回读校验兜住了,说明两层防护确实互补);去掉回读校验 → 1 条失败;**两层都去掉 → 1 条失败**。
|
|
46
|
+
- 顺带移除了该文件对 `dsh-client-ui-primitives` 的整包 `vi.mock`:图标已改纯 CSS,不再需要这个桩。
|
|
47
|
+
|
|
48
|
+
**双版本验证**:同一份代码在 schemastery **3.18.4**(volatile 生效)与 **3.18.2**(no-op 分支)下**均为 310 通过**。
|
|
49
|
+
|
|
3
50
|
## 2.1.0 (2026-09-24)
|
|
4
51
|
|
|
5
52
|
### Features
|
package/README.en.md
CHANGED
|
@@ -94,6 +94,25 @@ npm install dsh-connect-trae
|
|
|
94
94
|
|
|
95
95
|
Restart the DSH process after install/update/uninstall.
|
|
96
96
|
|
|
97
|
+
## DSH version compatibility
|
|
98
|
+
|
|
99
|
+
**One build serves both the DSH 0.1.5 and 0.1.7 lines** — no per-version package.
|
|
100
|
+
|
|
101
|
+
The two lines differ in their settings machinery, and the plugin probes for capability at runtime instead of assuming either:
|
|
102
|
+
|
|
103
|
+
| | 0.1.5 line | 0.1.7 line |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| Client settings service | `settingsScope` | `configForms` |
|
|
106
|
+
| Config card slots | `settings.plugin.item` | `plugins.bundle.config` / `plugins.row.config` |
|
|
107
|
+
| Host registration | `installSection()` | `configure({auto}, owner)` |
|
|
108
|
+
| Schema writable marker | not needed | `volatile()` required |
|
|
109
|
+
| Primitives icon names | `…Outline14` | `…OutlineRegular` |
|
|
110
|
+
|
|
111
|
+
Two decisions matter most:
|
|
112
|
+
|
|
113
|
+
- **`inject` declares only the services BOTH lines provide** (`slots` / `locale`); the settings surface is probed with `ctx.get()`. Cordis' dependency gate is hard — any `inject` entry the running line does not provide keeps `apply()` from ever running (0.1.7 removed `settingsScope`, which is why 2.1.0 and earlier sat at `pending (waiting for service: settingsScope)` on that line).
|
|
114
|
+
- **The collapse caret is pure CSS**, with no static icon import: the two lines' icon names do not overlap, so any static import fails to resolve on one of them.
|
|
115
|
+
|
|
97
116
|
## Windows notes
|
|
98
117
|
|
|
99
118
|
- **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.
|
package/README.md
CHANGED
|
@@ -96,6 +96,25 @@ npm install dsh-connect-trae
|
|
|
96
96
|
|
|
97
97
|
安装、更新或卸载 bundle 后,需要重启对应的 DSH 进程。
|
|
98
98
|
|
|
99
|
+
## DSH 版本兼容
|
|
100
|
+
|
|
101
|
+
**同一个构建同时服务 DSH 0.1.5 与 0.1.7 两条线**,无需按版本安装不同的包。
|
|
102
|
+
|
|
103
|
+
两条线的设置体系不同,插件在运行期按能力探测,而不是假定某一条:
|
|
104
|
+
|
|
105
|
+
| | 0.1.5 线 | 0.1.7 线 |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| 客户端设置服务 | `settingsScope` | `configForms` |
|
|
108
|
+
| 配置卡片槽位 | `settings.plugin.item` | `plugins.bundle.config` / `plugins.row.config` |
|
|
109
|
+
| 宿主端注册 | `installSection()` | `configure({auto}, owner)` |
|
|
110
|
+
| schema 可写声明 | 无需 | 必须标 `volatile()` |
|
|
111
|
+
| primitives 图标名 | `…Outline14` | `…OutlineRegular` |
|
|
112
|
+
|
|
113
|
+
两处关键做法:
|
|
114
|
+
|
|
115
|
+
- **`inject` 只声明两条线都有的服务**(`slots` / `locale`),设置面用 `ctx.get()` 软探测。Cordis 的依赖闸门是硬闸——`inject` 里任一服务在运行线上不存在,`apply()` 就永远不会执行(0.1.7 上 `settingsScope` 已被移除,这正是 2.1.0 及更早版本在 0.1.7 上卡在 `pending (waiting for service: settingsScope)` 的原因)。
|
|
116
|
+
- **折叠箭头用纯 CSS**,不静态导入任何图标:两条线的图标名不重叠,静态导入必然在其中一条线上解析失败。
|
|
117
|
+
|
|
99
118
|
## Windows 说明
|
|
100
119
|
|
|
101
120
|
- **账号数据目录**:插件读取 `%APPDATA%\Trae CN` / `%APPDATA%\TRAE SOLO CN` 下的 `User\globalStorage\storage.json`(与安装目录无关)。目录名与 macOS 一致,无需额外配置;若目录名对不上,可用插件配置项 `authFile` + `edition` 直接指定完整路径。
|
package/lib/client.js
CHANGED
|
@@ -5,7 +5,6 @@ window.__ModuleLoader__.load({
|
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
7
|
let react = require("react");
|
|
8
|
-
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
8
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
9
|
//#region src/status-paths.ts
|
|
11
10
|
/** Plugin-owned usage endpoint consumed by its browser half. */
|
|
@@ -31,6 +30,42 @@ window.__ModuleLoader__.load({
|
|
|
31
30
|
return `${path}?${TRAE_REGION_PARAM}=${region}`;
|
|
32
31
|
}
|
|
33
32
|
/**
|
|
33
|
+
* Peel ONE `{get(): T}` live reference, the shape DSH 0.1.7 delivers a
|
|
34
|
+
* volatile-marked settings field as (see {@link unwrapVolatileDeep}).
|
|
35
|
+
*/
|
|
36
|
+
function unwrapVolatile(value) {
|
|
37
|
+
if (value !== null && typeof value === "object" && typeof value.get === "function") return value.get();
|
|
38
|
+
return value;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Deep copy of a value with every `{get(): T}` live reference replaced by the
|
|
42
|
+
* value it resolves to.
|
|
43
|
+
*
|
|
44
|
+
* DSH 0.1.7 hands volatile-marked fields back as live references, and a live
|
|
45
|
+
* reference is still `typeof === 'object'` — so it passes a naive object check
|
|
46
|
+
* and every lookup on it is `undefined`. Worse, spreading one (`{ ...ref }`)
|
|
47
|
+
* does NOT read the field: it produces `{ get: <function> }`. Any merge that
|
|
48
|
+
* spreads a resolved field to preserve its siblings — the card's "write one
|
|
49
|
+
* region, keep the other" write, or the account map's spread — would otherwise
|
|
50
|
+
* DROP every sibling and leak a function into the document.
|
|
51
|
+
*
|
|
52
|
+
* Both halves therefore unwrap before touching a resolved field. This lives in
|
|
53
|
+
* the node-free host↔client bridge because the browser half needs it too.
|
|
54
|
+
*
|
|
55
|
+
* Non-reference values are recursed into so a nested volatile field is caught
|
|
56
|
+
* as well; arrays and objects are rebuilt rather than mutated, so the caller's
|
|
57
|
+
* value is never touched.
|
|
58
|
+
*/
|
|
59
|
+
function unwrapVolatileDeep(value) {
|
|
60
|
+
if (value === null || typeof value !== "object") return value;
|
|
61
|
+
if (typeof value.get === "function") return unwrapVolatileDeep(value.get());
|
|
62
|
+
if (Array.isArray(value)) return value.map((entry) => unwrapVolatileDeep(entry));
|
|
63
|
+
const source = value;
|
|
64
|
+
const out = {};
|
|
65
|
+
for (const key of Object.keys(source)) out[key] = unwrapVolatileDeep(source[key]);
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
34
69
|
* Build the next `regions` settings value for the card's save. The write
|
|
35
70
|
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
36
71
|
* is carried over untouched, so switching accounts never clobbers the other
|
|
@@ -38,8 +73,9 @@ window.__ModuleLoader__.load({
|
|
|
38
73
|
* from an empty document.
|
|
39
74
|
*/
|
|
40
75
|
function nextRegionSlots(regions, region, slot) {
|
|
76
|
+
const unwrapped = unwrapVolatileDeep(regions);
|
|
41
77
|
return {
|
|
42
|
-
...typeof
|
|
78
|
+
...typeof unwrapped === "object" && unwrapped !== null && !Array.isArray(unwrapped) ? unwrapped : {},
|
|
43
79
|
[region]: slot
|
|
44
80
|
};
|
|
45
81
|
}
|
|
@@ -50,17 +86,23 @@ window.__ModuleLoader__.load({
|
|
|
50
86
|
* where the map was expected was a real shipped bug — the lookup then read
|
|
51
87
|
* `section['cn']` (absent), so the card's checkbox reported `true` forever and
|
|
52
88
|
* clicking it appeared to do nothing even though the write succeeded.
|
|
89
|
+
*
|
|
90
|
+
* Unwraps live references first: on DSH 0.1.7 the `regions` field arrives as a
|
|
91
|
+
* `{get(): T}` reference, which passes the `typeof === 'object'` check below
|
|
92
|
+
* and would otherwise be returned as if it were the map — making every region
|
|
93
|
+
* read back as absent (and the enabled flag read as "on" forever).
|
|
53
94
|
*/
|
|
54
95
|
function regionsMapOf(value) {
|
|
55
|
-
|
|
56
|
-
|
|
96
|
+
const unwrapped = unwrapVolatileDeep(value);
|
|
97
|
+
if (typeof unwrapped !== "object" || unwrapped === null || Array.isArray(unwrapped)) return {};
|
|
98
|
+
const record = unwrapped;
|
|
57
99
|
const nested = record["regions"];
|
|
58
100
|
if (typeof nested === "object" && nested !== null && !Array.isArray(nested)) return nested;
|
|
59
101
|
return record;
|
|
60
102
|
}
|
|
61
103
|
/** One region's stored slot as a plain object; any other shape reads as empty. */
|
|
62
104
|
function regionSlotOf(value, region) {
|
|
63
|
-
const slot = regionsMapOf(value)[region];
|
|
105
|
+
const slot = unwrapVolatile(regionsMapOf(value)[region]);
|
|
64
106
|
return typeof slot === "object" && slot !== null && !Array.isArray(slot) ? slot : {};
|
|
65
107
|
}
|
|
66
108
|
/**
|
|
@@ -123,7 +165,13 @@ window.__ModuleLoader__.load({
|
|
|
123
165
|
.dsm-plugin-card-head{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}
|
|
124
166
|
.dsm-plugin-card-title{color:var(--dsw-alias-label-primary,#e6e6e6);font-size:15px;font-weight:600;line-height:1.4}
|
|
125
167
|
.dsm-plugin-card-description{color:var(--dsw-alias-label-tertiary,#999);font-size:13px;line-height:1.5}
|
|
126
|
-
|
|
168
|
+
/* Pure-CSS caret: the host primitives' chevron icon names differ per DSH line
|
|
169
|
+
(0.1.5 IconChevronDownOutline14 vs 0.1.7 IconChevronDownOutlineRegular),
|
|
170
|
+
so no static import can serve both — importing the 0.1.5 name makes the
|
|
171
|
+
client bundle fail to resolve on 0.1.7, taking the whole card down. A border
|
|
172
|
+
caret in the plugin's own CSS is version-proof. */
|
|
173
|
+
.dsm-plugin-card-chevron{color:var(--dsw-alias-label-tertiary,#999);flex:none;width:16px;height:16px;position:relative;transition:transform .16s}
|
|
174
|
+
.dsm-plugin-card-chevron::before{content:"";display:block;position:absolute;left:4px;top:5px;width:7px;height:7px;border-right:1.6px solid currentColor;border-bottom:1.6px solid currentColor;transform:rotate(45deg)}
|
|
127
175
|
.dsm-plugin-card-chevron-open{transform:rotate(180deg)}
|
|
128
176
|
.dsm-plugin-card-body{border-top:1px solid var(--dsw-alias-border-l2,#36373b);margin:0 16px;padding:0 0 8px}
|
|
129
177
|
.dsm-plugin-card-icon{width:32px;height:32px;flex:none;border-radius:7px}
|
|
@@ -230,11 +278,49 @@ window.__ModuleLoader__.load({
|
|
|
230
278
|
*/
|
|
231
279
|
const POLL_INTERVAL_MS = 6e4;
|
|
232
280
|
const TRAE_GITHUB_URL = "https://github.com/dingminhua/dsh-connect-trae";
|
|
233
|
-
/**
|
|
281
|
+
/**
|
|
282
|
+
* Read the per-region account selections out of the settings snapshot.
|
|
283
|
+
*
|
|
284
|
+
* Deep-unwraps first: on DSH 0.1.7 a volatile field arrives as a `{get(): T}`
|
|
285
|
+
* live reference, which passes the `typeof === 'object'` check below and would
|
|
286
|
+
* be returned as if it were the map. Every lookup on it is then `undefined`,
|
|
287
|
+
* and the card's merge (`{ ...configured, [region]: id }`) would spread a
|
|
288
|
+
* reference into `{get: <function>}` — dropping the other region's selection
|
|
289
|
+
* and leaking a function into the settings document.
|
|
290
|
+
*/
|
|
234
291
|
function configuredAccountsOf(configured) {
|
|
235
|
-
const accounts = configured?.accounts;
|
|
292
|
+
const accounts = unwrapVolatileDeep(configured)?.accounts;
|
|
236
293
|
return typeof accounts === "object" && accounts !== null ? accounts : {};
|
|
237
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Write one settings field and confirm the value actually landed.
|
|
297
|
+
*
|
|
298
|
+
* `settingsScope.set()` / `configForms.set()` resolving is NOT proof that
|
|
299
|
+
* anything was stored. On DSH 0.1.7 a write can be accepted by the transport
|
|
300
|
+
* and still not materialize — a rejected write reloads Host state and merely
|
|
301
|
+
* RETURNS, so the caller's `await` succeeds while the document is unchanged.
|
|
302
|
+
* The 0.1.7 form also answers with an explicit boolean for exactly this reason.
|
|
303
|
+
*
|
|
304
|
+
* Either way the caller must not report success on an unpersisted write: the
|
|
305
|
+
* user would see the control flip and then silently revert.
|
|
306
|
+
*
|
|
307
|
+
* @throws {TraeSettingsWriteError} when the write was refused or did not land.
|
|
308
|
+
*/
|
|
309
|
+
var TraeSettingsWriteError = class extends Error {
|
|
310
|
+
constructor(field, detail) {
|
|
311
|
+
super(detail === void 0 || detail === "" ? `trae: settings field "${field}" was not persisted by the settings write` : `trae: settings field "${field}" was not persisted by the settings write (${detail})`);
|
|
312
|
+
this.name = "TraeSettingsWriteError";
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
async function writeSettingsField(scope, field, value, landed) {
|
|
316
|
+
if (await scope.set(field, value) === false) throw new TraeSettingsWriteError(field, "the Host refused the write");
|
|
317
|
+
if (!landed(unwrapVolatileDeep(scope.getSnapshot().value))) throw new TraeSettingsWriteError(field);
|
|
318
|
+
}
|
|
319
|
+
/** Read one region's stored `regions` slot out of an unwrapped settings value. */
|
|
320
|
+
function regionSlotsOf(value) {
|
|
321
|
+
const regions = value?.regions;
|
|
322
|
+
return typeof regions === "object" && regions !== null ? regions : {};
|
|
323
|
+
}
|
|
238
324
|
/** Inject the shared card CSS once. */
|
|
239
325
|
if (typeof document !== "undefined") {
|
|
240
326
|
const cssId = "dsh-connect-trae/client.css";
|
|
@@ -271,9 +357,9 @@ window.__ModuleLoader__.load({
|
|
|
271
357
|
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)" };
|
|
272
358
|
}
|
|
273
359
|
/** Render Trae sign-in state and the total usage summary as one expandable card. */
|
|
274
|
-
function TraeUsageCard({ t, settingsScope }) {
|
|
360
|
+
function TraeUsageCard({ t, settingsScope, view }) {
|
|
275
361
|
if (t === void 0) throw new Error("Trae usage card requires its translation function");
|
|
276
|
-
const [open, setOpen] = (0, react.useState)(
|
|
362
|
+
const [open, setOpen] = (0, react.useState)(view === "page");
|
|
277
363
|
/** The region whose tab is on screen; each tab is its own provider stack. */
|
|
278
364
|
const [activeRegion, setActiveRegion] = (0, react.useState)("cn");
|
|
279
365
|
/** Last-known usage per region, so tab dots survive tab switches. */
|
|
@@ -304,6 +390,12 @@ window.__ModuleLoader__.load({
|
|
|
304
390
|
const [claiming, setClaiming] = (0, react.useState)(false);
|
|
305
391
|
/** Last claim refusal, shown until the next successful refresh. */
|
|
306
392
|
const [claimError, setClaimError] = (0, react.useState)(void 0);
|
|
393
|
+
/**
|
|
394
|
+
* A refused or unpersisted settings write, surfaced instead of silently
|
|
395
|
+
* reverting. On 0.1.7 a rejected write resolves normally, so without this
|
|
396
|
+
* the control would flip and then quietly snap back on the next snapshot.
|
|
397
|
+
*/
|
|
398
|
+
const [writeError, setWriteError] = (0, react.useState)(void 0);
|
|
307
399
|
const mounted = (0, react.useRef)(true);
|
|
308
400
|
(0, react.useEffect)(() => {
|
|
309
401
|
mounted.current = true;
|
|
@@ -399,6 +491,7 @@ window.__ModuleLoader__.load({
|
|
|
399
491
|
]);
|
|
400
492
|
const rescanAccounts = async () => {
|
|
401
493
|
setBusy(true);
|
|
494
|
+
setWriteError(void 0);
|
|
402
495
|
try {
|
|
403
496
|
const response = await fetch(withTraeRegion(TRAE_ACCOUNTS_REFRESH_PATH, activeRegion), {
|
|
404
497
|
method: "POST",
|
|
@@ -409,11 +502,13 @@ window.__ModuleLoader__.load({
|
|
|
409
502
|
if (!response.ok || !Array.isArray(body.accounts)) throw new Error(`HTTP ${response.status}`);
|
|
410
503
|
const selected = body.accounts.find((account) => account.selected)?.id;
|
|
411
504
|
const configured = configuredAccountsOf(settingsScope?.getSnapshot().value);
|
|
412
|
-
if (selected !== void 0 && selected !== configured[activeRegion] && settingsScope
|
|
505
|
+
if (selected !== void 0 && selected !== configured[activeRegion] && settingsScope !== void 0 && settingsScope.getSnapshot().writable === true) await writeSettingsField(settingsScope, "accounts", {
|
|
413
506
|
...configured,
|
|
414
507
|
[activeRegion]: selected
|
|
415
|
-
});
|
|
508
|
+
}, (readBack) => configuredAccountsOf(readBack)[activeRegion] === selected);
|
|
416
509
|
await refreshUsage(activeRegion);
|
|
510
|
+
} catch (error) {
|
|
511
|
+
if (mounted.current) setWriteError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
417
512
|
} finally {
|
|
418
513
|
if (mounted.current) setBusy(false);
|
|
419
514
|
}
|
|
@@ -421,13 +516,15 @@ window.__ModuleLoader__.load({
|
|
|
421
516
|
const switchAccount = async (accountId) => {
|
|
422
517
|
if (settingsScope === void 0) return;
|
|
423
518
|
setSwitchingAccount(true);
|
|
519
|
+
setWriteError(void 0);
|
|
424
520
|
try {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
...configured,
|
|
521
|
+
await writeSettingsField(settingsScope, "accounts", {
|
|
522
|
+
...configuredAccountsOf(settingsScope.getSnapshot().value),
|
|
428
523
|
[activeRegion]: accountId
|
|
429
|
-
});
|
|
524
|
+
}, (readBack) => configuredAccountsOf(readBack)[activeRegion] === accountId);
|
|
430
525
|
await refreshUsage(activeRegion);
|
|
526
|
+
} catch (error) {
|
|
527
|
+
if (mounted.current) setWriteError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
431
528
|
} finally {
|
|
432
529
|
if (mounted.current) setSwitchingAccount(false);
|
|
433
530
|
}
|
|
@@ -474,8 +571,11 @@ window.__ModuleLoader__.load({
|
|
|
474
571
|
const toggleRegion = async (item, enabled) => {
|
|
475
572
|
if (settingsScope === void 0 || settingsScope.getSnapshot().writable !== true) return;
|
|
476
573
|
setTogglingRegion(item);
|
|
574
|
+
setWriteError(void 0);
|
|
477
575
|
try {
|
|
478
|
-
await settingsScope
|
|
576
|
+
await writeSettingsField(settingsScope, "regions", nextRegionEnabled(settingsScope.getSnapshot().value, item, enabled), (readBack) => regionSlotsOf(readBack)[item] !== void 0 && regionSlotsOf(readBack)[item].enabled === enabled);
|
|
577
|
+
} catch (error) {
|
|
578
|
+
if (mounted.current) setWriteError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
479
579
|
} finally {
|
|
480
580
|
if (mounted.current) setTogglingRegion(void 0);
|
|
481
581
|
}
|
|
@@ -523,7 +623,7 @@ window.__ModuleLoader__.load({
|
|
|
523
623
|
if (mounted.current) setBusy(false);
|
|
524
624
|
}
|
|
525
625
|
};
|
|
526
|
-
const settingsValue = settingsScope?.getSnapshot().value;
|
|
626
|
+
const settingsValue = unwrapVolatileDeep(settingsScope?.getSnapshot().value);
|
|
527
627
|
const region = activeRegion;
|
|
528
628
|
const configuredRegions = typeof settingsValue === "object" && settingsValue !== null && typeof settingsValue.regions === "object" && settingsValue.regions !== null ? settingsValue.regions : {};
|
|
529
629
|
const regionSlot = configuredRegions[region];
|
|
@@ -594,9 +694,10 @@ window.__ModuleLoader__.load({
|
|
|
594
694
|
const saveModels = async () => {
|
|
595
695
|
if (settingsScope === void 0) return;
|
|
596
696
|
setSaving(true);
|
|
697
|
+
setWriteError(void 0);
|
|
597
698
|
try {
|
|
598
699
|
if (status.status !== "signed-in") return;
|
|
599
|
-
|
|
700
|
+
const nextSlot = {
|
|
600
701
|
enabled: regionOn(activeRegion),
|
|
601
702
|
lastCatalog: visibleModels.map((model) => ({
|
|
602
703
|
...model,
|
|
@@ -605,9 +706,15 @@ window.__ModuleLoader__.load({
|
|
|
605
706
|
enabledModelIds: [...activeEnabledIds],
|
|
606
707
|
imageModelIds: [...activeImageIds].filter((id) => activeEnabledIds.has(id)),
|
|
607
708
|
contextBudgets: activeContextBudgets
|
|
608
|
-
}
|
|
709
|
+
};
|
|
710
|
+
await writeSettingsField(settingsScope, "regions", nextRegionSlots(configuredRegions, activeRegion, nextSlot), (readBack) => {
|
|
711
|
+
const ids = regionSlotsOf(readBack)[activeRegion]?.enabledModelIds;
|
|
712
|
+
return Array.isArray(ids) && ids.length === nextSlot.enabledModelIds.length && nextSlot.enabledModelIds.every((id) => ids.includes(id));
|
|
713
|
+
});
|
|
609
714
|
discardModels();
|
|
610
715
|
await refreshUsage(activeRegion);
|
|
716
|
+
} catch (error) {
|
|
717
|
+
if (mounted.current) setWriteError(error instanceof Error ? error.message : t("row.requestFailed"));
|
|
611
718
|
} finally {
|
|
612
719
|
if (mounted.current) setSaving(false);
|
|
613
720
|
}
|
|
@@ -642,8 +749,7 @@ window.__ModuleLoader__.load({
|
|
|
642
749
|
}),
|
|
643
750
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
644
751
|
"aria-hidden": "true",
|
|
645
|
-
className: `dsm-plugin-card-chevron${open ? " dsm-plugin-card-chevron-open" : ""}
|
|
646
|
-
children: (0, react.createElement)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutline14, { size: 14 })
|
|
752
|
+
className: `dsm-plugin-card-chevron${open ? " dsm-plugin-card-chevron-open" : ""}`
|
|
647
753
|
})
|
|
648
754
|
]
|
|
649
755
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -695,6 +801,11 @@ window.__ModuleLoader__.load({
|
|
|
695
801
|
className: "dsm-trae-tab-hint",
|
|
696
802
|
children: t("row.tabHint")
|
|
697
803
|
}),
|
|
804
|
+
writeError === void 0 ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
805
|
+
className: "dsm-trae-usage-error",
|
|
806
|
+
role: "alert",
|
|
807
|
+
children: t("row.settingsWriteFailed", { message: writeError })
|
|
808
|
+
}),
|
|
698
809
|
regionOn(activeRegion) ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
699
810
|
className: "dsm-trae-tab-off-notice",
|
|
700
811
|
role: "status",
|
|
@@ -1069,6 +1180,7 @@ window.__ModuleLoader__.load({
|
|
|
1069
1180
|
"row.tabSwitchHint": "Uncheck to switch this provider off. Its models disappear from the DSH model picker; its account, usage, and model settings are kept and return when you check it again.",
|
|
1070
1181
|
"row.tabSwitchAria": "Offer the {region} provider to DSH",
|
|
1071
1182
|
"row.tabOffNotice": "This provider is switched off: none of its models are offered to DSH. Your account, usage, and model settings are kept — check the box above the tab to bring it back.",
|
|
1183
|
+
"row.settingsWriteFailed": "The setting was not saved: {message}",
|
|
1072
1184
|
"row.signedOut": "Not signed in",
|
|
1073
1185
|
"row.signedOutHint": "Sign in once in the Trae desktop app; this plugin follows that sign-in automatically.",
|
|
1074
1186
|
"row.searchedTitle": "Paths checked",
|
|
@@ -1146,6 +1258,7 @@ window.__ModuleLoader__.load({
|
|
|
1146
1258
|
"row.tabSwitchHint": "取消勾选即关闭该供应商:它的模型不再出现在 DSH 模型选择器里;账号、用量与模型设置都会保留,重新勾选即恢复。",
|
|
1147
1259
|
"row.tabSwitchAria": "是否向 DSH 提供{region}供应商",
|
|
1148
1260
|
"row.tabOffNotice": "该供应商已关闭:它的模型不会提供给 DSH。账号、用量与模型设置均已保留——勾选上方复选框即可恢复。",
|
|
1261
|
+
"row.settingsWriteFailed": "设置未能保存:{message}",
|
|
1149
1262
|
"row.signedOut": "未登录",
|
|
1150
1263
|
"row.signedOutHint": "在 Trae 桌面 App 里登录一次即可,插件会自动跟随当前登录的账号。",
|
|
1151
1264
|
"row.searchedTitle": "已检查的路径",
|
|
@@ -1216,12 +1329,17 @@ window.__ModuleLoader__.load({
|
|
|
1216
1329
|
//#region src/client/index.tsx
|
|
1217
1330
|
/** Stable browser-plugin name. */
|
|
1218
1331
|
const name = "dsh-connect-trae-client";
|
|
1219
|
-
/**
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1332
|
+
/**
|
|
1333
|
+
* Client services required by the Plugin configuration contribution.
|
|
1334
|
+
*
|
|
1335
|
+
* Deliberately only the two services that exist on BOTH host lines. Cordis'
|
|
1336
|
+
* dependency gate is hard: any `inject` entry the running line does not provide
|
|
1337
|
+
* keeps `apply` from ever running at all — which is exactly how this plugin
|
|
1338
|
+
* ended up `pending (waiting for service: settingsScope)` on 0.1.7. Probing the
|
|
1339
|
+
* settings surface through `ctx.get()` (which returns undefined, never throws,
|
|
1340
|
+
* for an absent service) is what lets one build serve both lines.
|
|
1341
|
+
*/
|
|
1342
|
+
const inject = ["slots", "locale"];
|
|
1225
1343
|
/**
|
|
1226
1344
|
* Register card copy and the Trae card under Plugin configuration.
|
|
1227
1345
|
*
|
|
@@ -1234,6 +1352,8 @@ window.__ModuleLoader__.load({
|
|
|
1234
1352
|
* NOTE: the try/catch boundary of this function is mirrored (duplicated) in
|
|
1235
1353
|
* `tests/client-fallback.spec.ts`, because the real client entry imports
|
|
1236
1354
|
* browser-only DSH packages that cannot load in the Node test environment.
|
|
1355
|
+
* If you change the guarded body, the soft probe, or the per-slot
|
|
1356
|
+
* registration here, update that mirror too.
|
|
1237
1357
|
*/
|
|
1238
1358
|
function apply(ctx) {
|
|
1239
1359
|
try {
|
|
@@ -1243,16 +1363,36 @@ window.__ModuleLoader__.load({
|
|
|
1243
1363
|
en
|
|
1244
1364
|
}), "dsh-connect-trae: settings copy");
|
|
1245
1365
|
const t = ctx.locale.bind(namespace);
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1366
|
+
const softGet = (name) => ctx.get(name);
|
|
1367
|
+
let settingsScope;
|
|
1368
|
+
const forms = softGet("configForms");
|
|
1369
|
+
const legacy = softGet("settingsScope");
|
|
1370
|
+
if (forms !== void 0) {
|
|
1371
|
+
let ns = "trae";
|
|
1372
|
+
try {
|
|
1373
|
+
const served = (forms.describe().getSnapshot().view?.namespaces ?? []).find((entry) => entry.ns === "trae" || /trae/i.test(entry.ns));
|
|
1374
|
+
if (served !== void 0) ns = served.ns;
|
|
1375
|
+
} catch {}
|
|
1376
|
+
settingsScope = forms.get(ns);
|
|
1377
|
+
} else if (legacy !== void 0) settingsScope = legacy.bind({ namespace: "trae" });
|
|
1378
|
+
const registerCard = (slotName, key) => {
|
|
1379
|
+
try {
|
|
1380
|
+
ctx.slots.inject(slotName, () => ctx.slots.register({
|
|
1381
|
+
name: slotName,
|
|
1382
|
+
key,
|
|
1383
|
+
priority: 30,
|
|
1384
|
+
inject: () => settingsScope === void 0 ? { t } : {
|
|
1385
|
+
t,
|
|
1386
|
+
settingsScope
|
|
1387
|
+
}
|
|
1388
|
+
}, TraeUsageCard));
|
|
1389
|
+
} catch (error) {
|
|
1390
|
+
console.error(`[dsh-connect-trae] card slot "${slotName}" failed to register (host provider unaffected):`, error);
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
registerCard("plugins.bundle.config", "dsh-connect-trae");
|
|
1394
|
+
registerCard("plugins.row.config", "dsh-connect-trae#dsh-connect-trae");
|
|
1395
|
+
registerCard("settings.plugin.item", "trae");
|
|
1256
1396
|
} catch (error) {
|
|
1257
1397
|
console.error("[dsh-connect-trae] client card failed to load (host provider unaffected):", error);
|
|
1258
1398
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1435,6 +1435,31 @@ interface TraeWebSearchPath {
|
|
|
1435
1435
|
reason: 'missing' | 'unreadable' | 'invalid';
|
|
1436
1436
|
message?: string;
|
|
1437
1437
|
}
|
|
1438
|
+
/**
|
|
1439
|
+
* Peel ONE `{get(): T}` live reference, the shape DSH 0.1.7 delivers a
|
|
1440
|
+
* volatile-marked settings field as (see {@link unwrapVolatileDeep}).
|
|
1441
|
+
*/
|
|
1442
|
+
declare function unwrapVolatile<T>(value: T): T;
|
|
1443
|
+
/**
|
|
1444
|
+
* Deep copy of a value with every `{get(): T}` live reference replaced by the
|
|
1445
|
+
* value it resolves to.
|
|
1446
|
+
*
|
|
1447
|
+
* DSH 0.1.7 hands volatile-marked fields back as live references, and a live
|
|
1448
|
+
* reference is still `typeof === 'object'` — so it passes a naive object check
|
|
1449
|
+
* and every lookup on it is `undefined`. Worse, spreading one (`{ ...ref }`)
|
|
1450
|
+
* does NOT read the field: it produces `{ get: <function> }`. Any merge that
|
|
1451
|
+
* spreads a resolved field to preserve its siblings — the card's "write one
|
|
1452
|
+
* region, keep the other" write, or the account map's spread — would otherwise
|
|
1453
|
+
* DROP every sibling and leak a function into the document.
|
|
1454
|
+
*
|
|
1455
|
+
* Both halves therefore unwrap before touching a resolved field. This lives in
|
|
1456
|
+
* the node-free host↔client bridge because the browser half needs it too.
|
|
1457
|
+
*
|
|
1458
|
+
* Non-reference values are recursed into so a nested volatile field is caught
|
|
1459
|
+
* as well; arrays and objects are rebuilt rather than mutated, so the caller's
|
|
1460
|
+
* value is never touched.
|
|
1461
|
+
*/
|
|
1462
|
+
declare function unwrapVolatileDeep<T>(value: T): T;
|
|
1438
1463
|
/**
|
|
1439
1464
|
* Build the next `regions` settings value for the card's save. The write
|
|
1440
1465
|
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
@@ -1655,7 +1680,27 @@ declare function regionStateOf(config: Config, region: TraeRegion): TraeRegionSt
|
|
|
1655
1680
|
* disagree about a region's state.
|
|
1656
1681
|
*/
|
|
1657
1682
|
declare function regionEnabled(config: Config, region: TraeRegion): boolean;
|
|
1683
|
+
/**
|
|
1684
|
+
* Mark a schema's field as volatile on the DSH lines that support it.
|
|
1685
|
+
*
|
|
1686
|
+
* `volatile()` exists from schemastery 3.18.3 (the DSH 0.1.7 line, which is the
|
|
1687
|
+
* only line whose settings write gate reads the marker). Older pinning (3.18.2,
|
|
1688
|
+
* the 0.1.5 line) has no such method, and the schema must stay byte-identical
|
|
1689
|
+
* to the unmarked original there: hand-writing `meta.volatile = true` would
|
|
1690
|
+
* bypass schemastery's own `validateVolatileSchema` checks and produce a schema
|
|
1691
|
+
* no 0.1.5 consumer understands — so on that line this degrades to an identity
|
|
1692
|
+
* no-op.
|
|
1693
|
+
*
|
|
1694
|
+
* Without the marker, 0.1.7's settings write gate REJECTS every write with
|
|
1695
|
+
* `Plugin entry "trae" has no volatile fields` while the scope's `set()` still
|
|
1696
|
+
* resolves — so the card would look like it saved and silently revert.
|
|
1697
|
+
*
|
|
1698
|
+
* Exported so BOTH arms are testable on any machine: the capability is decided
|
|
1699
|
+
* by whichever schemastery the dependency tree resolves, so without a seam the
|
|
1700
|
+
* no-op arm would silently stop being exercised the moment the pin moved up.
|
|
1701
|
+
*/
|
|
1702
|
+
declare function asVolatile<S>(schema: S): S;
|
|
1658
1703
|
declare const Config: z<Config>;
|
|
1659
1704
|
declare function apply(ctx: Context, config: Config): void;
|
|
1660
1705
|
//#endregion
|
|
1661
|
-
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, REGION_GATEWAYS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, 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 TraeAdapter, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinClaim, 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 TraeRefreshDevice, type TraeRegion, type TraeRegionGateways, TraeRegionState, 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 TraeWebCheckinClaim, 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, fallbackModelsFor, hashTraeRawChatArg, identityHeaders, inject, legacyTraeOwnAuthPath, mergeTraeModelSources, name, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, pickTraeStorageIdentity, prepareSoloBody, probeTraeRawChatCapability, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, sanitizeCatalog, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStorageCandidates, traeWebUsage, withTraeRegion };
|
|
1706
|
+
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, REGION_GATEWAYS, type RawChatDelta, type RawChatMessage, type RawChatTool, SseDecoder, type SseEvent, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, 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 TraeAdapter, type TraeCachedModelConfig, TraeCatalog, type TraeChatResult, type TraeCheckinClaim, 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 TraeRefreshDevice, type TraeRegion, type TraeRegionGateways, TraeRegionState, 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 TraeWebCheckinClaim, type TraeWebCredits, type TraeWebUsage, type TraeWireModel, UnconfiguredTraeUpstreamClient, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyTraeRawChatFailure, createTraeAdapter, createTraeRawGateway, createTraeShim, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, discoveredCatalog, fallbackModelsFor, hashTraeRawChatArg, identityHeaders, inject, legacyTraeOwnAuthPath, mergeTraeModelSources, name, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, pickTraeStorageIdentity, prepareSoloBody, probeTraeRawChatCapability, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, sanitizeCatalog, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStorageCandidates, traeWebUsage, unwrapVolatile, unwrapVolatileDeep, withTraeRegion };
|
package/lib/index.js
CHANGED
|
@@ -3269,6 +3269,42 @@ function regionOfTraeStatusUrl(url) {
|
|
|
3269
3269
|
return TRAE_REGIONS.includes(value) ? value : void 0;
|
|
3270
3270
|
}
|
|
3271
3271
|
/**
|
|
3272
|
+
* Peel ONE `{get(): T}` live reference, the shape DSH 0.1.7 delivers a
|
|
3273
|
+
* volatile-marked settings field as (see {@link unwrapVolatileDeep}).
|
|
3274
|
+
*/
|
|
3275
|
+
function unwrapVolatile(value) {
|
|
3276
|
+
if (value !== null && typeof value === "object" && typeof value.get === "function") return value.get();
|
|
3277
|
+
return value;
|
|
3278
|
+
}
|
|
3279
|
+
/**
|
|
3280
|
+
* Deep copy of a value with every `{get(): T}` live reference replaced by the
|
|
3281
|
+
* value it resolves to.
|
|
3282
|
+
*
|
|
3283
|
+
* DSH 0.1.7 hands volatile-marked fields back as live references, and a live
|
|
3284
|
+
* reference is still `typeof === 'object'` — so it passes a naive object check
|
|
3285
|
+
* and every lookup on it is `undefined`. Worse, spreading one (`{ ...ref }`)
|
|
3286
|
+
* does NOT read the field: it produces `{ get: <function> }`. Any merge that
|
|
3287
|
+
* spreads a resolved field to preserve its siblings — the card's "write one
|
|
3288
|
+
* region, keep the other" write, or the account map's spread — would otherwise
|
|
3289
|
+
* DROP every sibling and leak a function into the document.
|
|
3290
|
+
*
|
|
3291
|
+
* Both halves therefore unwrap before touching a resolved field. This lives in
|
|
3292
|
+
* the node-free host↔client bridge because the browser half needs it too.
|
|
3293
|
+
*
|
|
3294
|
+
* Non-reference values are recursed into so a nested volatile field is caught
|
|
3295
|
+
* as well; arrays and objects are rebuilt rather than mutated, so the caller's
|
|
3296
|
+
* value is never touched.
|
|
3297
|
+
*/
|
|
3298
|
+
function unwrapVolatileDeep(value) {
|
|
3299
|
+
if (value === null || typeof value !== "object") return value;
|
|
3300
|
+
if (typeof value.get === "function") return unwrapVolatileDeep(value.get());
|
|
3301
|
+
if (Array.isArray(value)) return value.map((entry) => unwrapVolatileDeep(entry));
|
|
3302
|
+
const source = value;
|
|
3303
|
+
const out = {};
|
|
3304
|
+
for (const key of Object.keys(source)) out[key] = unwrapVolatileDeep(source[key]);
|
|
3305
|
+
return out;
|
|
3306
|
+
}
|
|
3307
|
+
/**
|
|
3272
3308
|
* Build the next `regions` settings value for the card's save. The write
|
|
3273
3309
|
* targets ONLY the signed-in account's region slot; every other region's slot
|
|
3274
3310
|
* is carried over untouched, so switching accounts never clobbers the other
|
|
@@ -3276,8 +3312,9 @@ function regionOfTraeStatusUrl(url) {
|
|
|
3276
3312
|
* from an empty document.
|
|
3277
3313
|
*/
|
|
3278
3314
|
function nextRegionSlots(regions, region, slot) {
|
|
3315
|
+
const unwrapped = unwrapVolatileDeep(regions);
|
|
3279
3316
|
return {
|
|
3280
|
-
...typeof
|
|
3317
|
+
...typeof unwrapped === "object" && unwrapped !== null && !Array.isArray(unwrapped) ? unwrapped : {},
|
|
3281
3318
|
[region]: slot
|
|
3282
3319
|
};
|
|
3283
3320
|
}
|
|
@@ -3288,17 +3325,23 @@ function nextRegionSlots(regions, region, slot) {
|
|
|
3288
3325
|
* where the map was expected was a real shipped bug — the lookup then read
|
|
3289
3326
|
* `section['cn']` (absent), so the card's checkbox reported `true` forever and
|
|
3290
3327
|
* clicking it appeared to do nothing even though the write succeeded.
|
|
3328
|
+
*
|
|
3329
|
+
* Unwraps live references first: on DSH 0.1.7 the `regions` field arrives as a
|
|
3330
|
+
* `{get(): T}` reference, which passes the `typeof === 'object'` check below
|
|
3331
|
+
* and would otherwise be returned as if it were the map — making every region
|
|
3332
|
+
* read back as absent (and the enabled flag read as "on" forever).
|
|
3291
3333
|
*/
|
|
3292
3334
|
function regionsMapOf(value) {
|
|
3293
|
-
|
|
3294
|
-
|
|
3335
|
+
const unwrapped = unwrapVolatileDeep(value);
|
|
3336
|
+
if (typeof unwrapped !== "object" || unwrapped === null || Array.isArray(unwrapped)) return {};
|
|
3337
|
+
const record = unwrapped;
|
|
3295
3338
|
const nested = record["regions"];
|
|
3296
3339
|
if (typeof nested === "object" && nested !== null && !Array.isArray(nested)) return nested;
|
|
3297
3340
|
return record;
|
|
3298
3341
|
}
|
|
3299
3342
|
/** One region's stored slot as a plain object; any other shape reads as empty. */
|
|
3300
3343
|
function regionSlotOf(value, region) {
|
|
3301
|
-
const slot = regionsMapOf(value)[region];
|
|
3344
|
+
const slot = unwrapVolatile(regionsMapOf(value)[region]);
|
|
3302
3345
|
return typeof slot === "object" && slot !== null && !Array.isArray(slot) ? slot : {};
|
|
3303
3346
|
}
|
|
3304
3347
|
/**
|
|
@@ -3735,7 +3778,7 @@ const TRAE_SETTINGS_NS = "trae";
|
|
|
3735
3778
|
* picks (the same failure workbuddy fixed with its region split).
|
|
3736
3779
|
*/
|
|
3737
3780
|
function regionStateOf(config, region) {
|
|
3738
|
-
const stored = config.regions?.[region];
|
|
3781
|
+
const stored = unwrapVolatile(unwrapVolatile(config.regions)?.[region]);
|
|
3739
3782
|
if (stored !== void 0) return stored;
|
|
3740
3783
|
if (region !== "cn") return {};
|
|
3741
3784
|
return {
|
|
@@ -3756,6 +3799,29 @@ function regionStateOf(config, region) {
|
|
|
3756
3799
|
function regionEnabled(config, region) {
|
|
3757
3800
|
return regionStateOf(config, region).enabled !== false;
|
|
3758
3801
|
}
|
|
3802
|
+
/**
|
|
3803
|
+
* Mark a schema's field as volatile on the DSH lines that support it.
|
|
3804
|
+
*
|
|
3805
|
+
* `volatile()` exists from schemastery 3.18.3 (the DSH 0.1.7 line, which is the
|
|
3806
|
+
* only line whose settings write gate reads the marker). Older pinning (3.18.2,
|
|
3807
|
+
* the 0.1.5 line) has no such method, and the schema must stay byte-identical
|
|
3808
|
+
* to the unmarked original there: hand-writing `meta.volatile = true` would
|
|
3809
|
+
* bypass schemastery's own `validateVolatileSchema` checks and produce a schema
|
|
3810
|
+
* no 0.1.5 consumer understands — so on that line this degrades to an identity
|
|
3811
|
+
* no-op.
|
|
3812
|
+
*
|
|
3813
|
+
* Without the marker, 0.1.7's settings write gate REJECTS every write with
|
|
3814
|
+
* `Plugin entry "trae" has no volatile fields` while the scope's `set()` still
|
|
3815
|
+
* resolves — so the card would look like it saved and silently revert.
|
|
3816
|
+
*
|
|
3817
|
+
* Exported so BOTH arms are testable on any machine: the capability is decided
|
|
3818
|
+
* by whichever schemastery the dependency tree resolves, so without a seam the
|
|
3819
|
+
* no-op arm would silently stop being exercised the moment the pin moved up.
|
|
3820
|
+
*/
|
|
3821
|
+
function asVolatile(schema) {
|
|
3822
|
+
if (typeof schema.volatile === "function") return schema.volatile();
|
|
3823
|
+
return schema;
|
|
3824
|
+
}
|
|
3759
3825
|
const modelConfig = z.object({
|
|
3760
3826
|
id: z.string().required(),
|
|
3761
3827
|
name: z.string().required(),
|
|
@@ -3777,17 +3843,17 @@ const accountSelectionConfig = z.object({
|
|
|
3777
3843
|
ai: z.string().description("Selected international account id (never a token)")
|
|
3778
3844
|
});
|
|
3779
3845
|
const Config = z.object({
|
|
3780
|
-
authFile: z.string().description("Optional Trae storage.json path override"),
|
|
3781
|
-
edition: z.union([
|
|
3846
|
+
authFile: asVolatile(z.string().description("Optional Trae storage.json path override")),
|
|
3847
|
+
edition: asVolatile(z.union([
|
|
3782
3848
|
"auto",
|
|
3783
3849
|
"cn",
|
|
3784
3850
|
"sg",
|
|
3785
3851
|
"solo",
|
|
3786
3852
|
"solo-sg"
|
|
3787
|
-
]).default("auto").description("Trae edition hint"),
|
|
3853
|
+
]).default("auto").description("Trae edition hint")),
|
|
3788
3854
|
accountId: z.string().description("Deprecated: pre-split account selector, attributed to its own region"),
|
|
3789
|
-
accounts: accountSelectionConfig.description("Per-region account selections, keyed cn | ai"),
|
|
3790
|
-
regions: z.dict(regionStateConfig).default({}).description("Per-region model directory and selection, keyed cn | ai"),
|
|
3855
|
+
accounts: asVolatile(accountSelectionConfig.description("Per-region account selections, keyed cn | ai")),
|
|
3856
|
+
regions: asVolatile(z.dict(regionStateConfig).default({}).description("Per-region model directory and selection, keyed cn | ai")),
|
|
3791
3857
|
lastCatalog: z.array(modelConfig).description("Deprecated: pre-region-split CN model directory"),
|
|
3792
3858
|
enabledModelIds: z.array(z.string()).default([]).description("Deprecated: pre-region-split CN selection"),
|
|
3793
3859
|
contextBudgets: z.dict(z.number().step(1).min(1)).default({}).description("Deprecated: pre-region-split CN context budgets"),
|
|
@@ -3846,7 +3912,7 @@ function apply(ctx, config) {
|
|
|
3846
3912
|
*/
|
|
3847
3913
|
let legacyAccountRegion;
|
|
3848
3914
|
const effectiveAccountFor = (region, value) => {
|
|
3849
|
-
const explicit = value.accounts?.[region];
|
|
3915
|
+
const explicit = unwrapVolatile(value.accounts)?.[region];
|
|
3850
3916
|
if (explicit !== void 0) return explicit;
|
|
3851
3917
|
return legacyAccountRegion === region ? value.accountId : void 0;
|
|
3852
3918
|
};
|
|
@@ -3887,10 +3953,12 @@ function apply(ctx, config) {
|
|
|
3887
3953
|
try {
|
|
3888
3954
|
preferred = (await store.current())?.edition;
|
|
3889
3955
|
} catch {}
|
|
3890
|
-
const
|
|
3891
|
-
|
|
3956
|
+
const authFile = unwrapVolatile(config.authFile);
|
|
3957
|
+
const edition = unwrapVolatile(config.edition);
|
|
3958
|
+
const hint = (edition !== void 0 && edition !== "auto" ? edition : void 0) ?? preferred;
|
|
3959
|
+
return resolveTraeIdentity(authFile === void 0 ? traeStorageCandidates().filter((item) => item.source === "desktop" && (hint !== void 0 ? item.edition === hint : regionOfEdition(item.edition) === region)) : [{
|
|
3892
3960
|
edition: hint ?? (region === "ai" ? "sg" : "solo"),
|
|
3893
|
-
path:
|
|
3961
|
+
path: authFile,
|
|
3894
3962
|
source: "desktop"
|
|
3895
3963
|
}], hint ?? (region === "ai" ? "solo-sg" : "cn"));
|
|
3896
3964
|
};
|
|
@@ -3912,8 +3980,8 @@ function apply(ctx, config) {
|
|
|
3912
3980
|
};
|
|
3913
3981
|
const store = new TraeCredentialStore({
|
|
3914
3982
|
region,
|
|
3915
|
-
...config.authFile === void 0 ? {} : { storagePath: config.authFile },
|
|
3916
|
-
edition: config.edition ?? "auto",
|
|
3983
|
+
...unwrapVolatile(config.authFile) === void 0 ? {} : { storagePath: unwrapVolatile(config.authFile) },
|
|
3984
|
+
edition: unwrapVolatile(config.edition) ?? "auto",
|
|
3917
3985
|
refresh: async (credential) => refreshTraeCredential(credential, void 0, await refreshDeviceSafe())
|
|
3918
3986
|
});
|
|
3919
3987
|
const solo = new TraeSoloUpstreamClient({
|
|
@@ -4041,7 +4109,7 @@ function apply(ctx, config) {
|
|
|
4041
4109
|
const applySelection = (value) => {
|
|
4042
4110
|
for (const region of REGION_KEYS) {
|
|
4043
4111
|
const stack = stacks[region];
|
|
4044
|
-
stack.store.setSource(value.authFile, value.edition ?? "auto", effectiveAccountFor(region, value));
|
|
4112
|
+
stack.store.setSource(unwrapVolatile(value.authFile), unwrapVolatile(value.edition) ?? "auto", effectiveAccountFor(region, value));
|
|
4045
4113
|
stack.catalog.set(configuredModels(value, region));
|
|
4046
4114
|
stack.invalidateAdapter();
|
|
4047
4115
|
}
|
|
@@ -4070,7 +4138,18 @@ function apply(ctx, config) {
|
|
|
4070
4138
|
const legacyInstallSettingsSection = dshSettings.installSettingsSection;
|
|
4071
4139
|
if (typeof legacyInstallSettingsSection === "function") legacyInstallSettingsSection(ctx, TRAE_SETTINGS_NS, Config, config, sectionHooks);
|
|
4072
4140
|
else ctx.inject(["settings"], (settingsCtx) => {
|
|
4073
|
-
settingsCtx.settings
|
|
4141
|
+
const settings = settingsCtx.settings;
|
|
4142
|
+
if (typeof settings.configure === "function") {
|
|
4143
|
+
settings.configure({ auto: true }, ctx.fiber);
|
|
4144
|
+
return;
|
|
4145
|
+
}
|
|
4146
|
+
if (typeof settings.installSection === "function") {
|
|
4147
|
+
const entry = unwrapVolatileDeep(config);
|
|
4148
|
+
settings.installSection(ctx, TRAE_SETTINGS_NS, Config, entry, sectionHooks);
|
|
4149
|
+
}
|
|
4150
|
+
});
|
|
4151
|
+
ctx.on("loader/volatile-update", () => {
|
|
4152
|
+
applySelection(current());
|
|
4074
4153
|
});
|
|
4075
4154
|
let stopped = false;
|
|
4076
4155
|
ctx.effect(() => () => {
|
|
@@ -4153,4 +4232,4 @@ function apply(ctx, config) {
|
|
|
4153
4232
|
});
|
|
4154
4233
|
}
|
|
4155
4234
|
//#endregion
|
|
4156
|
-
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, REGION_GATEWAYS, SseDecoder, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, 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, TraeCatalog, TraeCredentialStore, TraeDelegatingUpstreamClient, TraeFallbackUpstreamClient, TraeGatedUpstreamClient, TraeRawCapabilityController, TraeRawCapabilityState, TraeRawChatUpstreamClient, TraeSoloBridge, TraeSoloRemoteCatalogClient, TraeSoloUpstreamClient, TraeUsageClient, UnconfiguredTraeUpstreamClient, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyTraeRawChatFailure, createTraeAdapter, createTraeRawGateway, createTraeShim, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, discoveredCatalog, fallbackModelsFor, hashTraeRawChatArg, identityHeaders, inject, legacyTraeOwnAuthPath, mergeTraeModelSources, name, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, pickTraeStorageIdentity, prepareSoloBody, probeTraeRawChatCapability, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, sanitizeCatalog, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStorageCandidates, traeWebUsage, withTraeRegion };
|
|
4235
|
+
export { Config, FALLBACK_TRAE_MODELS, FALLBACK_TRAE_MODELS_AI, REGION_GATEWAYS, SseDecoder, TRAE_AI_PROVIDER, TRAE_CHECKIN_PATH, TRAE_CN_AGENT_TASK_PATH, TRAE_CN_TITLE_PATH, TRAE_MODEL_DETAIL_FUNCTIONS, TRAE_MODEL_DETAIL_PATH, TRAE_PAY_BASE, TRAE_PROVIDER, TRAE_PROVIDERS, TRAE_PROVIDER_DISPLAY_NAMES, TRAE_RAW_CHAT_V1_PATH, TRAE_RAW_CHAT_V2_PATH, TRAE_REASONING_EFFORTS, TRAE_REGIONS, TRAE_REGION_PARAM, 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, TraeCatalog, TraeCredentialStore, TraeDelegatingUpstreamClient, TraeFallbackUpstreamClient, TraeGatedUpstreamClient, TraeRawCapabilityController, TraeRawCapabilityState, TraeRawChatUpstreamClient, TraeSoloBridge, TraeSoloRemoteCatalogClient, TraeSoloUpstreamClient, TraeUsageClient, UnconfiguredTraeUpstreamClient, apply, applyContextBudgets, applyImageSelection, applyReasoningEffort, asVolatile, bridgeTraeSoloStream, buildTraeAgentTaskBody, buildTraeCnHeaders, buildTraeFusionRawChatEnvelope, buildTraeModelDetailRequest, buildTraeRawChatDraft, buildTraeRawChatRuntimeConfig, classifyTraeRawChatFailure, createTraeAdapter, createTraeRawGateway, createTraeShim, decodeRawChatChunk, decodeTraeEvent, decryptTraeStorageValue, deriveCatalog, discoveredCatalog, fallbackModelsFor, hashTraeRawChatArg, identityHeaders, inject, legacyTraeOwnAuthPath, mergeTraeModelSources, name, nextRegionEnabled, nextRegionSlots, normalizeTraeCredential, normalizeTraeVersionCode, parseObservedModelConfig, parseReasoningCapability, parseTraeAuthValue, parseTraeCachedModel, parseTraeModelExtraConfigLogLine, parseTraeRawChatBehaviorConfig, parseTraeRemoteModel, parseTraeStorageDocument, pickTraeStorageIdentity, prepareSoloBody, probeTraeRawChatCapability, rawCapabilityDiagnostic, rawCapabilityFingerprint, readTraeCachedModel, readTraeCliIdentity, readTraeIdentity, refreshTraeCredential, regionEnabled, regionEnabledOf, regionOfCredential, regionOfEdition, regionOfHost, regionOfTraeProvider, regionOfTraeStatusUrl, regionOfUserRegion, regionStateOf, registerTraeUsageRoute, resolveTraeIdentity, resolveTraeRawRuntime, sanitizeCatalog, traeEndpoint, traeInputModalities, traeModelDisplayName, traeOwnAuthPath, traeRawChatExtraInfo, traeStorageCandidates, traeWebUsage, unwrapVolatile, unwrapVolatileDeep, withTraeRegion };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-connect-trae",
|
|
3
3
|
"displayName": "DSH Connect Trae",
|
|
4
4
|
"description": "Connect locally signed-in Trae models to DeepSeek Harness, with a usage/credits summary and daily check-in claiming.",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.2.0",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"@deepseek-ai/dsh-llm": "0.1.5-rc.2",
|
|
101
101
|
"@deepseek-ai/dsh-llm-pi-ai": "0.1.5-rc.2",
|
|
102
102
|
"@deepseek-ai/dsh-settings": "0.1.5-rc.2",
|
|
103
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
103
|
+
"@deepseek-ai/schemastery": "3.18.4",
|
|
104
104
|
"@earendil-works/pi-ai": "^0.85.1",
|
|
105
105
|
"@testing-library/dom": "^10.4.2",
|
|
106
106
|
"@testing-library/react": "^16.3.3",
|