dsh-remote-bridge 2.3.3 → 2.3.5

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
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <img alt="Version" src="https://img.shields.io/badge/version-v2.3.3-087f8c">
12
+ <img alt="Version" src="https://img.shields.io/badge/version-v2.3.5-087f8c">
13
13
  <img alt="DSH plugin" src="https://img.shields.io/badge/DeepSeek_Harness-plugin-1f2328">
14
14
  <img alt="Platforms" src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-586069">
15
15
  <img alt="License" src="https://img.shields.io/badge/license-AGPL--3.0-2da44e">
@@ -73,10 +73,10 @@ dsh plugin --profile web add dsh-remote-bridge
73
73
  dsh plugin --profile web add dsh-remote-bridge --registry https://registry.npmmirror.com
74
74
 
75
75
  # 2. tarball from the GitHub release
76
- dsh plugin --profile web add https://github.com/westanke/dsh-remote-bridge/releases/download/v2.3.3/dsh-remote-bridge-v2.3.3.tgz
76
+ dsh plugin --profile web add https://github.com/westanke/dsh-remote-bridge/releases/download/v2.3.5/dsh-remote-bridge-v2.3.5.tgz
77
77
 
78
78
  # 3. tarball from the Gitee release (faster from mainland China)
79
- dsh plugin --profile web add https://gitee.com/westanke/dsh-remote-bridge/releases/download/v2.3.3/dsh-remote-bridge-v2.3.3.tgz
79
+ dsh plugin --profile web add https://gitee.com/westanke/dsh-remote-bridge/releases/download/v2.3.5/dsh-remote-bridge-v2.3.5.tgz
80
80
 
81
81
  npx @deepseek-ai/dsh web
82
82
  ```
@@ -93,7 +93,7 @@ Restart DSH after installation, then open settings — The section is titled **
93
93
  To install a downloaded release archive:
94
94
 
95
95
  ```sh
96
- dsh plugin --profile web add ./dsh-remote-bridge-v2.3.3.tgz
96
+ dsh plugin --profile web add ./dsh-remote-bridge-v2.3.5.tgz
97
97
  ```
98
98
 
99
99
  ## First connection
@@ -327,11 +327,11 @@ pnpm pack
327
327
 
328
328
  `npm pack` produces roughly a **0.25 MB** archive: 2.2.0 dropped the standalone page and its editor dependencies and turned source maps off, down from 1.72 MB.
329
329
 
330
- v2.3.3 was developed against DSH `master@47f943859bef60e4160492346772ded9b24f765a`. CI covers Windows, Ubuntu, and macOS.
330
+ v2.3.5 was developed against DSH `master@47f943859bef60e4160492346772ded9b24f765a`. CI covers Windows, Ubuntu, and macOS.
331
331
 
332
332
  ## Project
333
333
 
334
- - Version: `v2.3.3`
334
+ - Version: `v2.3.5`
335
335
  - Author: upstream [Hakunm](https://github.com/Hakunm); this fork maintained by [westanke](https://github.com/westanke)
336
336
  - Repository: [GitHub](https://github.com/westanke/dsh-remote-bridge) · [Gitee](https://gitee.com/westanke/dsh-remote-bridge)
337
337
  - npm: [`dsh-remote-bridge`](https://www.npmjs.com/package/dsh-remote-bridge) ([mainland-China mirror](https://registry.npmmirror.com/dsh-remote-bridge))
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  </p>
10
10
 
11
11
  <p align="center">
12
- <img alt="Version" src="https://img.shields.io/badge/version-v2.3.3-087f8c">
12
+ <img alt="Version" src="https://img.shields.io/badge/version-v2.3.5-087f8c">
13
13
  <img alt="DSH plugin" src="https://img.shields.io/badge/DeepSeek_Harness-plugin-1f2328">
14
14
  <img alt="Platforms" src="https://img.shields.io/badge/platform-Windows%20%7C%20macOS%20%7C%20Linux-586069">
15
15
  <img alt="License" src="https://img.shields.io/badge/license-AGPL--3.0-2da44e">
@@ -70,10 +70,10 @@ dsh plugin --profile web add dsh-remote-bridge
70
70
  dsh plugin --profile web add dsh-remote-bridge --registry https://registry.npmmirror.com
71
71
 
72
72
  # ② GitHub Release 的 tarball
73
- dsh plugin --profile web add https://github.com/westanke/dsh-remote-bridge/releases/download/v2.3.3/dsh-remote-bridge-v2.3.3.tgz
73
+ dsh plugin --profile web add https://github.com/westanke/dsh-remote-bridge/releases/download/v2.3.5/dsh-remote-bridge-v2.3.5.tgz
74
74
 
75
75
  # ③ Gitee Release 的 tarball(国内访问更快)
76
- dsh plugin --profile web add https://gitee.com/westanke/dsh-remote-bridge/releases/download/v2.3.3/dsh-remote-bridge-v2.3.3.tgz
76
+ dsh plugin --profile web add https://gitee.com/westanke/dsh-remote-bridge/releases/download/v2.3.5/dsh-remote-bridge-v2.3.5.tgz
77
77
 
78
78
  npx @deepseek-ai/dsh web
79
79
  ```
@@ -89,7 +89,7 @@ npx @deepseek-ai/dsh web
89
89
  从 GitHub Release 下载离线安装包时,可直接安装 tarball:
90
90
 
91
91
  ```sh
92
- dsh plugin --profile web add ./dsh-remote-bridge-v2.3.3.tgz
92
+ dsh plugin --profile web add ./dsh-remote-bridge-v2.3.5.tgz
93
93
  ```
94
94
 
95
95
  ## 第一次使用
@@ -319,11 +319,11 @@ pnpm pack
319
319
 
320
320
  `npm pack` 的产物约 **0.25 MB**:2.2.0 删除独立页及其编辑器依赖、并关闭 source map 之后,从 1.72 MB 降下来。
321
321
 
322
- v2.3.3 基于 DSH `master@47f943859bef60e4160492346772ded9b24f765a` 开发,CI 覆盖 Windows、Ubuntu 和 macOS。
322
+ v2.3.5 基于 DSH `master@47f943859bef60e4160492346772ded9b24f765a` 开发,CI 覆盖 Windows、Ubuntu 和 macOS。
323
323
 
324
324
  ## 项目信息
325
325
 
326
- - 当前版本:`v2.3.3`
326
+ - 当前版本:`v2.3.5`
327
327
  - 作者:上游 [Hakunm](https://github.com/Hakunm),本 fork 维护 [westanke](https://github.com/westanke)
328
328
  - 仓库:[GitHub](https://github.com/westanke/dsh-remote-bridge) · [Gitee](https://gitee.com/westanke/dsh-remote-bridge)
329
329
  - npm:[`dsh-remote-bridge`](https://www.npmjs.com/package/dsh-remote-bridge)([国内镜像](https://registry.npmmirror.com/dsh-remote-bridge))
@@ -1,7 +1,7 @@
1
1
  asyncapi: 3.0.0
2
2
  info:
3
3
  title: DeepSeek Harness Mobile Events
4
- version: 2.3.3
4
+ version: 2.3.5
5
5
  description: |
6
6
  Live file and authorized DSH chat events. Reconnect clients must refresh
7
7
  REST state; unbounded replay is not provided.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.1.0
2
2
  info:
3
3
  title: DeepSeek Harness Mobile API
4
- version: 2.3.3
4
+ version: 2.3.5
5
5
  description: Versioned file and chat BFF for mobile and third-party DSH clients. HTTP and HTTPS are both supported.
6
6
  servers:
7
7
  - url: http://127.0.0.1:3090/api/v1
@@ -24,7 +24,7 @@ paths:
24
24
  properties:
25
25
  ok: { type: boolean, const: true }
26
26
  version: { type: string, const: v1 }
27
- pluginVersion: { type: string, const: 2.3.3 }
27
+ pluginVersion: { type: string, const: 2.3.5 }
28
28
  /pairings/exchange:
29
29
  post:
30
30
  security: []
@@ -1005,6 +1005,13 @@ components:
1005
1005
  id: { type: string }
1006
1006
  rootId: { type: string }
1007
1007
  cwd: { $ref: '#/components/schemas/WirePath' }
1008
+ cwdAbsolute:
1009
+ type: string
1010
+ description: >-
1011
+ Absolute path of the session working directory. Optional; older clients
1012
+ ignore it. Needed to compose `@absolute-path` mentions. Note that an
1013
+ empty `cwd` is legal and means the session working directory IS the
1014
+ authorized root itself.
1008
1015
  updatedAt: { type: integer }
1009
1016
  running: { type: boolean }
1010
1017
  blank: { type: boolean }
@@ -4,7 +4,7 @@ plugins {
4
4
  }
5
5
 
6
6
  group = "ai.deepseek.dsh"
7
- version = "2.3.3"
7
+ version = "2.3.5"
8
8
 
9
9
  repositories { mavenCentral() }
10
10
 
package/lib/index.d.ts CHANGED
@@ -1131,6 +1131,22 @@ interface ChatSessionView {
1131
1131
  id: string;
1132
1132
  rootId: string;
1133
1133
  cwd: string;
1134
+ /**
1135
+ * 会话工作目录的**绝对路径**(可选,老客户端会忽略)。
1136
+ *
1137
+ * `cwd` 是**相对授权根**的 wire 路径(列举接口要的正是这个),手机端要往输入框
1138
+ * 里插一条 `@绝对路径` 时却需要绝对路径 —— 而客户端手里没有根的 realPath
1139
+ * (`RootView` 刻意不含它,那是机器信息)。此前 App 拿 `cwd` 去 `/roots/resolve`
1140
+ * 换,可那个端点**要求绝对路径输入**、对相对路径直接 400 —— 于是补全必然失败。
1141
+ *
1142
+ * 这里补的这一个字段就是那条缺失的桥:会话的绝对 cwd 服务端本来就有(`matchRoot`
1143
+ * 的入参就是它),它又一定落在**这台设备已授权**的根内(不匹配的会话压根不会出现在
1144
+ * 列表里),所以给出它不扩大任何可见范围。
1145
+ *
1146
+ * `cwd` 为空字符串是**合法**的:会话工作目录正好就是授权根本身时,
1147
+ * `path.relative(root, root)` 返回空串 —— 客户端必须把它当作「根目录」而不是「没有」。
1148
+ */
1149
+ cwdAbsolute?: string;
1134
1150
  updatedAt: number;
1135
1151
  running: boolean;
1136
1152
  blank: boolean;
package/lib/index.js CHANGED
@@ -244,7 +244,9 @@ var DshChatAdapter = class {
244
244
  const visible = [];
245
245
  for (const session of value.items) {
246
246
  if (archivedSessionIds.has(session.sessionId)) continue;
247
- const match = session.cwd === void 0 ? void 0 : matchRoot(roots, session.cwd);
247
+ const absoluteCwd = session.cwd;
248
+ if (absoluteCwd === void 0) continue;
249
+ const match = matchRoot(roots, absoluteCwd);
248
250
  if (match === void 0) continue;
249
251
  const workspace = workspaces.find((item) => item.rootId === match.root.id && item.path === match.relative);
250
252
  const title = sessionTitle(session);
@@ -252,6 +254,7 @@ var DshChatAdapter = class {
252
254
  id: session.sessionId,
253
255
  rootId: match.root.id,
254
256
  cwd: match.relative,
257
+ cwdAbsolute: absoluteCwd,
255
258
  updatedAt: session.updatedAt,
256
259
  running: session.running,
257
260
  blank: session.blank,
@@ -3239,12 +3242,47 @@ function defaultDisplayName() {
3239
3242
  //#endregion
3240
3243
  //#region src/host/plugin-inventory.ts
3241
3244
  /**
3245
+ * 把 profile 标识归一化成 profile 名。
3246
+ *
3247
+ * 内核接受**两种**写法,两者都合法:
3248
+ *
3249
+ * - `--profile web` —— profile 名;
3250
+ * - `--profile /home/u/.dsh/profiles/web` —— profile 的绝对目录。内核启动器文档里
3251
+ * 写的正是 `--profile ${basename(profileDir)}`,**内核自己会取 basename**。
3252
+ *
3253
+ * 本插件此前只认第一种,于是把第二种的**整条路径**当成了 profile 名。而 `path.join`
3254
+ * 并不会因为后面一段是绝对路径就重置(那是 `path.resolve` 的行为),于是拼出:
3255
+ *
3256
+ * /home/u/.dsh/profiles/home/u/.dsh/profiles/desktop
3257
+ *
3258
+ * —— 必然 ENOENT。**官方 Electron 桌面版恰好用第二种启动内核**,所以在桌面版里,
3259
+ * 手机上只会看到「服务器读不出插件清单:package.json 可能损坏、缺失或没有读取权限」,
3260
+ * 而磁盘上的 package.json 完好无损、权限也对。web 版(`dsh web` / `--profile web`)
3261
+ * 走的是名字形式,不受影响 —— 这就是这个 bug 能潜伏到桌面版才暴露的原因。
3262
+ *
3263
+ * 归一化只做一件事:**含路径分隔符时取最后一段**;不含则原样返回。于是
3264
+ * 「名字」「绝对目录」「相对目录」「Windows 反斜杠路径」「末尾带斜杠」五者同归一条规则。
3265
+ */
3266
+ function normalizeProfileName(value) {
3267
+ const trimmed = value.trim();
3268
+ if (trimmed === "") return null;
3269
+ if (!/[/\\]/.test(trimmed)) return trimmed;
3270
+ const withoutTrailing = trimmed.replace(/[/\\]+$/, "");
3271
+ if (withoutTrailing === "") return null;
3272
+ const cut = Math.max(withoutTrailing.lastIndexOf("/"), withoutTrailing.lastIndexOf("\\"));
3273
+ const base = withoutTrailing.slice(cut + 1);
3274
+ return base === "" ? null : base;
3275
+ }
3276
+ /**
3242
3277
  * 解析当前 profile 名。
3243
3278
  *
3244
3279
  * 依次尝试:`DSH_PROFILE` 环境变量 → `--profile=<name>` → `--profile <name>`
3245
3280
  * → **子命令简写**(`dsh web` 等价于 `dsh --profile web`)。
3246
3281
  * 都拿不到时返回 null(调用方不要猜,猜错会读到另一个 profile 的清单)。
3247
3282
  *
3283
+ * **四个取值来源一律过 `normalizeProfileName`**:它们都可能装着一个 profile 目录
3284
+ * 而不是名字(官方 Electron 桌面版就是),见该函数的说明。
3285
+ *
3248
3286
  * 最后那条简写路径是补上的一个真 bug:内核的启动器文档写得很清楚 ——
3249
3287
  *
3250
3288
  * > `dsh <name>` abbreviates `dsh --profile <name>`;`dsh web` boots the web
@@ -3258,15 +3296,15 @@ function resolveProfileName(input = {}) {
3258
3296
  const env = input.env ?? process.env;
3259
3297
  const argv = input.argv ?? process.argv;
3260
3298
  const fromEnv = env.DSH_PROFILE?.trim();
3261
- if (fromEnv) return fromEnv;
3299
+ if (fromEnv) return normalizeProfileName(fromEnv);
3262
3300
  for (const arg of argv) if (arg.startsWith("--profile=")) {
3263
3301
  const value = arg.slice(10).trim();
3264
- if (value) return value;
3302
+ if (value) return normalizeProfileName(value);
3265
3303
  }
3266
3304
  const index = argv.indexOf("--profile");
3267
3305
  if (index >= 0) {
3268
3306
  const value = argv[index + 1]?.trim();
3269
- if (value && !value.startsWith("-")) return value;
3307
+ if (value && !value.startsWith("-")) return normalizeProfileName(value);
3270
3308
  return null;
3271
3309
  }
3272
3310
  return profileFromSubcommand(argv);
@@ -3285,6 +3323,9 @@ function resolveProfileName(input = {}) {
3285
3323
  *
3286
3324
  * `plugin` 单独排除:`dsh plugin add xxx` 是管理插件依赖的命令,
3287
3325
  * 它**不启动任何 profile**,把它当 profile 名会去读一个不存在的目录。
3326
+ *
3327
+ * 取到的 token 同样过 `normalizeProfileName`:桌面版可能把这个位置填成 profile
3328
+ * 目录的绝对路径(`--profile <dir>` 的等价位置参数写法)。
3288
3329
  */
3289
3330
  function profileFromSubcommand(argv) {
3290
3331
  const start = argv.findIndex((arg) => /(^|[/\\])dsh(\.js|\.cjs|\.mjs)?$/.test(arg));
@@ -3299,7 +3340,7 @@ function profileFromSubcommand(argv) {
3299
3340
  i += arg.includes("=") ? 1 : 2;
3300
3341
  continue;
3301
3342
  }
3302
- return arg === "plugin" ? null : arg;
3343
+ return arg === "plugin" ? null : normalizeProfileName(arg);
3303
3344
  }
3304
3345
  return null;
3305
3346
  }
@@ -3641,7 +3682,7 @@ async function inspectResolvedPath(root, wirePath) {
3641
3682
  }
3642
3683
  //#endregion
3643
3684
  //#region src/shared/version.ts
3644
- const PLUGIN_VERSION = "2.3.3";
3685
+ const PLUGIN_VERSION = "2.3.5";
3645
3686
  //#endregion
3646
3687
  //#region src/host/router.ts
3647
3688
  var ApiRouter = class {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-remote-bridge",
3
- "version": "2.3.3",
3
+ "version": "2.3.5",
4
4
  "description": "Versioned REST bridge for DeepSeek Harness: remote access for trusted clients (chat, files, devices) plus a Phone-settings panel inside the DSH WebUI.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.19.0",