dsh-workbuddy-connect 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.en.md CHANGED
@@ -34,11 +34,14 @@ Prerequisite: the WorkBuddy desktop app is installed and signed in (the plugin r
34
34
 
35
35
  | Plugin | Required DSH core | Desktop app |
36
36
  |---|---|---|
37
- | **0.3.0+** | `0.1.2-rc.1` or newer | `2.0.5`+ recommended |
37
+ | **0.3.2+** | `0.1.5-rc.1` or newer | wait for the app's bundled core to follow |
38
+ | **0.3.0 – 0.3.1** | `0.1.2-rc.1` | `2.0.5`+ recommended |
38
39
  | **0.2.6** | `0.1.1-rc.2` (older line) | `2.0.3` / `2.0.4` |
39
40
 
40
- - On DSH `0.1.2-rc.1` or newer, just install the latest: `dsh plugin --profile web add dsh-workbuddy-connect`
41
+ - On DSH `0.1.5-rc.1` or newer, just install the latest: `dsh plugin --profile web add dsh-workbuddy-connect`
42
+ - Still on DSH `0.1.2-rc.1`? Stay on `0.3.1`: `dsh plugin --profile web add dsh-workbuddy-connect@0.3.1`
41
43
  - Still on DSH `0.1.1-rc.2`? Stay on the older release: `dsh plugin --profile web add dsh-workbuddy-connect@0.2.6`
44
+ - The desktop app (`2.0.5` today, bundled core still `0.1.2-rc.1`) should stay on `0.3.1` until its bundled core reaches `0.1.5`
42
45
 
43
46
  The plugin runs under all three DSH interfaces: **Web**, **Desktop**, and **TUI**. Pick the install command that matches the profile you use.
44
47
 
@@ -64,7 +67,7 @@ dsh plugin --profile dsh-tui add dsh-workbuddy-connect
64
67
  dsh --profile dsh-tui
65
68
  ```
66
69
 
67
- > **TUI users should stay on 0.2.6**: in our testing, installing this plugin 0.3.0 on the TUI profile crashes startup with `events is not iterable` — the terminal UI package (`@deepseek-harness-tui/dsh-tui`) has not been adapted to the new DSH core yet (the fix is committed upstream, unreleased). We recommend TUI users keep DSH `0.1.1-rc.2` and plugin `0.2.6` for now, and upgrade to 0.3.0 once the terminal UI ships an adapted release.
70
+ > **TUI users, check the version pairing**: the terminal UI package (`@deepseek-harness-tui/dsh-tui`) must be **`0.10.0-beta.5` or newer** — older versions fail at startup with `events is not iterable` when this plugin is installed. Update the shell first (via its built-in update command or a fresh install), then add this plugin; the newest release is a beta, and a stable one will work the same way.
68
71
 
69
72
  > Note: the `dsh-tui` profile requires pnpm 11 to install packages (a different pnpm on PATH fails with `ERR_PNPM_UNEXPECTED_STORE` — use `npx pnpm@11`).
70
73
 
@@ -76,7 +79,7 @@ After installing, switch to a WorkBuddy model in the model picker of the interfa
76
79
 
77
80
  ## Known limitations
78
81
 
79
- - Verified on macOS with the DSH Web / Desktop profiles (`0.1.2-rc.1`+, Node 22+); TUI pending a terminal-UI release adapted to 0.1.2 (see the Install section). Windows probes Local and Roaming AppData in order; WSL first reads credentials from the mounted Windows user profile. If the Windows and Linux user names differ and Windows environment variables are not forwarded into WSL, point `WORKBUDDY_AUTH_FILE` at the actual file.
82
+ - Verified on macOS with the DSH Web / Desktop / TUI profiles (as of 0.3.2 this requires `0.1.5-rc.1`+ and Node 22+; TUI requires the terminal UI package `0.10.0-beta.5` or newer — see the Install section). Windows probes Local and Roaming AppData in order; WSL first reads credentials from the mounted Windows user profile. If the Windows and Linux user names differ and Windows environment variables are not forwarded into WSL, point `WORKBUDDY_AUTH_FILE` at the actual file.
80
83
  - Relies on WorkBuddy client interfaces (not a public API); the plugin may need updates as WorkBuddy changes.
81
84
 
82
85
  ## Disclaimer
package/README.md CHANGED
@@ -44,11 +44,14 @@
44
44
 
45
45
  | 插件版本 | 要求的 DSH 核心 | 桌面 App |
46
46
  |---|---|---|
47
- | **0.3.0+** | `0.1.2-rc.1` 及以上 | 建议 `2.0.5`+ |
47
+ | **0.3.2+** | `0.1.5-rc.1` 及以上 | 待 App 内置核心跟进 |
48
+ | **0.3.0 – 0.3.1** | `0.1.2-rc.1` | `2.0.5`+ |
48
49
  | **0.2.6** | `0.1.1-rc.2`(旧线) | `2.0.3` / `2.0.4` |
49
50
 
50
- - DSH `0.1.2-rc.1` 及以上的用户,正常安装最新版即可:`dsh plugin --profile web add dsh-workbuddy-connect`
51
- - 还在用 DSH `0.1.1-rc.2` 的用户,请安装旧版本并停留在 `0.2.6`:`dsh plugin --profile web add dsh-workbuddy-connect@0.2.6`
51
+ - DSH `0.1.5-rc.1` 及以上的用户,正常安装最新版即可:`dsh plugin --profile web add dsh-workbuddy-connect`
52
+ - 还在用 DSH `0.1.2-rc.1` 的用户,请停留在 `0.3.1`:`dsh plugin --profile web add dsh-workbuddy-connect@0.3.1`
53
+ - 还在用 DSH `0.1.1-rc.2` 的用户,请停留在 `0.2.6`:`dsh plugin --profile web add dsh-workbuddy-connect@0.2.6`
54
+ - 桌面 App(当前 `2.0.5`,内置核心仍为 `0.1.2-rc.1`)请在 App 内核跟进 `0.1.5` 前继续使用 `0.3.1`
52
55
 
53
56
  插件在三种 DSH 界面下均可运行:**Web**、**Desktop**、**TUI**。根据你使用的 profile 选对应命令安装。
54
57
 
@@ -74,7 +77,7 @@ dsh plugin --profile dsh-tui add dsh-workbuddy-connect
74
77
  dsh --profile dsh-tui
75
78
  ```
76
79
 
77
- > **TUI 用户请先留在 0.2.6**:实测在 TUI 上安装本插件 0.3.0 会导致启动崩溃(报 `events is not iterable`),原因是终端界面插件 `@deepseek-harness-tui/dsh-tui` 还没适配 DSH 新核心(修复已提交,尚未发版)。建议 TUI 用户暂时继续使用 DSH `0.1.1-rc.2` 和本插件 `0.2.6`,等终端界面插件发布适配版本后再升级 0.3.0。
80
+ > **TUI 用户请注意版本搭配**:终端界面插件 `@deepseek-harness-tui/dsh-tui` 需要 **`0.10.0-beta.5` 及以上**(更早的版本装了本插件会启动失败,报 `events is not iterable`)。请先用 TUI 自带的更新方式把壳升到 beta.5 及以上,再安装本插件;当前最新的是 beta 版,正式版发布后同样可用。
78
81
 
79
82
  > 提示:`dsh-tui` profile 需用 pnpm 11 安装(PATH 里是其他版本会报 `ERR_PNPM_UNEXPECTED_STORE`,用 `npx pnpm@11` 即可)。
80
83
 
@@ -86,7 +89,7 @@ dsh --profile dsh-tui
86
89
 
87
90
  ## 已知限制
88
91
 
89
- - 在 macOS 的 DSH Web / Desktop profile(`0.1.2-rc.1`+、Node 22+)下验证通过;TUI 待终端界面插件发布 0.1.2 适配版后验证(见安装章节说明)。Windows 会依次探测 Local 与 Roaming AppData;WSL 会优先从挂载的 Windows 用户目录读取登录凭据。若 Windows 与 Linux 用户名不同且 Windows 环境变量未传入 WSL,请通过 `WORKBUDDY_AUTH_FILE` 指定实际位置。
92
+ - 在 macOS 的 DSH Web / Desktop / TUI 下验证通过(0.3.2 起要求 `0.1.5-rc.1`+、Node 22+;TUI 需终端界面插件 `0.10.0-beta.5` 及以上,见安装章节说明)。Windows 会依次探测 Local 与 Roaming AppData;WSL 会优先从挂载的 Windows 用户目录读取登录凭据。若 Windows 与 Linux 用户名不同且 Windows 环境变量未传入 WSL,请通过 `WORKBUDDY_AUTH_FILE` 指定实际位置。
90
93
  - 依赖 WorkBuddy 客户端接口(非官方开放 API),WorkBuddy 更新后插件可能需要随之调整。
91
94
 
92
95
  ## 免责声明
package/lib/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { S as workbuddyOwnAuthPath, a as readHostHeartbeat, c as WORKBUDDY_CONNECT_VERSION, l as WorkBuddyUpstreamClient, m as FALLBACK_WORKBUDDY_MODELS, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, v as WorkBuddyCredentialStore } from "./host-heartbeat-CM7AW7vZ.js";
2
+ import { S as workbuddyOwnAuthPath, a as readHostHeartbeat, c as WORKBUDDY_CONNECT_VERSION, l as WorkBuddyUpstreamClient, m as FALLBACK_WORKBUDDY_MODELS, o as workbuddyHostHeartbeatPath, r as isHeartbeatProcessAlive, v as WorkBuddyCredentialStore } from "./host-heartbeat-BSsKUoB8.js";
3
3
  import { realpathSync } from "node:fs";
4
4
  import { fileURLToPath } from "node:url";
5
5
  //#region src/bin.ts
@@ -142,10 +142,21 @@ function parseOwnDocument(text) {
142
142
  const document = parsed;
143
143
  if (document["version"] !== OWN_FORMAT_VERSION) return void 0;
144
144
  if (typeof document["credential"] !== "object" || document["credential"] === null) return void 0;
145
- const credential = parseWorkBuddyAuth(JSON.stringify({ auth: document["credential"] }));
146
- if (credential === void 0) return void 0;
145
+ const stored = document["credential"];
146
+ const accessToken = typeof stored["accessToken"] === "string" ? stored["accessToken"] : "";
147
+ if (accessToken === "") return void 0;
148
+ const refreshExpiresAtMs = typeof stored["refreshExpiresAtMs"] === "number" ? stored["refreshExpiresAtMs"] : void 0;
149
+ const enterpriseId = optionalString(stored["enterpriseId"]);
150
+ const nickname = optionalString(stored["nickname"]);
147
151
  return {
148
- ...credential,
152
+ accessToken,
153
+ refreshToken: typeof stored["refreshToken"] === "string" ? stored["refreshToken"] : "",
154
+ expiresAtMs: typeof stored["expiresAtMs"] === "number" ? stored["expiresAtMs"] : 0,
155
+ ...refreshExpiresAtMs === void 0 ? {} : { refreshExpiresAtMs },
156
+ domain: optionalString(stored["domain"]) ?? "",
157
+ uid: optionalString(stored["uid"]) ?? "",
158
+ ...enterpriseId === void 0 ? {} : { enterpriseId },
159
+ ...nickname === void 0 ? {} : { nickname },
149
160
  source: "dsh"
150
161
  };
151
162
  }
@@ -1041,7 +1052,7 @@ var WorkBuddyUpstreamClient = class {
1041
1052
  };
1042
1053
  //#endregion
1043
1054
  //#region src/version.ts
1044
- const WORKBUDDY_CONNECT_VERSION = "0.3.0";
1055
+ const WORKBUDDY_CONNECT_VERSION = "0.3.2";
1045
1056
  //#endregion
1046
1057
  //#region src/host-heartbeat.ts
1047
1058
  /**
package/lib/index.d.ts CHANGED
@@ -335,6 +335,13 @@ interface WorkBuddyAdapter {
335
335
  * Assemble the adapter. The provider's `getModels` reads the live catalog,
336
336
  * and every model's `baseUrl` is re-resolved per read so the shim's
337
337
  * ephemeral port applies from the first snapshot after startup.
338
+ *
339
+ * The profile is constructed by hand rather than through dsh-llm-pi-ai's
340
+ * internal `resolveProfiles()`: that helper is not part of the package's
341
+ * public export surface (root entry, `lib/` deep imports blocked by the
342
+ * exports map, `src/` not shipped), so hand-assembly is the only supported
343
+ * path and every newly required field must be adopted here explicitly —
344
+ * `modelErrors` since 0.1.5-alpha.2 (#12).
338
345
  */
339
346
  declare function createWorkBuddyAdapter(options: WorkBuddyAdapterOptions): WorkBuddyAdapter;
340
347
  //#endregion
package/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { S as workbuddyOwnAuthPath, _ as WORKBUDDY_AUTH_FILE_ENV, a as readHostHeartbeat, b as defaultDesktopAuthPath, d as normalizeCredits, f as prepareChatBody, g as WORKBUDDY_AUTH_FILENAME, h as WorkBuddyCatalog, i as processStartTimeMs, l as WorkBuddyUpstreamClient, m as FALLBACK_WORKBUDDY_MODELS, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as regionOf, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as classifyUpstreamError, v as WorkBuddyCredentialStore, x as parseWorkBuddyAuth, y as defaultDesktopAuthCandidates } from "./host-heartbeat-CM7AW7vZ.js";
1
+ import { S as workbuddyOwnAuthPath, _ as WORKBUDDY_AUTH_FILE_ENV, a as readHostHeartbeat, b as defaultDesktopAuthPath, d as normalizeCredits, f as prepareChatBody, g as WORKBUDDY_AUTH_FILENAME, h as WorkBuddyCatalog, i as processStartTimeMs, l as WorkBuddyUpstreamClient, m as FALLBACK_WORKBUDDY_MODELS, n as clearHostHeartbeat, o as workbuddyHostHeartbeatPath, p as regionOf, r as isHeartbeatProcessAlive, s as writeHostHeartbeat, t as WORKBUDDY_HOST_HEARTBEAT_FILENAME, u as classifyUpstreamError, v as WorkBuddyCredentialStore, x as parseWorkBuddyAuth, y as defaultDesktopAuthCandidates } from "./host-heartbeat-BSsKUoB8.js";
2
2
  import z from "@deepseek-ai/schemastery";
3
3
  import { createProvider } from "@earendil-works/pi-ai";
4
4
  import { openAICompletionsApi } from "@earendil-works/pi-ai/api/openai-completions.lazy";
@@ -158,6 +158,13 @@ function toPiModel(info, baseUrl) {
158
158
  * Assemble the adapter. The provider's `getModels` reads the live catalog,
159
159
  * and every model's `baseUrl` is re-resolved per read so the shim's
160
160
  * ephemeral port applies from the first snapshot after startup.
161
+ *
162
+ * The profile is constructed by hand rather than through dsh-llm-pi-ai's
163
+ * internal `resolveProfiles()`: that helper is not part of the package's
164
+ * public export surface (root entry, `lib/` deep imports blocked by the
165
+ * exports map, `src/` not shipped), so hand-assembly is the only supported
166
+ * path and every newly required field must be adopted here explicitly —
167
+ * `modelErrors` since 0.1.5-alpha.2 (#12).
161
168
  */
162
169
  function createWorkBuddyAdapter(options) {
163
170
  const { shim, store, catalog, resolveAttachments } = options;
@@ -190,6 +197,7 @@ function createWorkBuddyAdapter(options) {
190
197
  streamIdleTimeoutMs: WORKBUDDY_STREAM_IDLE_TIMEOUT_MS,
191
198
  retryPolicy: resolveRetryPolicy(void 0, "dsh-workbuddy-connect retryPolicy"),
192
199
  configuredMaxTokens: /* @__PURE__ */ new Map(),
200
+ modelErrors: /* @__PURE__ */ new Map(),
193
201
  ...REQUEST_IMAGE_BUDGETS,
194
202
  piProvider: provider
195
203
  };
@@ -253,25 +261,15 @@ var WorkBuddyPiAiAdapter = class extends PiAiAdapter {
253
261
  }
254
262
  };
255
263
  //#endregion
256
- //#region src/shim.ts
264
+ //#region src/loopback.ts
257
265
  /**
258
- * Loopback OpenAI-compatible endpoint. The pi-ai provider points here; the
259
- * shim applies the WorkBuddy wire quirks (forced streaming, string
260
- * `tool_choice`, CLI-shaped headers) and forwards to the real upstream.
261
- * It binds 127.0.0.1 only and never serves another interface.
262
- *
263
- * Inbound hardening: the loopback bind alone is not a trust boundary (any
264
- * local process or a DNS-rebinding page can reach 127.0.0.1), so every
265
- * request must carry a loopback Host header, browser-sent Origins must be
266
- * loopback, chat POSTs must be application/json, and the Authorization
267
- * header must carry the shim's per-process shared secret. The plugin's
268
- * own client satisfies all four by construction; local attackers cannot
269
- * read the secret out of the plugin process's memory.
266
+ * Shared loopback gates for the plugin's local HTTP surfaces: the loopback
267
+ * shim and the same-origin web-status route. Both are only ever meant to be
268
+ * addressed through the machine's loopback interface.
270
269
  *
271
- * @module dsh-workbuddy-connect/shim
270
+ * @module dsh-workbuddy-connect/loopback
272
271
  */
273
- const REQUEST_BODY_LIMIT = 67108864;
274
- /** Loopback hostnames the shim's own in-process client uses. */
272
+ /** Loopback hostnames a local plugin surface may be addressed by. */
275
273
  const LOOPBACK_HOSTS = /* @__PURE__ */ new Set([
276
274
  "127.0.0.1",
277
275
  "localhost",
@@ -285,7 +283,7 @@ function hostnameOfHost(host) {
285
283
  return end === -1 ? hostname : hostname.slice(0, end + 1);
286
284
  }
287
285
  const colon = hostname.lastIndexOf(":");
288
- if (colon !== -1 && /^\d+$/.test(hostname.slice(colon + 1))) hostname = hostname.slice(0, colon);
286
+ if (colon !== -1 && !hostname.slice(0, colon).includes(":") && /^\d+$/.test(hostname.slice(colon + 1))) hostname = hostname.slice(0, colon);
289
287
  return hostname;
290
288
  }
291
289
  /**
@@ -310,6 +308,25 @@ function originIsLoopback(origin) {
310
308
  return false;
311
309
  }
312
310
  }
311
+ //#endregion
312
+ //#region src/shim.ts
313
+ /**
314
+ * Loopback OpenAI-compatible endpoint. The pi-ai provider points here; the
315
+ * shim applies the WorkBuddy wire quirks (forced streaming, string
316
+ * `tool_choice`, CLI-shaped headers) and forwards to the real upstream.
317
+ * It binds 127.0.0.1 only and never serves another interface.
318
+ *
319
+ * Inbound hardening: the loopback bind alone is not a trust boundary (any
320
+ * local process or a DNS-rebinding page can reach 127.0.0.1), so every
321
+ * request must carry a loopback Host header, browser-sent Origins must be
322
+ * loopback, chat POSTs must be application/json, and the Authorization
323
+ * header must carry the shim's per-process shared secret. The plugin's
324
+ * own client satisfies all four by construction; local attackers cannot
325
+ * read the secret out of the plugin process's memory.
326
+ *
327
+ * @module dsh-workbuddy-connect/shim
328
+ */
329
+ const REQUEST_BODY_LIMIT = 67108864;
313
330
  /** Chat-completion POSTs must carry a JSON body type (simple-request CSRF drops here). */
314
331
  function isJsonContentType(req) {
315
332
  const type = req.headers["content-type"];
@@ -500,16 +517,14 @@ function json(res, status, body) {
500
517
  });
501
518
  res.end(payload);
502
519
  }
503
- /** Loopback browser origins only; other devices are refused until trusted origins exist. */
504
- function loopbackOrigin(req) {
505
- const origin = req.headers.origin;
506
- if (origin === void 0) return true;
507
- try {
508
- const { hostname } = new URL(origin);
509
- return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
510
- } catch {
511
- return false;
512
- }
520
+ /**
521
+ * The request must be addressed to the loopback interface, and a
522
+ * browser-attached Origin must be loopback too. The Host check drops
523
+ * DNS-rebinding pages (their Host is the attacker's domain, not loopback);
524
+ * the card's same-origin fetches carry no Origin and pass on Host alone.
525
+ */
526
+ function loopbackRequest(req) {
527
+ return hostIsLoopback(req.headers.host) && originIsLoopback(req.headers.origin);
513
528
  }
514
529
  /**
515
530
  * Assemble the card's status document. Sign-in state is read-only; credit is
@@ -557,27 +572,31 @@ async function workBuddyWebStatus(deps) {
557
572
  }
558
573
  return statusWithModels;
559
574
  }
575
+ /** The status route's request handler, extracted so tests can mount it on a bare server. */
576
+ function workBuddyStatusHandler(deps) {
577
+ return async (req, res) => {
578
+ if (req.method !== "GET") {
579
+ json(res, 405, { error: "method not allowed" });
580
+ return;
581
+ }
582
+ if (!loopbackRequest(req)) {
583
+ json(res, 403, { error: "request-not-trusted" });
584
+ return;
585
+ }
586
+ try {
587
+ json(res, 200, await workBuddyWebStatus(deps));
588
+ } catch (error) {
589
+ json(res, 500, { error: safeMessage(error) });
590
+ }
591
+ };
592
+ }
560
593
  /** Mount the GET status route on an optional webServer context. */
561
594
  function registerWorkBuddyStatusRoute(ctx, deps) {
562
595
  ctx.effect(() => {
563
596
  const dispose = ctx.webServer.register({
564
597
  kind: "exact",
565
598
  path: WORKBUDDY_STATUS_PATH,
566
- handler: async (req, res) => {
567
- if (req.method !== "GET") {
568
- json(res, 405, { error: "method not allowed" });
569
- return;
570
- }
571
- if (!loopbackOrigin(req)) {
572
- json(res, 403, { error: "origin-not-trusted" });
573
- return;
574
- }
575
- try {
576
- json(res, 200, await workBuddyWebStatus(deps));
577
- } catch (error) {
578
- json(res, 500, { error: safeMessage(error) });
579
- }
580
- }
599
+ handler: workBuddyStatusHandler(deps)
581
600
  });
582
601
  return () => {
583
602
  dispose();
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "dsh-workbuddy-connect",
3
3
  "displayName": "DSH WorkBuddy Connect",
4
4
  "description": "将 WorkBuddy 桌面 App 包含的模型自动接入 DeepSeek Harness — bring WorkBuddy desktop app models into DeepSeek Harness with zero configuration.",
5
- "version": "0.3.0",
5
+ "version": "0.3.2",
6
6
  "author": "corrinehu",
7
7
  "keywords": [
8
8
  "dsh-plugin",
@@ -64,32 +64,32 @@
64
64
  }
65
65
  },
66
66
  "peerDependencies": {
67
- "@earendil-works/pi-ai": "^0.84.2",
67
+ "@earendil-works/pi-ai": "^0.85.1",
68
68
  "@deepseek-ai/cordis": "^4.0.2",
69
- "@deepseek-ai/dsh-atomic-write": "^0.1.2-rc.1",
70
- "@deepseek-ai/dsh-attachment": "^0.1.2-rc.1",
71
- "@deepseek-ai/dsh-home-paths": "^0.1.2-rc.1",
72
- "@deepseek-ai/dsh-host-webserver": "^0.1.2-rc.1",
73
- "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
74
- "@deepseek-ai/dsh-llm-pi-ai": "^0.1.2-rc.1",
75
- "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
69
+ "@deepseek-ai/dsh-atomic-write": "^0.1.5-rc.1",
70
+ "@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
71
+ "@deepseek-ai/dsh-home-paths": "^0.1.5-rc.1",
72
+ "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
73
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
74
+ "@deepseek-ai/dsh-llm-pi-ai": "^0.1.5-rc.1",
75
+ "@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
76
76
  "@deepseek-ai/schemastery": "^3.18.2",
77
77
  "react": "^18.2.0"
78
78
  },
79
79
  "devDependencies": {
80
- "@earendil-works/pi-ai": "^0.84.2",
80
+ "@earendil-works/pi-ai": "^0.85.1",
81
81
  "@deepseek-ai/cordis": "^4.0.2",
82
- "@deepseek-ai/dsh-atomic-write": "^0.1.2-rc.1",
83
- "@deepseek-ai/dsh-attachment": "^0.1.2-rc.1",
84
- "@deepseek-ai/dsh-client-locale": "^0.1.2-rc.1",
85
- "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.2-rc.1",
86
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-rc.1",
87
- "@deepseek-ai/dsh-credentials": "^0.1.2-rc.1",
88
- "@deepseek-ai/dsh-home-paths": "^0.1.2-rc.1",
89
- "@deepseek-ai/dsh-host-webserver": "^0.1.2-rc.1",
90
- "@deepseek-ai/dsh-llm": "^0.1.2-rc.1",
91
- "@deepseek-ai/dsh-llm-pi-ai": "^0.1.2-rc.1",
92
- "@deepseek-ai/dsh-settings": "^0.1.2-rc.1",
82
+ "@deepseek-ai/dsh-atomic-write": "^0.1.5-rc.1",
83
+ "@deepseek-ai/dsh-attachment": "^0.1.5-rc.1",
84
+ "@deepseek-ai/dsh-client-locale": "^0.1.5-rc.1",
85
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.5-rc.1",
86
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.1",
87
+ "@deepseek-ai/dsh-credentials": "^0.1.5-rc.1",
88
+ "@deepseek-ai/dsh-home-paths": "^0.1.5-rc.1",
89
+ "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.1",
90
+ "@deepseek-ai/dsh-llm": "^0.1.5-rc.1",
91
+ "@deepseek-ai/dsh-llm-pi-ai": "^0.1.5-rc.1",
92
+ "@deepseek-ai/dsh-settings": "^0.1.5-rc.1",
93
93
  "@deepseek-ai/schemastery": "^3.18.2",
94
94
  "@types/node": "^22.20.0",
95
95
  "@types/react": "~18.3.1",
@@ -97,6 +97,6 @@
97
97
  "tsdown": "^0.22.2",
98
98
  "typescript": "^5.9.3",
99
99
  "vitest": "^4.1.8",
100
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-rc.1"
100
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.1"
101
101
  }
102
102
  }