dsh-workbuddy-bridge 0.5.0 → 0.5.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/README.md +2 -1
- package/README_en.md +2 -0
- package/lib/bin.js +1 -1
- package/lib/{heartbeat-BpW2mSgI.js → heartbeat-DR6QsZ9h.js} +61 -24
- package/lib/index.d.ts +28 -2
- package/lib/index.js +8 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -47,10 +47,11 @@
|
|
|
47
47
|
|
|
48
48
|
- **开箱即用** —— 装完启用,模型分组自己出现。
|
|
49
49
|
- **两版隔离** —— 国内版与国际版各自分组,模型、账号、积分互不混用,只跟随各自 App 的登录状态。
|
|
50
|
-
- **推理档位** —— 上游声明了档位的模型直接可选;没声明的可在插件页**手动检测**。
|
|
51
50
|
- **推理档位** —— 上游声明了档位的模型直接可选;没声明的可在插件页**手动检测**。
|
|
52
51
|
灯泡表示能切档位;上游已声明的模型也亮着,只是不需要检测。
|
|
53
52
|
能切档位的模型会带一个**默认档位**(上游声明了就按声明,否则取 `high`),因此选择器里不再出现「Default」这一项。
|
|
53
|
+
档位里的 **Off 表示「不发送档位参数」**:两个接口都不接受这个字面量,所以插件不会把它发出去;
|
|
54
|
+
实际是否关闭思考由上游决定,插件不做保证。
|
|
54
55
|
- **积分可见** —— 每条回复下方显示本次消耗,模型选择器旁常驻剩余积分。拿不到数字时不显示。
|
|
55
56
|
- **模型显隐** —— 卡片「模型」标签里勾选哪些模型出现在选择器里,按登录账号分别保存。
|
|
56
57
|
- **图片输入** —— 多数模型可直接粘贴或拖入图片;纯文字模型会明确说明。
|
package/README_en.md
CHANGED
|
@@ -54,6 +54,8 @@ models appear directly in the DSH model picker — no separate provider to confi
|
|
|
54
54
|
on the plugin page. The bulb means "this model can switch levels"; a declared model shows it too, it just
|
|
55
55
|
has nothing to detect. A switchable model also carries a **default level** (the upstream's own declaration
|
|
56
56
|
when it has one, otherwise `high`), so the picker no longer offers "Default".
|
|
57
|
+
**Off means "send no level parameter"**: neither endpoint accepts that literal, so the plugin never puts it
|
|
58
|
+
on the wire — whether thinking is then actually disabled is up to the upstream, and the plugin makes no claim.
|
|
57
59
|
- **Credit in view** — each reply shows what it consumed, and remaining credit sits beside the model picker.
|
|
58
60
|
Nothing renders when a figure is unavailable.
|
|
59
61
|
- **Model visibility** — tick which models appear in the picker on the card's "Models" tab, saved per
|
package/lib/bin.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as variantFor, D as WorkBuddyUpstreamClient, S as WORKBUDDY_VARIANTS, Y as resolveAppVersion, a as readHostHeartbeat, c as WORKBUDDY_BRIDGE_VERSION, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, x as CN_VARIANT } from "./heartbeat-
|
|
2
|
+
import { C as variantFor, D as WorkBuddyUpstreamClient, S as WORKBUDDY_VARIANTS, Y as resolveAppVersion, a as readHostHeartbeat, c as WORKBUDDY_BRIDGE_VERSION, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, u as FALLBACK_WORKBUDDY_MODELS, x as CN_VARIANT } from "./heartbeat-DR6QsZ9h.js";
|
|
3
3
|
import { realpathSync } from "node:fs";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/cli/bin.ts
|
|
@@ -828,13 +828,21 @@ function billingHeaders(credential) {
|
|
|
828
828
|
* Normalize an OpenAI chat-completions body for the WorkBuddy upstream:
|
|
829
829
|
* force `stream: true` (the upstream rejects non-streaming), flatten
|
|
830
830
|
* `tool_choice` (the upstream's field is a string; object forms return 400),
|
|
831
|
-
*
|
|
831
|
+
* rewrite `developer` messages as `system`, and drop the adapter's own `off`
|
|
832
|
+
* effort spelling (see {@link dropUnsupportedEffort}).
|
|
832
833
|
*
|
|
833
834
|
* The `developer` rewrite is load-bearing: pi-ai emits the system prompt as
|
|
834
835
|
* `role: "developer"` (the OpenAI convention it adopted), but the WorkBuddy
|
|
835
836
|
* upstream rejects that role with HTTP 400 code 11128 ("Illegal API
|
|
836
837
|
* invocation from an unapproved channel"). Rewriting to `system` is the
|
|
837
838
|
* compatible spelling the upstream accepts.
|
|
839
|
+
*
|
|
840
|
+
* Every transformation here is region-agnostic on purpose. The two endpoints
|
|
841
|
+
* differ in what they *add* (the international one also needs a leading system
|
|
842
|
+
* prompt — see {@link prepareInternationalChatBody}), not in what they reject:
|
|
843
|
+
* both refuse the picker's `off` spelling, which is why that strip lives here
|
|
844
|
+
* rather than in the international layer (issue #13 reversed the earlier
|
|
845
|
+
* international-only scope decision, which rested on CN accepting it).
|
|
838
846
|
*/
|
|
839
847
|
function prepareChatBody(source) {
|
|
840
848
|
let body;
|
|
@@ -848,6 +856,7 @@ function prepareChatBody(source) {
|
|
|
848
856
|
obj["stream"] = true;
|
|
849
857
|
normalizeDeveloperRole(obj);
|
|
850
858
|
normalizeToolChoice(obj);
|
|
859
|
+
dropUnsupportedEffort(obj);
|
|
851
860
|
return JSON.stringify(obj);
|
|
852
861
|
}
|
|
853
862
|
/** Rewrite `role: "developer"` messages to `role: "system"` (upstream rejects developer). */
|
|
@@ -937,7 +946,20 @@ var WorkBuddyUpstreamClient = class {
|
|
|
937
946
|
this.resolveAppVersion = options.resolveAppVersion ?? (() => resolveAppVersion());
|
|
938
947
|
this.resolveChatIdentity = options.resolveChatIdentity ?? ((region) => resolveChatIdentity(region));
|
|
939
948
|
}
|
|
940
|
-
/**
|
|
949
|
+
/**
|
|
950
|
+
* POST the chat endpoint; a successful answer is the raw SSE response.
|
|
951
|
+
*
|
|
952
|
+
* This is the one place every chat request converges on (the loopback shim,
|
|
953
|
+
* the host LLM route, and any direct caller all end up here), so it is also
|
|
954
|
+
* where the body is normalized for the upstream — in *both* regions. The
|
|
955
|
+
* region only decides which extra requirement applies on top: the
|
|
956
|
+
* international gateway additionally demands a leading system message. It
|
|
957
|
+
* used to decide whether the body was normalized at all, which left the CN
|
|
958
|
+
* path sending the picker's `off` spelling verbatim (issue #13).
|
|
959
|
+
*
|
|
960
|
+
* Normalization is idempotent, so a caller that already prepared the body
|
|
961
|
+
* (the shim does) sees no second change.
|
|
962
|
+
*/
|
|
941
963
|
async chatStream(credential, bodyJson, signal) {
|
|
942
964
|
const region = regionOf(credential.domain);
|
|
943
965
|
let userAgent;
|
|
@@ -946,6 +968,7 @@ var WorkBuddyUpstreamClient = class {
|
|
|
946
968
|
} catch {
|
|
947
969
|
userAgent = chatUserAgent(fallbackChatIdentity(region), region);
|
|
948
970
|
}
|
|
971
|
+
const body = region === "global" ? prepareInternationalChatBody(bodyJson) : prepareChatBody(bodyJson);
|
|
949
972
|
let response;
|
|
950
973
|
try {
|
|
951
974
|
response = await fetch(`${chatBase(credential)}/v2/chat/completions`, {
|
|
@@ -954,7 +977,7 @@ var WorkBuddyUpstreamClient = class {
|
|
|
954
977
|
...chatHeaders(credential, userAgent),
|
|
955
978
|
Authorization: `Bearer ${credential.accessToken}`
|
|
956
979
|
},
|
|
957
|
-
body
|
|
980
|
+
body,
|
|
958
981
|
...signal === void 0 ? {} : { signal }
|
|
959
982
|
});
|
|
960
983
|
} catch (error) {
|
|
@@ -1498,6 +1521,11 @@ function modelWithCurrentPromotion(model, now = Date.now()) {
|
|
|
1498
1521
|
* merged: existing messages keep their order and wording. A body that is not a
|
|
1499
1522
|
* JSON object is returned unchanged, exactly as {@link prepareChatBody} does,
|
|
1500
1523
|
* so this is safe to run over an already-prepared-or-not body.
|
|
1524
|
+
*
|
|
1525
|
+
* This layer now carries *only* that requirement. The `reasoning_effort` strip
|
|
1526
|
+
* used to live here, scoped to this region; issue #13 showed CN rejects the
|
|
1527
|
+
* same spelling, so it moved into the shared {@link prepareChatBody} and this
|
|
1528
|
+
* function no longer touches the effort field at all.
|
|
1501
1529
|
*/
|
|
1502
1530
|
function prepareInternationalChatBody(source) {
|
|
1503
1531
|
const prepared = prepareChatBody(source);
|
|
@@ -1508,7 +1536,6 @@ function prepareInternationalChatBody(source) {
|
|
|
1508
1536
|
return prepared;
|
|
1509
1537
|
}
|
|
1510
1538
|
if (!isObject(body)) return prepared;
|
|
1511
|
-
dropUnsupportedEffort(body);
|
|
1512
1539
|
const messages = body["messages"];
|
|
1513
1540
|
if (!Array.isArray(messages)) return JSON.stringify(body);
|
|
1514
1541
|
const first = messages[0];
|
|
@@ -1520,25 +1547,35 @@ function prepareInternationalChatBody(source) {
|
|
|
1520
1547
|
return JSON.stringify(body);
|
|
1521
1548
|
}
|
|
1522
1549
|
/**
|
|
1523
|
-
* Remove the adapter's own `off` effort spelling from the
|
|
1524
|
-
*
|
|
1525
|
-
* `thinkingLevelMap.off` is pinned to the literal `'off'`
|
|
1526
|
-
*
|
|
1527
|
-
*
|
|
1528
|
-
*
|
|
1529
|
-
*
|
|
1530
|
-
*
|
|
1531
|
-
*
|
|
1532
|
-
* `
|
|
1533
|
-
*
|
|
1534
|
-
*
|
|
1535
|
-
*
|
|
1536
|
-
*
|
|
1537
|
-
*
|
|
1538
|
-
*
|
|
1539
|
-
*
|
|
1540
|
-
*
|
|
1541
|
-
*
|
|
1550
|
+
* Remove the adapter's own `off` effort spelling from the wire, in both regions.
|
|
1551
|
+
*
|
|
1552
|
+
* `thinkingLevelMap.off` is pinned to the literal `'off'` so the level stays
|
|
1553
|
+
* selectable in the picker — pi-ai exposes a level only when its entry is a
|
|
1554
|
+
* string — but that same entry is also the value pi-ai puts on the wire, both
|
|
1555
|
+
* for an explicit Off selection and for *every* request that carries no level
|
|
1556
|
+
* at all. `'off'` is a picker name, not an upstream spelling, and both
|
|
1557
|
+
* endpoints reject it:
|
|
1558
|
+
*
|
|
1559
|
+
* - international GPT family: HTTP 400 `11133` / `extError.param ===
|
|
1560
|
+
* 'reasoning.effort'` (issue #49);
|
|
1561
|
+
* - CN: the same 400 `11133` on every `canDisableThinking` model — measured
|
|
1562
|
+
* on `deepseek-v4.1-flash`, where the author also confirmed `'disabled'`
|
|
1563
|
+
* is rejected and `'none'` answers 200 (issue #13). This is what made the
|
|
1564
|
+
* earlier international-only scope decision obsolete.
|
|
1565
|
+
*
|
|
1566
|
+
* Omission is the only form measured good on every affected model, so it is
|
|
1567
|
+
* the only form this function can produce; a literal `'none'` is *not* a safe
|
|
1568
|
+
* substitute (accepted by the GPT-5.6 family and GLM, rejected by
|
|
1569
|
+
* `gpt-6-astra`, and silently ignored by `kimi-k2.8-preview`). Declared
|
|
1570
|
+
* spellings (`low`/`medium`/`high`/`xhigh`/`max`) and an explicit `none` pass
|
|
1571
|
+
* through untouched — the adapter does not decide a user's `none` for them.
|
|
1572
|
+
*
|
|
1573
|
+
* Consequences, stated honestly: the picker still offers Off in both regions,
|
|
1574
|
+
* but selecting it means "the field is omitted". The model's actual behaviour
|
|
1575
|
+
* is then decided upstream — *not* guaranteed to disable thinking and not
|
|
1576
|
+
* guaranteed to match the catalog's `defaultEffort`. The plugin used to claim
|
|
1577
|
+
* more than that on CN, where `'off'` was merely accepted (accepted never
|
|
1578
|
+
* meant effective); #13 is why the claim is withdrawn rather than reworded.
|
|
1542
1579
|
*/
|
|
1543
1580
|
function dropUnsupportedEffort(obj) {
|
|
1544
1581
|
if (obj["reasoning_effort"] === "off") delete obj["reasoning_effort"];
|
|
@@ -3688,7 +3725,7 @@ var WorkBuddyCatalog = class {
|
|
|
3688
3725
|
};
|
|
3689
3726
|
//#endregion
|
|
3690
3727
|
//#region src/version.ts
|
|
3691
|
-
const WORKBUDDY_BRIDGE_VERSION = "0.5.
|
|
3728
|
+
const WORKBUDDY_BRIDGE_VERSION = "0.5.1";
|
|
3692
3729
|
//#endregion
|
|
3693
3730
|
//#region src/web/heartbeat.ts
|
|
3694
3731
|
/**
|
package/lib/index.d.ts
CHANGED
|
@@ -613,13 +613,21 @@ declare function regionOf(domain: string): WorkBuddyRegion;
|
|
|
613
613
|
* Normalize an OpenAI chat-completions body for the WorkBuddy upstream:
|
|
614
614
|
* force `stream: true` (the upstream rejects non-streaming), flatten
|
|
615
615
|
* `tool_choice` (the upstream's field is a string; object forms return 400),
|
|
616
|
-
*
|
|
616
|
+
* rewrite `developer` messages as `system`, and drop the adapter's own `off`
|
|
617
|
+
* effort spelling (see {@link dropUnsupportedEffort}).
|
|
617
618
|
*
|
|
618
619
|
* The `developer` rewrite is load-bearing: pi-ai emits the system prompt as
|
|
619
620
|
* `role: "developer"` (the OpenAI convention it adopted), but the WorkBuddy
|
|
620
621
|
* upstream rejects that role with HTTP 400 code 11128 ("Illegal API
|
|
621
622
|
* invocation from an unapproved channel"). Rewriting to `system` is the
|
|
622
623
|
* compatible spelling the upstream accepts.
|
|
624
|
+
*
|
|
625
|
+
* Every transformation here is region-agnostic on purpose. The two endpoints
|
|
626
|
+
* differ in what they *add* (the international one also needs a leading system
|
|
627
|
+
* prompt — see {@link prepareInternationalChatBody}), not in what they reject:
|
|
628
|
+
* both refuse the picker's `off` spelling, which is why that strip lives here
|
|
629
|
+
* rather than in the international layer (issue #13 reversed the earlier
|
|
630
|
+
* international-only scope decision, which rested on CN accepting it).
|
|
623
631
|
*/
|
|
624
632
|
declare function prepareChatBody(source: string): string;
|
|
625
633
|
/** Provenance of one successful catalog fetch, surfaced by the status card. */
|
|
@@ -660,7 +668,20 @@ declare class WorkBuddyUpstreamClient {
|
|
|
660
668
|
/** Provenance of the most recent successful catalog fetch, for the card. */
|
|
661
669
|
lastCatalog: WorkBuddyCatalogFetch | undefined;
|
|
662
670
|
constructor(options?: WorkBuddyUpstreamClientOptions);
|
|
663
|
-
/**
|
|
671
|
+
/**
|
|
672
|
+
* POST the chat endpoint; a successful answer is the raw SSE response.
|
|
673
|
+
*
|
|
674
|
+
* This is the one place every chat request converges on (the loopback shim,
|
|
675
|
+
* the host LLM route, and any direct caller all end up here), so it is also
|
|
676
|
+
* where the body is normalized for the upstream — in *both* regions. The
|
|
677
|
+
* region only decides which extra requirement applies on top: the
|
|
678
|
+
* international gateway additionally demands a leading system message. It
|
|
679
|
+
* used to decide whether the body was normalized at all, which left the CN
|
|
680
|
+
* path sending the picker's `off` spelling verbatim (issue #13).
|
|
681
|
+
*
|
|
682
|
+
* Normalization is idempotent, so a caller that already prepared the body
|
|
683
|
+
* (the shim does) sees no second change.
|
|
684
|
+
*/
|
|
664
685
|
chatStream(credential: WorkBuddyCredential, bodyJson: string, signal?: AbortSignal): Promise<WorkBuddyChatResult>;
|
|
665
686
|
/** POST the token-refresh endpoint; the caller merges the outcome. */
|
|
666
687
|
refreshToken(credential: WorkBuddyCredential): Promise<WorkBuddyRefreshOutcome>;
|
|
@@ -833,6 +854,11 @@ declare function modelWithCurrentPromotion(model: WorkBuddyUpstreamModel, now?:
|
|
|
833
854
|
* merged: existing messages keep their order and wording. A body that is not a
|
|
834
855
|
* JSON object is returned unchanged, exactly as {@link prepareChatBody} does,
|
|
835
856
|
* so this is safe to run over an already-prepared-or-not body.
|
|
857
|
+
*
|
|
858
|
+
* This layer now carries *only* that requirement. The `reasoning_effort` strip
|
|
859
|
+
* used to live here, scoped to this region; issue #13 showed CN rejects the
|
|
860
|
+
* same spelling, so it moved into the shared {@link prepareChatBody} and this
|
|
861
|
+
* function no longer touches the effort field at all.
|
|
836
862
|
*/
|
|
837
863
|
declare function prepareInternationalChatBody(source: string): string;
|
|
838
864
|
//#endregion
|
package/lib/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as parseModelCatalog, B as chatUserAgent, C as variantFor, D as WorkBuddyUpstreamClient, F as probeModel, G as WORKBUDDY_APP_VERSION_FILENAME, H as readCliVersion, I as randomSentinel, J as readBundleVersion, K as appUserAgent, L as classifyUpstreamError, M as prepareInternationalChatBody, N as regionOf, O as modelWithCurrentPromotion, P as PROBE_EFFORT_CANDIDATES, R as CN_APP_VERSION_FILENAME, S as WORKBUDDY_VARIANTS, U as resolveChatIdentity, V as fallbackChatIdentity, W as validCliVersion, X as validAppVersion, Y as resolveAppVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as AI_VARIANT, c as WORKBUDDY_BRIDGE_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as prepareChatBody, k as normalizeCredits, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as installedAppVersion, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as WORKBUDDY_CREDIT_PATH, x as CN_VARIANT, y as workbuddyOwnAuthPath, z as FALLBACK_CN_APP_VERSION } from "./heartbeat-
|
|
1
|
+
import { A as parseModelCatalog, B as chatUserAgent, C as variantFor, D as WorkBuddyUpstreamClient, F as probeModel, G as WORKBUDDY_APP_VERSION_FILENAME, H as readCliVersion, I as randomSentinel, J as readBundleVersion, K as appUserAgent, L as classifyUpstreamError, M as prepareInternationalChatBody, N as regionOf, O as modelWithCurrentPromotion, P as PROBE_EFFORT_CANDIDATES, R as CN_APP_VERSION_FILENAME, S as WORKBUDDY_VARIANTS, U as resolveChatIdentity, V as fallbackChatIdentity, W as validCliVersion, X as validAppVersion, Y as resolveAppVersion, _ as desktopAuthCandidatesFor, a as readHostHeartbeat, b as AI_VARIANT, c as WORKBUDDY_BRIDGE_VERSION, d as WorkBuddyCatalog, f as WORKBUDDY_AUTH_FILENAME, g as defaultDesktopAuthPath, h as defaultDesktopAuthCandidates, i as processStartTimeMs, j as prepareChatBody, k as normalizeCredits, l as FALLBACK_WORKBUDDY_AI_MODELS, m as WorkBuddyCredentialStore, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as WORKBUDDY_AUTH_FILE_ENV, q as installedAppVersion, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as FALLBACK_WORKBUDDY_MODELS, v as parseWorkBuddyAuth, w as WORKBUDDY_CREDIT_PATH, x as CN_VARIANT, y as workbuddyOwnAuthPath, z as FALLBACK_CN_APP_VERSION } from "./heartbeat-DR6QsZ9h.js";
|
|
2
2
|
import z from "@deepseek-ai/schemastery";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { resolveDshHome } from "@deepseek-ai/dsh-home-paths";
|
|
@@ -446,6 +446,13 @@ function withCatalogDisplay(name, info) {
|
|
|
446
446
|
* The offered set is described internally as "verified accepted", never as
|
|
447
447
|
* "verified effective": acceptance proves the upstream did not reject the
|
|
448
448
|
* spelling, not that it changes what the model does.
|
|
449
|
+
*
|
|
450
|
+
* `off` is a picker name, not a wire spelling. It stays pinned to the literal
|
|
451
|
+
* `'off'` (a `null` here would remove the level from the picker entirely), and
|
|
452
|
+
* the shared preparation in `src/protocol/client.ts` strips that exact value
|
|
453
|
+
* before the request leaves the plugin — in both regions, because both
|
|
454
|
+
* endpoints reject it (issues #49 and #13). Selecting Off therefore means "send
|
|
455
|
+
* no `reasoning_effort`", and what the model then does is upstream's call.
|
|
449
456
|
*/
|
|
450
457
|
function reasoningFields(info, observed) {
|
|
451
458
|
const resolved = resolveEfforts(info, observed);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "dsh-workbuddy-bridge",
|
|
3
3
|
"displayName": "DSH WorkBuddy Bridge",
|
|
4
4
|
"description": "将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness — bring WorkBuddy desktop app models into DeepSeek Harness with zero configuration.",
|
|
5
|
-
"version": "0.5.
|
|
5
|
+
"version": "0.5.1",
|
|
6
6
|
"author": "zlZayn",
|
|
7
7
|
"keywords": [
|
|
8
8
|
"dsh",
|
|
@@ -97,7 +97,7 @@
|
|
|
97
97
|
"react-dom": "^18.2.0"
|
|
98
98
|
},
|
|
99
99
|
"devDependencies": {
|
|
100
|
-
"@deepseek-ai/cordis": "4.0.4",
|
|
100
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
101
101
|
"@deepseek-ai/dsh-api-remotes": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
|
|
102
102
|
"@deepseek-ai/dsh-atomic-write": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
|
|
103
103
|
"@deepseek-ai/dsh-attachment": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
|
|
@@ -119,7 +119,7 @@
|
|
|
119
119
|
"@deepseek-ai/dsh-settings": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
|
|
120
120
|
"@deepseek-ai/dsh-util-code-language": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
|
|
121
121
|
"@deepseek-ai/dsh-util-workspace-path": "^0.1.7-rc.1 || ^0.2.0-rc.1 || ^0.2.1-rc.1",
|
|
122
|
-
"@deepseek-ai/schemastery": "3.18.
|
|
122
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
123
123
|
"@earendil-works/pi-ai": "^1.1.0",
|
|
124
124
|
"@eslint/js": "^10.0.1",
|
|
125
125
|
"@shikijs/langs": "^4.4.3",
|
|
@@ -150,7 +150,7 @@
|
|
|
150
150
|
"micromark-util-symbol": "^2.0.1",
|
|
151
151
|
"prettier": "^3.9.9",
|
|
152
152
|
"react": "^18.2.0",
|
|
153
|
-
"react-dom": "^18.
|
|
153
|
+
"react-dom": "^18.2.0",
|
|
154
154
|
"react-test-renderer": "18.3.1",
|
|
155
155
|
"shiki": "^4.4.3",
|
|
156
156
|
"simple-icons": "^16.32.0",
|