dsh-connect-trae 1.0.0 → 1.0.1
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 +16 -0
- package/README.en.md +26 -6
- package/README.md +12 -9
- package/cordis.patch.yml +1 -1
- package/lib/index.d.ts +24 -4
- package/lib/index.js +27 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## 1.0.1 (2026-08-31)
|
|
6
|
+
|
|
7
|
+
### Changes
|
|
8
|
+
|
|
9
|
+
- 将 Cordis 插件运行 ID 从 `llm-trae` 统一调整为 `dsh-connect-trae`,与 npm 包名保持一致。已有 1.0.0 本地安装升级后如保留旧配置条目,需移除旧的 `llm-trae` 实例,避免重复加载。
|
|
10
|
+
|
|
11
|
+
### Windows support
|
|
12
|
+
|
|
13
|
+
- `src/identity.ts` 现按平台读取 `product.json`:macOS 保持原路径,新增 Windows 路径 `<LOCALAPPDATA>\Programs\<AppName>\resources\app\product.json`(缺失时回退 `<home>\AppData\Local`),Windows 上 `appVersion` 不再恒为 `undefined`,会随请求头发送 `x-app-version` / `x-ide-version`。
|
|
14
|
+
- `src/identity.ts` 的 `osVersion` 在 Windows 上由 `win32 <release>` 规范化为 `Windows <release>`。
|
|
15
|
+
- `src/identity.ts` / `src/model-cache.ts` 路径推导参数化(`platform` / `home` / `env` 可选注入,默认取真实环境),便于跨平台测试;所有平台判断统一使用同一平台源,避免 `x-device-type` 与 `x-os-version` 自相矛盾。
|
|
16
|
+
- `src/model-cache.ts` 的 `state.vscdb` 路径按平台推导;该模块依赖 `sqlite3` 命令行,Windows 默认未安装,Raw Chat 探测会失败并安全回退(Raw Chat 默认关闭,不影响主流程),详见 README「Windows 说明」。
|
|
17
|
+
- 新增 Windows / Linux / `sg` / `solo-sg` 的 identity 测试用例;修复 `tests/identity.spec.ts` 中依赖测试机平台类型的断言(现显式注入平台,Windows 真机与 CI 均可通过)。
|
|
18
|
+
|
|
3
19
|
## 1.0.0 (2026-08-30)
|
|
4
20
|
|
|
5
21
|
### Features
|
package/README.en.md
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/assets/dsh-connect-trae-usage-card.png" width="860" alt="dsh-connect-trae settings panel" />
|
|
3
|
+
</p>
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
<h1 align="center">dsh-connect-trae</h1>
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
<p align="center"><b>Connect locally signed-in Trae models to DeepSeek Harness with local DSH tools and a read-only credits overview.</b></p>
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="README.md">中文</a> ·
|
|
11
|
+
<a href="#install">Install</a> ·
|
|
12
|
+
<a href="#how-it-works">How it works</a> ·
|
|
13
|
+
<a href="CHANGELOG.md">Changelog</a> ·
|
|
14
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/issues">Issues</a>
|
|
15
|
+
</p>
|
|
8
16
|
|
|
9
17
|
<p align="center">
|
|
10
|
-
<img src="
|
|
18
|
+
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/v/dsh-connect-trae?style=flat-square&label=npm&color=cb3837" alt="npm version"></a>
|
|
19
|
+
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/dm/dsh-connect-trae?style=flat-square&label=downloads" alt="npm downloads"></a>
|
|
20
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/dingminhua/dsh-connect-trae/ci.yml?branch=main&style=flat-square&label=tests" alt="test status"></a>
|
|
21
|
+
<a href="LICENSE"><img src="https://img.shields.io/github/license/dingminhua/dsh-connect-trae?style=flat-square" alt="MIT license"></a>
|
|
22
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/stargazers"><img src="https://img.shields.io/github/stars/dingminhua/dsh-connect-trae?style=flat-square" alt="GitHub stars"></a>
|
|
23
|
+
<a href="https://dshfind.com/plugins/dingminhua/dsh-connect-trae"><img src="https://dshfind.com/api/badge/dingminhua/dsh-connect-trae" alt="dshfind plugin"></a>
|
|
11
24
|
</p>
|
|
12
25
|
|
|
13
|
-
|
|
26
|
+
A [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) bundle plugin that connects locally signed-in Trae CN models to the DSH model picker. Trae generates structured tool calls while DSH executes its own local tools, with a read-only Work/general credits and model-management panel.
|
|
14
27
|
|
|
15
28
|
## Features
|
|
16
29
|
|
|
@@ -50,6 +63,13 @@ npm install dsh-connect-trae
|
|
|
50
63
|
|
|
51
64
|
Restart the DSH process after install/update/uninstall.
|
|
52
65
|
|
|
66
|
+
## Windows notes
|
|
67
|
+
|
|
68
|
+
- **Account data directory**: the plugin reads `%APPDATA%\Trae CN` / `%APPDATA%\TRAE SOLO CN` → `User\globalStorage\storage.json` (unrelated to the install directory). The folder names match macOS, so no extra config is needed; if the name does not match, point the `authFile` + `edition` plugin options at the exact path.
|
|
69
|
+
- **App version headers**: the plugin reads `appVersion` from `<LOCALAPPDATA>\Programs\<AppName>\resources\app\product.json` and sends `x-app-version` / `x-ide-version`; if unreadable, those headers are omitted (same as the previous behavior).
|
|
70
|
+
- **Raw Chat probing (known limitation)**: `model-cache` depends on the `sqlite3` command-line tool, which is not installed by default on Windows; Raw Chat capability probing fails and falls back safely. Raw Chat is off by default and does not affect the main flow.
|
|
71
|
+
- See `docs/WINDOWS_TOKEN_PROBE.md` for troubleshooting.
|
|
72
|
+
|
|
53
73
|
## Development
|
|
54
74
|
|
|
55
75
|
```sh
|
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<
|
|
2
|
+
<img src="docs/assets/dsh-connect-trae-usage-card.png" width="860" alt="dsh-connect-trae settings panel" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">dsh-connect-trae</h1>
|
|
@@ -16,19 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
<p align="center">
|
|
18
18
|
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/v/dsh-connect-trae?style=flat-square&label=npm&color=cb3837" alt="npm version"></a>
|
|
19
|
+
<a href="https://www.npmjs.com/package/dsh-connect-trae"><img src="https://img.shields.io/npm/dm/dsh-connect-trae?style=flat-square&label=downloads" alt="npm downloads"></a>
|
|
20
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/dingminhua/dsh-connect-trae/ci.yml?branch=main&style=flat-square&label=tests" alt="test status"></a>
|
|
19
21
|
<a href="LICENSE"><img src="https://img.shields.io/github/license/dingminhua/dsh-connect-trae?style=flat-square" alt="MIT license"></a>
|
|
22
|
+
<a href="https://github.com/dingminhua/dsh-connect-trae/stargazers"><img src="https://img.shields.io/github/stars/dingminhua/dsh-connect-trae?style=flat-square" alt="GitHub stars"></a>
|
|
23
|
+
<a href="https://dshfind.com/plugins/dingminhua/dsh-connect-trae"><img src="https://dshfind.com/api/badge/dingminhua/dsh-connect-trae" alt="dshfind plugin"></a>
|
|
20
24
|
</p>
|
|
21
25
|
|
|
22
26
|
一个独立的 [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) bundle 插件。它把本机已登录的 Trae 中国区账号接到 DSH 的模型选择器:模型负责生成结构化工具调用,`bash` / `read` / `write` / `edit` 等工具由 DSH 本地执行;同时提供**只读**的 Work/通用积分与模型管理界面。
|
|
23
27
|
|
|
24
|
-
## 效果预览
|
|
25
|
-
|
|
26
|
-
<p align="center">
|
|
27
|
-
<img src="docs/assets/dsh-connect-trae-usage-card.png" alt="DSH Connect Trae 插件卡片:Trae 账号、Work 与通用积分以及模型管理" width="900">
|
|
28
|
-
</p>
|
|
29
|
-
|
|
30
|
-
<p align="center"><sub>设置 → 插件配置 → DSH Connect Trae:切换本机 Trae 账号、查看 Work/通用积分,并管理 DSH 中启用的 Trae 模型。</sub></p>
|
|
31
|
-
|
|
32
28
|
## 功能特性
|
|
33
29
|
|
|
34
30
|
- **Trae 模型接入** —— 把本机登录的 Trae 模型注册为 DSH 的 `trae` provider,模型选择器出现 `DeepSeek-V4-Flash`、`DeepSeek-V4-Pro` 等。
|
|
@@ -69,6 +65,13 @@ npm install dsh-connect-trae
|
|
|
69
65
|
|
|
70
66
|
安装、更新或卸载 bundle 后,需要重启对应的 DSH 进程。
|
|
71
67
|
|
|
68
|
+
## Windows 说明
|
|
69
|
+
|
|
70
|
+
- **账号数据目录**:插件读取 `%APPDATA%\Trae CN` / `%APPDATA%\TRAE SOLO CN` 下的 `User\globalStorage\storage.json`(与安装目录无关)。目录名与 macOS 一致,无需额外配置;若目录名对不上,可用插件配置项 `authFile` + `edition` 直接指定完整路径。
|
|
71
|
+
- **应用版本头**:插件从安装目录 `<LOCALAPPDATA>\Programs\<AppName>\resources\app\product.json` 读取 `appVersion`,随请求发送 `x-app-version` / `x-ide-version`;读不到时这些头不发送(与旧版行为一致)。
|
|
72
|
+
- **Raw Chat 探测(已知限制)**:`model-cache` 依赖 `sqlite3` 命令行,Windows 默认未安装,Raw Chat 能力探测会失败并安全回退。Raw Chat 默认关闭,不影响主流程。
|
|
73
|
+
- 排查指引见 `docs/WINDOWS_TOKEN_PROBE.md`。
|
|
74
|
+
|
|
72
75
|
## 开发
|
|
73
76
|
|
|
74
77
|
```sh
|
package/cordis.patch.yml
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -213,8 +213,16 @@ interface TraeIdentity {
|
|
|
213
213
|
osVersion?: string;
|
|
214
214
|
platform: NodeJS.Platform;
|
|
215
215
|
}
|
|
216
|
+
interface TraeIdentityReadOptions {
|
|
217
|
+
/** Platform override for testing; defaults to process.platform. */
|
|
218
|
+
platform?: NodeJS.Platform;
|
|
219
|
+
/** Home-directory override for testing; defaults to homedir(). */
|
|
220
|
+
home?: string;
|
|
221
|
+
/** Environment override for testing; defaults to process.env. */
|
|
222
|
+
env?: NodeJS.ProcessEnv;
|
|
223
|
+
}
|
|
216
224
|
/** Read stable identity from Trae-owned files without generating impersonated IDs. */
|
|
217
|
-
declare function readTraeIdentity(candidate: TraeStorageCandidate): Promise<TraeIdentity>;
|
|
225
|
+
declare function readTraeIdentity(candidate: TraeStorageCandidate, options?: TraeIdentityReadOptions): Promise<TraeIdentity>;
|
|
218
226
|
/** Headers derived from actual persisted identity, never a new random identity per request. */
|
|
219
227
|
declare function identityHeaders(identity: TraeIdentity): Record<string, string>;
|
|
220
228
|
//#endregion
|
|
@@ -244,8 +252,20 @@ interface TraeCachedModelConfig {
|
|
|
244
252
|
}
|
|
245
253
|
/** Parse a safe subset of one cached model entry; credentials and endpoints are intentionally omitted. */
|
|
246
254
|
declare function parseTraeCachedModel(value: unknown): TraeCachedModelConfig | undefined;
|
|
247
|
-
|
|
248
|
-
|
|
255
|
+
interface TraeCachedModelReadOptions {
|
|
256
|
+
/** Platform override for testing; defaults to process.platform. */
|
|
257
|
+
platform?: NodeJS.Platform;
|
|
258
|
+
/** Home-directory override for testing; defaults to homedir(). */
|
|
259
|
+
home?: string;
|
|
260
|
+
/** Environment override for testing; defaults to process.env. */
|
|
261
|
+
env?: NodeJS.ProcessEnv;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Read Trae's own current user's model map via sqlite3 without exposing
|
|
265
|
+
* secrets. The sqlite3 command line is a macOS prerequisite; on Windows it is
|
|
266
|
+
* typically absent, so the call fails and callers fall back gracefully.
|
|
267
|
+
*/
|
|
268
|
+
declare function readTraeCachedModel(functionName: string, modelName: string, userId: string, options?: TraeCachedModelReadOptions): Promise<TraeCachedModelConfig | undefined>;
|
|
249
269
|
//#endregion
|
|
250
270
|
//#region src/model-extra-config.d.ts
|
|
251
271
|
interface TraeRawChatBehaviorConfig {
|
|
@@ -952,7 +972,7 @@ declare function traeWebUsage(deps: TraeUsageRouteOptions): Promise<TraeWebUsage
|
|
|
952
972
|
declare function registerTraeUsageRoute(ctx: Context, deps: TraeUsageRouteOptions): void;
|
|
953
973
|
//#endregion
|
|
954
974
|
//#region src/index.d.ts
|
|
955
|
-
declare const name = "
|
|
975
|
+
declare const name = "dsh-connect-trae";
|
|
956
976
|
declare const inject: string[];
|
|
957
977
|
declare const TRAE_SETTINGS_NS: import("@deepseek-ai/dsh-settings").SettingsNamespace;
|
|
958
978
|
interface Config {
|
package/lib/index.js
CHANGED
|
@@ -834,7 +834,10 @@ function deviceCenterId(storage) {
|
|
|
834
834
|
return ids.length === 1 ? ids[0] : void 0;
|
|
835
835
|
}
|
|
836
836
|
/** Read stable identity from Trae-owned files without generating impersonated IDs. */
|
|
837
|
-
async function readTraeIdentity(candidate) {
|
|
837
|
+
async function readTraeIdentity(candidate, options = {}) {
|
|
838
|
+
const platform = options.platform ?? process.platform;
|
|
839
|
+
const home = options.home ?? homedir();
|
|
840
|
+
const env = options.env ?? process.env;
|
|
838
841
|
const storage = JSON.parse(await readFile(candidate.path, "utf8"));
|
|
839
842
|
const appRoot = dirname(dirname(dirname(candidate.path)));
|
|
840
843
|
const machineFile = nonEmpty(await readFile(join(appRoot, "machineid"), "utf8").catch(() => ""));
|
|
@@ -845,16 +848,24 @@ async function readTraeIdentity(candidate) {
|
|
|
845
848
|
if (machineId === void 0) throw new Error(`Trae ${candidate.edition} has no stable machine identity`);
|
|
846
849
|
const deviceId = dcDevice ?? devDevice ?? createHash("sha256").update(machineId).digest("hex").slice(0, 32);
|
|
847
850
|
const buildVersion = nonEmpty(storage["iCubeLastVersion"]);
|
|
848
|
-
const
|
|
851
|
+
const appName = candidate.edition === "cn" ? "Trae CN" : candidate.edition === "solo" ? "TRAE SOLO CN" : void 0;
|
|
852
|
+
const productPaths = [];
|
|
853
|
+
if (appName !== void 0 && (platform === "darwin" || platform === "win32")) {
|
|
854
|
+
if (platform === "darwin") productPaths.push(join("/Applications", `${appName}.app`, "Contents", "Resources", "app", "product.json"));
|
|
855
|
+
else {
|
|
856
|
+
const localRoots = [env.LOCALAPPDATA, join(home, "AppData", "Local")].filter((value) => typeof value === "string" && value !== "").filter((value, index, all) => all.indexOf(value) === index);
|
|
857
|
+
for (const root of localRoots) productPaths.push(join(root, "Programs", appName, "resources", "app", "product.json"));
|
|
858
|
+
}
|
|
859
|
+
}
|
|
849
860
|
let product = {};
|
|
850
861
|
for (const path of productPaths) try {
|
|
851
862
|
product = JSON.parse(await readFile(path, "utf8"));
|
|
852
863
|
break;
|
|
853
864
|
} catch {}
|
|
854
865
|
const appVersion = nonEmpty(product["appVersion"]);
|
|
855
|
-
const deviceBrand =
|
|
866
|
+
const deviceBrand = platform === "darwin" ? nonEmpty(env["TRAE_DEVICE_BRAND"]) : void 0;
|
|
856
867
|
const deviceCpu = cpus()[0]?.model.split(" ")[0];
|
|
857
|
-
const osVersion = `${
|
|
868
|
+
const osVersion = `${platform === "darwin" ? "macOS" : platform === "win32" ? "Windows" : platform} ${release()}`;
|
|
858
869
|
return {
|
|
859
870
|
edition: candidate.edition,
|
|
860
871
|
machineId,
|
|
@@ -864,7 +875,7 @@ async function readTraeIdentity(candidate) {
|
|
|
864
875
|
...deviceBrand === void 0 ? {} : { deviceBrand },
|
|
865
876
|
...deviceCpu === void 0 ? {} : { deviceCpu },
|
|
866
877
|
osVersion,
|
|
867
|
-
platform
|
|
878
|
+
platform
|
|
868
879
|
};
|
|
869
880
|
}
|
|
870
881
|
/** Headers derived from actual persisted identity, never a new random identity per request. */
|
|
@@ -2320,9 +2331,16 @@ function parseTraeCachedModel(value) {
|
|
|
2320
2331
|
...typeof raw["model_type"] === "string" ? { modelType: raw["model_type"] } : {}
|
|
2321
2332
|
};
|
|
2322
2333
|
}
|
|
2323
|
-
/**
|
|
2324
|
-
|
|
2325
|
-
|
|
2334
|
+
/**
|
|
2335
|
+
* Read Trae's own current user's model map via sqlite3 without exposing
|
|
2336
|
+
* secrets. The sqlite3 command line is a macOS prerequisite; on Windows it is
|
|
2337
|
+
* typically absent, so the call fails and callers fall back gracefully.
|
|
2338
|
+
*/
|
|
2339
|
+
async function readTraeCachedModel(functionName, modelName, userId, options = {}) {
|
|
2340
|
+
const platform = options.platform ?? process.platform;
|
|
2341
|
+
const home = options.home ?? homedir();
|
|
2342
|
+
const env = options.env ?? process.env;
|
|
2343
|
+
const database = platform === "win32" ? join(env.APPDATA ?? join(home, "AppData", "Roaming"), "Trae CN", "User", "globalStorage", "state.vscdb") : join(home, "Library", "Application Support", "Trae CN", "User", "globalStorage", "state.vscdb");
|
|
2326
2344
|
const key = `${userId}_AI.agent.model.model_list_map`;
|
|
2327
2345
|
const sql = `select value from ItemTable where key=${JSON.stringify(key)} limit 1;`;
|
|
2328
2346
|
const { stdout } = await execFileAsync("sqlite3", [database, sql], { maxBuffer: 8388608 });
|
|
@@ -2915,7 +2933,7 @@ var UnconfiguredTraeUpstreamClient = class {
|
|
|
2915
2933
|
};
|
|
2916
2934
|
//#endregion
|
|
2917
2935
|
//#region src/index.ts
|
|
2918
|
-
const name = "
|
|
2936
|
+
const name = "dsh-connect-trae";
|
|
2919
2937
|
const inject = ["llm"];
|
|
2920
2938
|
const TRAE_SETTINGS_NS = settingsNamespace("trae");
|
|
2921
2939
|
const modelConfig = z.object({
|
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, plus a read-only usage/credits summary.",
|
|
5
|
-
"version": "1.0.
|
|
5
|
+
"version": "1.0.1",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|