dsh-connect-trae 4.8.0 → 4.8.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 +28 -0
- package/README.en.md +17 -1
- package/README.md +35 -1
- package/lib/client.js +85 -5
- package/lib/index.js +83 -1
- package/package.json +17 -17
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 4.8.1 (2026-11-05)
|
|
4
|
+
|
|
5
|
+
### 适配
|
|
6
|
+
|
|
7
|
+
- **DSH 0.2.2-rc.1 同步**。宿主这一版随包换代到 `cordis@4.1.0`、`schemastery@3.19.0`、
|
|
8
|
+
`@earendil-works/pi-ai@1.3.0`,插件消费的 13 个宿主包里有 8 个带实质变化。
|
|
9
|
+
- **唯一的契约破坏**:`ResolvedPiAiProviderProfile` 新增两个必填字段
|
|
10
|
+
`maxRequestImages` / `imageOffloadCountQuantum`。本插件从实时目录手工构造这个 profile,
|
|
11
|
+
升级依赖后 `pnpm typecheck` 报 `TS2739`;已在 `REQUEST_IMAGE_BUDGETS` 补上宿主默认值
|
|
12
|
+
`50 / 10`(旧宿主忽略多余键,0.2.1 线仍类型通过)。
|
|
13
|
+
- **运行期无需适配**:4.8.0 在 0.2.2-rc.1 上照常工作——宿主只在配置解析路径给这两个字段
|
|
14
|
+
兜底,手写 profile 传 `undefined` 时 0.2.2 走「不限制张数」分支(本机实测:usage 路由
|
|
15
|
+
200、已登录)。本版把这两个字段显式声明,图像张数超限的流程才跟着宿主一起生效。
|
|
16
|
+
- **目录变化公告**:区域目录变化时按 provider 发一次 `llm/models-updated`(0.2.2 新增)。
|
|
17
|
+
`llm/adapters-updated` 只在路由拓扑变化时发,覆盖不到「同一路由换了 roster」;签名去重
|
|
18
|
+
保证一次设置写入重建出相同行时不会惊动选择器。旧宿主上这是无人监听的未知事件。
|
|
19
|
+
- **模型标签补回别人的 badge**:`conversation.input.model.label` 是 `single` 槽,本插件
|
|
20
|
+
占住后宿主的「名字 + `model.badge`」内置渲染对所有 provider 都不再生效。现在非 Trae 行
|
|
21
|
+
按宿主顺序补回 badge(trigger 在前、菜单在后)并做语言回退;本插件自己的行行为不变。
|
|
22
|
+
- 不采纳:新语言 ja/es/fr/de/ru/pt(只维护 zh/en)、`settings.section.icon`(不拥有
|
|
23
|
+
`settings.section`)、`llm-pi-ai/request-headers`、`supportsMidConvoEffort`。
|
|
24
|
+
- 三大价值(双区域供应商 / 用量积分 / 每日签到)不受影响,对应测试全绿。
|
|
25
|
+
- **开发树同步**:13 个 `@deepseek-ai/dsh-*` devDependency → `0.2.2-rc.1`,`cordis` →
|
|
26
|
+
`^4.1.0`,`schemastery` → `3.19.0`(含 `pnpm-workspace.yaml` override),`pi-ai` →
|
|
27
|
+
`1.3.0`;`pnpm-lock.yaml` 重新生成。peerDependencies 零改动。
|
|
28
|
+
- `tests/dsh-peer-range.spec.ts` 的 `MUST_ADMIT` 补入 `0.2.2-rc.1`;新增目录公告与
|
|
29
|
+
badge 渲染用例(103 文件 / 1335 用例全绿)。
|
|
30
|
+
|
|
3
31
|
## 4.8.0 (2026-11-05)
|
|
4
32
|
|
|
5
33
|
> **从 npm 升级的用户,这一版把 v4.7.0 也一起带上了。** v4.7.0 的 tag 与 GitHub
|
package/README.en.md
CHANGED
|
@@ -197,7 +197,7 @@ Restart the DSH process after install/update/uninstall.
|
|
|
197
197
|
## DSH version compatibility
|
|
198
198
|
|
|
199
199
|
**Requires DSH 0.1.7-rc.1 and up** (since 2.3.0 the plugin no longer targets hosts older than 0.1.7; the peer dependency ranges are narrowed accordingly).
|
|
200
|
-
**The peer upper bound is `<0.3.0-0`, so both the 0.1.7 and the 0.2 line are supported (including 0.2.
|
|
200
|
+
**The peer upper bound is `<0.3.0-0`, so both the 0.1.7 and the 0.2 line are supported (including 0.2.2-rc.1, verified).**
|
|
201
201
|
|
|
202
202
|
### Both pi-ai context generations are supported (since 3.4.2)
|
|
203
203
|
|
|
@@ -257,6 +257,22 @@ For **this plugin**:
|
|
|
257
257
|
|
|
258
258
|
Details: [section 11 of `docs/DSH_0.2.1_RC1_SYNC.md`](https://github.com/dingminhua/dsh-connect-trae/blob/main/docs/DSH_0.2.1_RC1_SYNC.md).
|
|
259
259
|
|
|
260
|
+
### `0.2.2-rc.1` sync (since 4.8.1)
|
|
261
|
+
|
|
262
|
+
The host moved to `0.2.2-rc.1`. This release is **not just version bumps**: the bundled dependencies move as a set (`cordis` 4.0.5 → **4.1.0**, `schemastery` 3.18.5 → **3.19.0**, `@earendil-works/pi-ai` 1.1.0 → **1.3.0**), and **8 of the 13 host packages** this plugin consumes carry real changes.
|
|
263
|
+
|
|
264
|
+
For **this plugin**:
|
|
265
|
+
|
|
266
|
+
- **One contract break**: `dsh-llm-pi-ai` added two **required** fields to `ResolvedPiAiProviderProfile` — `maxRequestImages` and `imageOffloadCountQuantum`. This plugin builds that profile **by hand** from the live catalog (it bypasses the host's config resolution), so `pnpm typecheck` fails with `TS2739` after the bump. Both are now declared in `REQUEST_IMAGE_BUDGETS` with the host's own defaults, `50 / 10`.
|
|
267
|
+
- **Runtime was never broken**: the host only defaults those fields on its config-resolution path; a hand-built profile that omits them takes the "image count unchecked" branch on 0.2.2. That is why 4.8.0 keeps working there (verified on the desktop host: `GET /plugins/dsh-connect-trae/usage` → 200, `signed-in`).
|
|
268
|
+
- **New capabilities adopted where they matter**: the plugin now emits `llm/models-updated(provider)` when a region's catalog changes (deduplicated by a signature, so a settings write that rebuilds identical rows does not wake every consumer). And because `conversation.input.model.label` is a `single` slot, holding it suppresses the host's built-in "name + `model.badge`" label for **every** provider — so the component now renders another provider's `model.badge` (with language fallback) instead of dropping it. Its own rows are unchanged.
|
|
269
|
+
- **Deliberately not adopted**: the six new UI languages (this plugin keeps zh/en and falls back to English), `settings.section.icon` (it owns plugin cards, not a `settings.section`), `llm-pi-ai/request-headers` (no custom inference headers), `supportsMidConvoEffort` (not on the openai-completions route).
|
|
270
|
+
- **The three core values are unaffected**: dual-region providers, usage/credits overview, daily check-in. Their tests are green; this change only touches the image budget, catalog announcements, and the model label.
|
|
271
|
+
- The other six changed packages (`dsh-host-webserver` resource routes, `dsh-attachment` admission variants, the new languages in `dsh-client-locale` / `dsh-client-ui-settings-plugins`, the `dsh-client-ui-settings` icon slot, `dsh-client-ui-primitives` additions) are **additive**; this plugin either does not use them or already has an equivalent. The five unchanged packages (`dsh-atomic-write`, `dsh-client-ui-renderer`, `dsh-client-ui-slots`, `dsh-home-paths`, `dsh-settings`) are **byte-for-byte identical**, so every slot contract this plugin registers is unchanged.
|
|
272
|
+
- The peer range **needs no change**: `0.2.2-rc.1` is admitted by `>=0.1.7-rc.1 <0.3.0-0`, and `MUST_ADMIT` in `tests/dsh-peer-range.spec.ts` now includes it.
|
|
273
|
+
|
|
274
|
+
Details: [`docs/DSH_0.2.2_RC1_SYNC.md`](https://github.com/dingminhua/dsh-connect-trae/blob/main/docs/DSH_0.2.2_RC1_SYNC.md).
|
|
275
|
+
|
|
260
276
|
|
|
261
277
|
### Why the upper bound is not `<0.2.0`
|
|
262
278
|
|
package/README.md
CHANGED
|
@@ -216,7 +216,7 @@ npm install dsh-connect-trae
|
|
|
216
216
|
## DSH 版本兼容
|
|
217
217
|
|
|
218
218
|
**要求 DSH 0.1.7-rc.1 及以上**(2.3.0 起不再支持 0.1.7 之前的宿主;peer 依赖范围已按此收窄)。
|
|
219
|
-
**peer 上界为 `<0.3.0-0`:0.1.7 与 0.2 两条线均受支持(含 0.2.
|
|
219
|
+
**peer 上界为 `<0.3.0-0`:0.1.7 与 0.2 两条线均受支持(含 0.2.2-rc.1,已实测)。**
|
|
220
220
|
|
|
221
221
|
### 同时支持 pi-ai 的两代上下文(3.4.2 起)
|
|
222
222
|
|
|
@@ -317,6 +317,40 @@ stderr、View 标签的 tooltip 只在文字溢出时显示、More 菜单 toolti
|
|
|
317
317
|
细节见 [`docs/DSH_0.2.1_RC1_SYNC.md`](https://github.com/dingminhua/dsh-connect-trae/blob/main/docs/DSH_0.2.1_RC1_SYNC.md) 第十一节。
|
|
318
318
|
|
|
319
319
|
|
|
320
|
+
### `0.2.2-rc.1` 同步结论(4.8.1 起)
|
|
321
|
+
|
|
322
|
+
宿主推进到 `0.2.2-rc.1`。这一版**不只是版本号**:随包依赖整体换代(`cordis` 4.0.5 →
|
|
323
|
+
**4.1.0**、`schemastery` 3.18.5 → **3.19.0**、`@earendil-works/pi-ai` 1.1.0 → **1.3.0**),
|
|
324
|
+
插件消费的 13 个宿主包里 **8 个有实质变化**。
|
|
325
|
+
|
|
326
|
+
对**本插件**而言:
|
|
327
|
+
|
|
328
|
+
- **唯一的契约破坏**:`dsh-llm-pi-ai` 给 `ResolvedPiAiProviderProfile` 新增了两个**必填**
|
|
329
|
+
字段 `maxRequestImages` / `imageOffloadCountQuantum`。本插件从实时目录**手工构造**这个
|
|
330
|
+
profile(不走宿主的配置解析),所以升级依赖后 `pnpm typecheck` 报 `TS2739`。已在
|
|
331
|
+
`REQUEST_IMAGE_BUDGETS` 补上宿主默认值 `50 / 10`。
|
|
332
|
+
- **运行期原本就没坏**:宿主只在配置解析路径里给这两个字段兜底,手写 profile 传
|
|
333
|
+
`undefined` 时 0.2.2 走「不限制张数」,因此 4.8.0 在 0.2.2 上照常工作(本机实测:桌面端
|
|
334
|
+
0.2.2-rc.1 + 插件 4.8.0,`GET /plugins/dsh-connect-trae/usage` 返回 200 且 `signed-in`)。
|
|
335
|
+
- **新增能力按需采纳**:目录变化时按 provider 发 `llm/models-updated`(签名去重,避免每次
|
|
336
|
+
设置写入都惊动选择器);`conversation.input.model.label` 是 `single` 槽,本插件占住后会
|
|
337
|
+
压掉宿主的「名字 + `model.badge`」内置渲染,因此对**别的 provider** 的模型补回了 badge
|
|
338
|
+
(含语言回退),本插件自己的行行为不变。
|
|
339
|
+
- **明确不采纳**:新语言 ja / es / fr / de / ru / pt(只维护 zh / en,其余回退英文)、
|
|
340
|
+
`settings.section.icon`(插件不拥有 `settings.section`)、`llm-pi-ai/request-headers`
|
|
341
|
+
(不需要额外请求头)、`supportsMidConvoEffort`(openai-completions 路线用不到)。
|
|
342
|
+
- **三大价值不受影响**:双区域供应商、用量与积分概览、每日签到领取——对应测试全绿,本次
|
|
343
|
+
只碰图像预算、目录公告与模型标签三处。
|
|
344
|
+
- 其余 6 个有变化的包(`dsh-host-webserver` 的资源路由、`dsh-attachment` 的准入类型扩展、
|
|
345
|
+
`dsh-client-locale` / `dsh-client-ui-settings-plugins` 的新语言、`dsh-client-ui-settings`
|
|
346
|
+
的 icon 槽位、`dsh-client-ui-primitives` 的新增属性)**全部是新增**,本插件未使用或已有
|
|
347
|
+
等价实现;`dsh-atomic-write` / `dsh-client-ui-renderer` / `dsh-client-ui-slots` /
|
|
348
|
+
`dsh-home-paths` / `dsh-settings` 这 5 个包**逐字节未变**,槽位契约不变。
|
|
349
|
+
- peer 范围**无需改动**:`0.2.2-rc.1` 已被 `>=0.1.7-rc.1 <0.3.0-0` 放行,
|
|
350
|
+
`tests/dsh-peer-range.spec.ts` 的 `MUST_ADMIT` 已补入。
|
|
351
|
+
|
|
352
|
+
细节见 [`docs/DSH_0.2.2_RC1_SYNC.md`](https://github.com/dingminhua/dsh-connect-trae/blob/main/docs/DSH_0.2.2_RC1_SYNC.md)。
|
|
353
|
+
|
|
320
354
|
### peer 上界为什么不写 `<0.2.0`
|
|
321
355
|
|
|
322
356
|
2.3.1 曾写 `<0.2.0-0`,意图是「先不支持 0.2.0 正式版」。这个写法**是错的**:
|
package/lib/client.js
CHANGED
|
@@ -8611,8 +8611,9 @@ window.__ModuleLoader__.load({
|
|
|
8611
8611
|
*
|
|
8612
8612
|
* WHY THE HOST STILL OWNS THE NAME. The contract says to keep `model.name` as
|
|
8613
8613
|
* the text and render the addition beside it, so this component returns the name
|
|
8614
|
-
* first — it never replaces it
|
|
8615
|
-
*
|
|
8614
|
+
* first — it never replaces it. For a provider that is not ours it reproduces
|
|
8615
|
+
* the host's own label: the catalog name and, since 0.2.2, that model's optional
|
|
8616
|
+
* `badge` (see {@link HostModelBadge}).
|
|
8616
8617
|
*
|
|
8617
8618
|
* @module dsh-connect-trae/client/TraeModelLabel
|
|
8618
8619
|
*/
|
|
@@ -8869,8 +8870,9 @@ window.__ModuleLoader__.load({
|
|
|
8869
8870
|
*
|
|
8870
8871
|
* WHAT WINNING/HOLDING COSTS. This cell is `single`, so the other registrants'
|
|
8871
8872
|
* decorations on the rows this plugin claims are not composed. That is the
|
|
8872
|
-
* documented, accepted trade-off, and it is why the component
|
|
8873
|
-
* catalog name
|
|
8873
|
+
* documented, accepted trade-off, and it is why the component reproduces the
|
|
8874
|
+
* host's own presentation — catalog name plus that model's optional badge — for
|
|
8875
|
+
* any provider that is not ours.
|
|
8874
8876
|
*
|
|
8875
8877
|
* WHY A DISTINCT PRIORITY IS NOT ENOUGH ON ITS OWN. It removes the cross-plugin
|
|
8876
8878
|
* collision, but issue #74's error was a SECOND registration of THIS plugin
|
|
@@ -8883,10 +8885,88 @@ window.__ModuleLoader__.load({
|
|
|
8883
8885
|
* made the throw rarer and harder to read, not absent.
|
|
8884
8886
|
*/
|
|
8885
8887
|
const MODEL_LABEL_PRIORITY = -.25;
|
|
8888
|
+
/** The tone colours, mapped onto the same theme tokens the host's Tag paints. */
|
|
8889
|
+
const HOST_BADGE_TONES = {
|
|
8890
|
+
neutral: {
|
|
8891
|
+
color: "var(--dsw-alias-label-secondary)",
|
|
8892
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
8893
|
+
border: "var(--dsw-alias-border-l2)"
|
|
8894
|
+
},
|
|
8895
|
+
info: {
|
|
8896
|
+
color: "var(--dsw-alias-brand-primary)",
|
|
8897
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
8898
|
+
border: "var(--dsw-alias-border-l2)"
|
|
8899
|
+
},
|
|
8900
|
+
success: {
|
|
8901
|
+
color: "var(--dsw-alias-state-success-primary)",
|
|
8902
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
8903
|
+
border: "var(--dsw-alias-border-l2)"
|
|
8904
|
+
},
|
|
8905
|
+
warning: {
|
|
8906
|
+
color: "var(--dsw-alias-state-warn-secondary)",
|
|
8907
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
8908
|
+
border: "var(--dsw-alias-border-l2)"
|
|
8909
|
+
}
|
|
8910
|
+
};
|
|
8911
|
+
/**
|
|
8912
|
+
* The one line a badge shows, in the reader's language.
|
|
8913
|
+
*
|
|
8914
|
+
* The host contract requires an English entry, so that is the last resort; the
|
|
8915
|
+
* active language and its base tag (`de-DE` → `de`) come first, matching what
|
|
8916
|
+
* the host's own resolver does. An empty string is treated as absent — a blank
|
|
8917
|
+
* chip would be a decoration that says nothing.
|
|
8918
|
+
*/
|
|
8919
|
+
function resolveHostBadgeText(text) {
|
|
8920
|
+
if (typeof text === "string") return text.trim() === "" ? void 0 : text;
|
|
8921
|
+
const language = uiLanguage().toLowerCase();
|
|
8922
|
+
const base = language.split("-")[0] ?? "";
|
|
8923
|
+
const picked = text[language] ?? (base === "" ? void 0 : text[base]) ?? text.en;
|
|
8924
|
+
return picked === void 0 || picked.trim() === "" ? void 0 : picked;
|
|
8925
|
+
}
|
|
8926
|
+
/** One provider-authored selector badge, drawn where the host's own label draws it. */
|
|
8927
|
+
function HostBadge(props) {
|
|
8928
|
+
const tone = HOST_BADGE_TONES[props.badge.tone] ?? HOST_BADGE_TONES.neutral;
|
|
8929
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
8930
|
+
className: "dsm-trae-model-label-host-badge",
|
|
8931
|
+
style: {
|
|
8932
|
+
flex: "none",
|
|
8933
|
+
borderRadius: "999px",
|
|
8934
|
+
padding: "0 6px",
|
|
8935
|
+
fontSize: "10px",
|
|
8936
|
+
fontWeight: 500,
|
|
8937
|
+
lineHeight: "15px",
|
|
8938
|
+
whiteSpace: "nowrap",
|
|
8939
|
+
border: `1px solid ${tone.border}`,
|
|
8940
|
+
color: tone.color,
|
|
8941
|
+
background: tone.background,
|
|
8942
|
+
maxWidth: "8em",
|
|
8943
|
+
overflow: "hidden",
|
|
8944
|
+
textOverflow: "ellipsis"
|
|
8945
|
+
},
|
|
8946
|
+
children: props.label
|
|
8947
|
+
});
|
|
8948
|
+
}
|
|
8886
8949
|
function TraeModelLabel(props) {
|
|
8887
8950
|
const { provider, model } = props;
|
|
8888
8951
|
const panel = panelOfProvider(provider.id);
|
|
8889
|
-
if (panel === void 0)
|
|
8952
|
+
if (panel === void 0) {
|
|
8953
|
+
const badgeInfo = model.badge;
|
|
8954
|
+
const label = badgeInfo === void 0 ? void 0 : resolveHostBadgeText(badgeInfo.text);
|
|
8955
|
+
if (badgeInfo === void 0 || label === void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: model.name });
|
|
8956
|
+
const badge = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(HostBadge, {
|
|
8957
|
+
badge: badgeInfo,
|
|
8958
|
+
label
|
|
8959
|
+
});
|
|
8960
|
+
return props.placement === "trigger" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
8961
|
+
badge,
|
|
8962
|
+
" ",
|
|
8963
|
+
model.name
|
|
8964
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", { children: [
|
|
8965
|
+
model.name,
|
|
8966
|
+
" ",
|
|
8967
|
+
badge
|
|
8968
|
+
] });
|
|
8969
|
+
}
|
|
8890
8970
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TraeModelLabelInner, {
|
|
8891
8971
|
modelId: model.id,
|
|
8892
8972
|
name: model.name,
|
package/lib/index.js
CHANGED
|
@@ -1034,10 +1034,33 @@ const INERT_AUTH = {
|
|
|
1034
1034
|
}
|
|
1035
1035
|
}
|
|
1036
1036
|
};
|
|
1037
|
+
/**
|
|
1038
|
+
* The image-request policy this hand-built profile hands to `dsh-llm-pi-ai`.
|
|
1039
|
+
*
|
|
1040
|
+
* WHY THIS OBJECT IS SPELLED OUT. DSH's own config resolution (`resolveProfiles`
|
|
1041
|
+
* in `dsh-llm-pi-ai`) defaults every route-level image bound. This plugin never
|
|
1042
|
+
* runs that path: it builds `ResolvedPiAiProviderProfile` by hand from a live
|
|
1043
|
+
* Trae catalog, so every field the host expects has to be named here or the
|
|
1044
|
+
* bound silently does not apply.
|
|
1045
|
+
*
|
|
1046
|
+
* `maxRequestImages` / `imageOffloadCountQuantum` joined that contract in DSH
|
|
1047
|
+
* 0.2.2-rc.1 (the required fields on `ResolvedPiAiProviderProfile`). The count
|
|
1048
|
+
* bound is what turns a request carrying more images than a route accepts into
|
|
1049
|
+
* the host's `IMAGE_OFFLOAD_REQUIRED` flow instead of an upstream rejection, and
|
|
1050
|
+
* the quantum is how many of the oldest occurrences that flow offloads at once.
|
|
1051
|
+
* Without them the host treats the route as count-unbounded — the pre-0.2.2
|
|
1052
|
+
* behaviour, which is why 4.8.0 kept working — but the type contract no longer
|
|
1053
|
+
* compiles, so they are declared here with the host's own defaults (50 / 10).
|
|
1054
|
+
*
|
|
1055
|
+
* `imageOffloadCountQuantum` must be a positive integer no greater than
|
|
1056
|
+
* `maxRequestImages`; 10 ≤ 50 keeps the host's default ratio.
|
|
1057
|
+
*/
|
|
1037
1058
|
const REQUEST_IMAGE_BUDGETS = {
|
|
1038
1059
|
maxRequestImageBytes: 20971520,
|
|
1039
1060
|
requestImagePixelBudget: 4194304,
|
|
1040
|
-
requestImageMaxBytes: 1048576
|
|
1061
|
+
requestImageMaxBytes: 1048576,
|
|
1062
|
+
maxRequestImages: 50,
|
|
1063
|
+
imageOffloadCountQuantum: 10
|
|
1041
1064
|
};
|
|
1042
1065
|
function toPiModel(info, baseUrl, providerId, withRate = true) {
|
|
1043
1066
|
return {
|
|
@@ -12190,6 +12213,64 @@ function apply(ctx, config) {
|
|
|
12190
12213
|
delete registration.cn.directory;
|
|
12191
12214
|
};
|
|
12192
12215
|
/**
|
|
12216
|
+
* The last catalog announced to the host, per region.
|
|
12217
|
+
*
|
|
12218
|
+
* DSH 0.2.2-rc.1 added `llm/models-updated(provider)`: "a provider's advertised
|
|
12219
|
+
* models or display metadata changed; consumers reload `listModels()`". The
|
|
12220
|
+
* model picker listens for it next to the payload-free `llm/adapters-updated`
|
|
12221
|
+
* — and the latter only fires when a route's TOPOLOGY changes, which is not
|
|
12222
|
+
* the same event as "the models behind an unchanged route changed". The live
|
|
12223
|
+
* directory this plugin refreshes from upstream is exactly the second kind:
|
|
12224
|
+
* the same provider, a different roster.
|
|
12225
|
+
*
|
|
12226
|
+
* The map is the dedupe ledger. Every settings write rebuilds the catalog
|
|
12227
|
+
* object even when the served rows are identical, so an unconditional emit
|
|
12228
|
+
* would make every picker (and every other consumer) re-read the catalog on
|
|
12229
|
+
* each card keystroke.
|
|
12230
|
+
*/
|
|
12231
|
+
const announcedCatalog = /* @__PURE__ */ new Map();
|
|
12232
|
+
/**
|
|
12233
|
+
* What a picker can tell apart about one catalog.
|
|
12234
|
+
*
|
|
12235
|
+
* Must cover every field the host exposes for a model — id, display name,
|
|
12236
|
+
* context window, output cap, input modalities, reasoning tiers, and the
|
|
12237
|
+
* credit multiplier the display name is derived from — or a refresh that
|
|
12238
|
+
* changed only one of them would stay stale in the picker. Order and
|
|
12239
|
+
* omission are both meaningful, so `null` marks an absent key instead of it
|
|
12240
|
+
* collapsing into the empty string.
|
|
12241
|
+
*/
|
|
12242
|
+
function catalogSignature(models) {
|
|
12243
|
+
return models.map((model) => JSON.stringify([
|
|
12244
|
+
model.id,
|
|
12245
|
+
model.name,
|
|
12246
|
+
model.contextWindow ?? null,
|
|
12247
|
+
model.maxTokens ?? null,
|
|
12248
|
+
model.input ?? null,
|
|
12249
|
+
model.reasoningEfforts ?? null,
|
|
12250
|
+
model.creditMultiplier ?? null
|
|
12251
|
+
])).join("\n");
|
|
12252
|
+
}
|
|
12253
|
+
/**
|
|
12254
|
+
* Tell the host that one region's catalog changed, once per change.
|
|
12255
|
+
*
|
|
12256
|
+
* Called from `invalidateAdapter` — the single seam every `catalog.set` path
|
|
12257
|
+
* already ends with (a settings write through `applySelection`, and the
|
|
12258
|
+
* startup discovery) — so a new catalog-set path cannot forget to announce.
|
|
12259
|
+
* A switched-off region advertises nothing: its route is withdrawn and
|
|
12260
|
+
* `syncRegionRegistration` announces that topology change itself, so this
|
|
12261
|
+
* only records the signature.
|
|
12262
|
+
*
|
|
12263
|
+
* Emitting on a host older than 0.2.2 is deliberately harmless: cordis
|
|
12264
|
+
* dispatches events by name and simply has no listener for this one.
|
|
12265
|
+
*/
|
|
12266
|
+
function announceCatalog(panel) {
|
|
12267
|
+
const signature = catalogSignature(stacks[panel].catalog.current());
|
|
12268
|
+
if (announcedCatalog.get(panel) === signature) return;
|
|
12269
|
+
announcedCatalog.set(panel, signature);
|
|
12270
|
+
if (!regionEnabled(current(), panel)) return;
|
|
12271
|
+
ctx.emit("llm/models-updated", providerOfPanel(panel));
|
|
12272
|
+
}
|
|
12273
|
+
/**
|
|
12193
12274
|
* Publish each region's on/off state to the harness (issue #11). Both swaps
|
|
12194
12275
|
* are single synchronous sections, so no request can observe a half-applied
|
|
12195
12276
|
* state, and `replace` announces itself through `llm/adapters-updated`, which
|
|
@@ -12355,6 +12436,7 @@ function apply(ctx, config) {
|
|
|
12355
12436
|
});
|
|
12356
12437
|
stack.invalidateAdapter = () => {
|
|
12357
12438
|
trae.invalidate();
|
|
12439
|
+
announceCatalog(panel);
|
|
12358
12440
|
};
|
|
12359
12441
|
registration[panel].adapters.push({
|
|
12360
12442
|
provider,
|
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.8.
|
|
5
|
+
"version": "4.8.1",
|
|
6
6
|
"author": "dingminhua",
|
|
7
7
|
"copyright": "Copyright (c) 2026 LaoDing",
|
|
8
8
|
"license": "MIT",
|
|
@@ -100,22 +100,22 @@
|
|
|
100
100
|
}
|
|
101
101
|
},
|
|
102
102
|
"devDependencies": {
|
|
103
|
-
"@deepseek-ai/cordis": "^4.0
|
|
104
|
-
"@deepseek-ai/dsh-atomic-write": "0.2.
|
|
105
|
-
"@deepseek-ai/dsh-attachment": "0.2.
|
|
106
|
-
"@deepseek-ai/dsh-client-locale": "0.2.
|
|
107
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.2.
|
|
108
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.2.
|
|
109
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.2.
|
|
110
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.2.
|
|
111
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.2.
|
|
112
|
-
"@deepseek-ai/dsh-home-paths": "0.2.
|
|
113
|
-
"@deepseek-ai/dsh-host-webserver": "0.2.
|
|
114
|
-
"@deepseek-ai/dsh-llm": "0.2.
|
|
115
|
-
"@deepseek-ai/dsh-llm-pi-ai": "0.2.
|
|
116
|
-
"@deepseek-ai/dsh-settings": "0.2.
|
|
117
|
-
"@deepseek-ai/schemastery": "3.
|
|
118
|
-
"@earendil-works/pi-ai": "1.
|
|
103
|
+
"@deepseek-ai/cordis": "^4.1.0",
|
|
104
|
+
"@deepseek-ai/dsh-atomic-write": "0.2.2-rc.1",
|
|
105
|
+
"@deepseek-ai/dsh-attachment": "0.2.2-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-client-locale": "0.2.2-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.2-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.2-rc.1",
|
|
109
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.2-rc.1",
|
|
110
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "0.2.2-rc.1",
|
|
111
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.2-rc.1",
|
|
112
|
+
"@deepseek-ai/dsh-home-paths": "0.2.2-rc.1",
|
|
113
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.2-rc.1",
|
|
114
|
+
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
115
|
+
"@deepseek-ai/dsh-llm-pi-ai": "0.2.2-rc.1",
|
|
116
|
+
"@deepseek-ai/dsh-settings": "0.2.2-rc.1",
|
|
117
|
+
"@deepseek-ai/schemastery": "3.19.0",
|
|
118
|
+
"@earendil-works/pi-ai": "1.3.0",
|
|
119
119
|
"@testing-library/dom": "^10.4.2",
|
|
120
120
|
"@testing-library/react": "^16.3.3",
|
|
121
121
|
"@types/node": "^22.20.0",
|