@dsh-electron/dsh-plugin-multi-root-workspace 0.1.1 → 0.1.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/CHANGELOG.en.md +14 -2
- package/CHANGELOG.md +14 -2
- package/README.en.md +8 -6
- package/README.md +8 -6
- package/lib/client.js +133 -14
- package/lib/client.js.map +1 -1
- package/lib/{compat-nFYqN5wt.js → compat-CRdv0vPw.js} +6 -1
- package/lib/compat.js +1 -1
- package/lib/index.js +2 -2
- package/lib/{instructions-BRGoC82G.js → instructions-Cn1Jj5Xi.js} +79 -11
- package/lib/instructions.js +1 -1
- package/lib/types/client/panel-client.d.ts +0 -2
- package/lib/types/compat/client-icons.d.ts +40 -0
- package/lib/types/compat/client-session.d.ts +32 -0
- package/lib/types/compat/dsh-version.d.ts +1 -1
- package/lib/types/compat/llm-message.d.ts +39 -1
- package/lib/types/compat/tool-result.d.ts +29 -0
- package/lib/types/instructions.d.ts +4 -3
- package/package.json +15 -15
package/CHANGELOG.en.md
CHANGED
|
@@ -10,7 +10,18 @@ This file records the user-visible changes of every **released** version.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## [0.1.2] - 2026-09-22
|
|
14
|
+
|
|
15
|
+
With the exact allowlist contract from `v0.1.1` unchanged, the supported upstream runtimes grow to `0.1.6-alpha.2` and `0.1.7-alpha.1`; the reasoning is still [ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md).
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **Support for the upstream runtime `0.1.6-alpha.2`**, alongside `0.1.5-rc.2` and `0.1.6-alpha.1`. `confine` stays asynchronous and the instruction renderer keeps the `0.1.6-alpha.1` name; the client current-session id now comes from the catalog row's `retainedBy.mainView` (see Fixed). The development pin remains `0.1.5-rc.2`.
|
|
20
|
+
- **Support for the upstream runtime `0.1.7-alpha.1`**. `confine` and the instruction renderer keep their previous shapes, but this release needs adapters: session format 4 rejects `kind: 'plugin'`, so additional-root instructions use this plugin's own source kind `multi-root-workspace` (format 3 and earlier still use `plugin`); the tool-failure bit moved from the content block onto the message; panel icons moved from pixel names to the Regular weight; in-process boot uses `createRuntimeResolution` plus `PluginPackages`; bash execution moved from `shell.run` to `shell.execute().result()`. This release's `dsh` depends on cordis `^4.0.3`, and a probe must pin cordis to that version — two copies of `@deepseek-ai/dsh-tools` make the tool scheduler's Symbol miss, and tool calls die on the first step. The development pin remains `0.1.5-rc.2`.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **An open session on `0.1.6-alpha.2` was shown as "No active session"** in the Workspace Folders panel. That release dropped `current` from the Session list snapshot; the session on screen is the catalog row whose `retainedBy.mainView` is positive, because the main view retains it with source `mainView`. `src/compat/client-session.ts` probes both shapes structurally. A populated catalog with nobody retained still shows the empty state and never falls back to `ids[0]`.
|
|
14
25
|
|
|
15
26
|
## [0.1.1] - 2026-09-16
|
|
16
27
|
|
|
@@ -72,6 +83,7 @@ The first release: the three MVP milestones (M1–M3).
|
|
|
72
83
|
|
|
73
84
|
- All eight findings of the pre-release external review (three of them release-blocking) are fixed, each with a regression test: a registered directory replaced by a symlink transplanting its authority (which introduced `recordedPath` — **re-resolving a path is not re-authorizing it**), concurrent registry mutations losing a write or reviving a revoked grant (per-primary-root mutations are serialized), a refresh not re-checking directories, a typed path being overwritten by the directory picker, the `reveal` response contract and failure code, duplicate ids not validated, the primary root missing from nesting validation, and CI testing before building.
|
|
74
85
|
|
|
75
|
-
[Unreleased]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.
|
|
86
|
+
[Unreleased]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.2...HEAD
|
|
87
|
+
[0.1.2]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.1...v0.1.2
|
|
76
88
|
[0.1.1]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.0...v0.1.1
|
|
77
89
|
[0.1.0]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/tag/v0.1.0
|
package/CHANGELOG.md
CHANGED
|
@@ -10,7 +10,18 @@ English: [CHANGELOG.en.md](./CHANGELOG.en.md)
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
## [0.1.2] - 2026-09-22
|
|
14
|
+
|
|
15
|
+
在 `v0.1.1` 的精确 allowlist 契约不变的前提下,把受支持的上游运行时扩展到 `0.1.6-alpha.2` 与 `0.1.7-alpha.1`;设计取舍仍见 [ADR-0009](./docs/decisions/ADR-0009-dsh-compat-contract.md)。
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **支持上游运行时 `0.1.6-alpha.2`**,与 `0.1.5-rc.2`、`0.1.6-alpha.1` 一起进 allowlist。该版本的 `confine` 异步形状与 instruction renderer 名字与 `0.1.6-alpha.1` 相同;客户端当前会话改从目录行的 `retainedBy.mainView` 读取(见 Fixed)。开发 pin 仍是 `0.1.5-rc.2`。
|
|
20
|
+
- **支持上游运行时 `0.1.7-alpha.1`**。`confine` 与 instruction renderer 的形状没变,但这一版有几处必须适配:session format 4 不再接受 `kind: 'plugin'`,附加根指令改用本插件自己的 source kind `multi-root-workspace`(format 3 及更早仍是 `plugin`);工具失败位从 content block 移到消息本身;面板图标从像素命名改为 Regular 线宽;进程内启动改为 `createRuntimeResolution` + `PluginPackages`;bash 执行从 `shell.run` 改为 `shell.execute().result()`。该版本的 `dsh` 依赖 cordis `^4.0.3`,探测时必须把 cordis 钉到这个版本,否则两份 `@deepseek-ai/dsh-tools` 会让工具调度用的 Symbol 对不上、工具调用在第一步失败。开发 pin 仍是 `0.1.5-rc.2`。
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **`0.1.6-alpha.2` 上已打开的会话被面板显示成「当前没有活动会话」**:该版本从 Session 目录快照删除了 `current`,当前会话改由主视图 `retain(..., { source: 'mainView' })` 持有,投影在目录行的 `retainedBy.mainView`。`src/compat/client-session.ts` 用结构探测同时认两种形状;目录有行但没有主视图时仍显示空态,不会把 `ids[0]` 当成当前会话。
|
|
14
25
|
|
|
15
26
|
## [0.1.1] - 2026-09-16
|
|
16
27
|
|
|
@@ -72,6 +83,7 @@ English: [CHANGELOG.en.md](./CHANGELOG.en.md)
|
|
|
72
83
|
|
|
73
84
|
- 发布前外部评审提出的 8 项发现(其中 3 项发布阻断)全部修复,每项各带一个回归测试:登记目录被替换为符号链接后授权转移(引入 `recordedPath`,**重新解析路径不等于重新授权**)、并发修改注册表丢写或复活已撤销的授权(每个主根的变更串行)、刷新不重新检查目录、手输路径被目录选择器覆盖、`reveal` 的应答契约与失败码、重复 id 未校验、主根未纳入嵌套校验、CI 先测后构建。
|
|
74
85
|
|
|
75
|
-
[Unreleased]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.
|
|
86
|
+
[Unreleased]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.2...HEAD
|
|
87
|
+
[0.1.2]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.1...v0.1.2
|
|
76
88
|
[0.1.1]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/compare/v0.1.0...v0.1.1
|
|
77
89
|
[0.1.0]: https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/tag/v0.1.0
|
package/README.en.md
CHANGED
|
@@ -16,7 +16,9 @@ Three things make this plugin worth looking at:
|
|
|
16
16
|
|
|
17
17
|
**Done and released: the MVP `v0.1.0` (milestones M1–M3)** — composition and empty-root pass-through, multi-root capability and dialect grants, the root registry / the `/workspace-folders` command / the Workspace Folders panel / a cross-repository journey e2e.
|
|
18
18
|
|
|
19
|
-
**Done and released: the `v0.1.1` hardening batch (H1–H4)** — a cross-process Registry Authority Lease (when two DSH processes share one `$DSH_HOME`, only the lease holder grants additional roots; the other fails closed and takes over once the holder exits), panel primary-root authority derived from the host session (a client-named root is no longer accepted), DSH compatibility turned from a documented agreement into a **code contract enforced at startup** (an exact allowlist, mixed-install detection, a `src/compat/` adapter layer —
|
|
19
|
+
**Done and released: the `v0.1.1` hardening batch (H1–H4)** — a cross-process Registry Authority Lease (when two DSH processes share one `$DSH_HOME`, only the lease holder grants additional roots; the other fails closed and takes over once the holder exits), panel primary-root authority derived from the host session (a client-named root is no longer accepted), DSH compatibility turned from a documented agreement into a **code contract enforced at startup** (an exact allowlist, mixed-install detection, a `src/compat/` adapter layer — see the "Upgrade Notes" in the [CHANGELOG](./CHANGELOG.en.md)), and **an additional root's own `AGENTS.md` / `CLAUDE.md` reaching the model** — native instruction discovery walks upward from the session cwd, so it can never reach an additional root.
|
|
20
|
+
|
|
21
|
+
**Done and released: `v0.1.2`** — with the `v0.1.1` contract unchanged, the supported upstream runtimes grow to `0.1.6-alpha.2` and `0.1.7-alpha.1` (the latter needs adapters for session format 4, in-process `PluginPackages`, bash `execute().result()`, and more); it also fixes the Workspace Folders panel on `0.1.6-alpha.2`, where dropping `current` from the Session catalog wrongly showed "No active session". See the [CHANGELOG](./CHANGELOG.en.md).
|
|
20
22
|
|
|
21
23
|
The single source of truth for progress, numbering, and release state is the [roadmap progress ledger](./docs/plans/active/2026-09-12-multi-root-workspace.md#进度总账) (M1–M4 are the MVP milestone numbers, H1–H4 are the `v0.1.1` batch numbers, and H1 is M4); per-item evidence lives in the [completed plans](./docs/plans/README.md), and the user-visible changes of each version are in the [CHANGELOG](./CHANGELOG.en.md).
|
|
22
24
|
|
|
@@ -39,7 +41,7 @@ The agent can now read, write, and run bash in that directory, with the same rig
|
|
|
39
41
|
|
|
40
42
|
## Requirements
|
|
41
43
|
|
|
42
|
-
- **Using the published plugin**: you need a *supported* DSH runtime — currently **`0.1.5-rc.2` and `0.1.
|
|
44
|
+
- **Using the published plugin**: you need a *supported* DSH runtime — currently **`0.1.5-rc.2`, `0.1.6-alpha.1`, `0.1.6-alpha.2`, and `0.1.7-alpha.1`**, and nothing else will install or run (see below). `dsh plugin` installs the package into the matching profile, and no local Node toolchain is required
|
|
43
45
|
- **Building from source / contributing**: **Node.js** `^22.19.0 || >=24` (pinned by the repository's `engines`), **Git**, and **pnpm 11** (`packageManager` pins `pnpm@11.25.0`; corepack recommended)
|
|
44
46
|
- **DSH runtime**: the dev pin is exactly `0.1.5-rc.2`, the baseline among the supported releases; the upgrade procedure lives in the [development workflow](./docs/development/plugin-development-workflow.md)
|
|
45
47
|
- **Platforms**: kernel-level multi-root is complete on macOS (Seatbelt) and Linux (bwrap or Landlock); on Windows only the `fs` write path covers additional roots (confined bash/PTY does not — see [known limitations](#known-limitations))
|
|
@@ -80,8 +82,8 @@ This installs pre-built artifacts (the plugin itself is never compiled), but the
|
|
|
80
82
|
```sh
|
|
81
83
|
pnpm pack @dsh-electron/dsh-plugin-multi-root-workspace
|
|
82
84
|
# or download the tgz from the GitHub Release assets, e.g.:
|
|
83
|
-
# https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/download/v0.1.
|
|
84
|
-
dsh plugin --profile web add ./dsh-electron-dsh-plugin-multi-root-workspace-0.1.
|
|
85
|
+
# https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/download/v0.1.2/dsh-electron-dsh-plugin-multi-root-workspace-0.1.2.tgz
|
|
86
|
+
dsh plugin --profile web add ./dsh-electron-dsh-plugin-multi-root-workspace-0.1.2.tgz
|
|
85
87
|
```
|
|
86
88
|
|
|
87
89
|
Also pre-built (the plugin itself is never compiled here), handy for air-gapped or offline delivery — and the first `add` needs the same `allowBuilds` answer.
|
|
@@ -100,10 +102,10 @@ allowBuilds:
|
|
|
100
102
|
koffi: true
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
Then run `add` again. Pinning a tag (e.g. `#v0.1.
|
|
105
|
+
Then run `add` again. Pinning a tag (e.g. `#v0.1.2`) is recommended so a later push cannot silently change what actually runs:
|
|
104
106
|
|
|
105
107
|
```sh
|
|
106
|
-
dsh plugin --profile web add github:cherrchen/dsh-plugin-multi-root-workspace#v0.1.
|
|
108
|
+
dsh plugin --profile web add github:cherrchen/dsh-plugin-multi-root-workspace#v0.1.2
|
|
107
109
|
```
|
|
108
110
|
|
|
109
111
|
### Install from a local clone (development & debugging)
|
package/README.md
CHANGED
|
@@ -16,7 +16,9 @@ DSH(DeepSeek Harness)的外部插件 bundle:把 Workspace 的可写范围
|
|
|
16
16
|
|
|
17
17
|
**已完成并发布:MVP `v0.1.0`(里程碑 M1–M3)**——组合与空根直通、多根能力与方言 grant、根注册表 / `/workspace-folders` 命令 / Workspace Folders 面板 / 跨仓库旅程 e2e。
|
|
18
18
|
|
|
19
|
-
**已完成并发布:`v0.1.1` 硬化批次(H1–H4)**——跨进程 Registry Authority Lease(两个 DSH 进程共用 `$DSH_HOME` 时只有持锁者授予附加根,另一方 fail-closed 并在对方退出后接管)、面板主根改为 host session 推导(不再接受客户端指名的根)、DSH 兼容性从文档约定变成**启动时执行的代码契约**(精确 allowlist + 混装检测 + `src/compat/`
|
|
19
|
+
**已完成并发布:`v0.1.1` 硬化批次(H1–H4)**——跨进程 Registry Authority Lease(两个 DSH 进程共用 `$DSH_HOME` 时只有持锁者授予附加根,另一方 fail-closed 并在对方退出后接管)、面板主根改为 host session 推导(不再接受客户端指名的根)、DSH 兼容性从文档约定变成**启动时执行的代码契约**(精确 allowlist + 混装检测 + `src/compat/` 适配层,见 [CHANGELOG](./CHANGELOG.md) 的「升级注意」),以及**附加根自身的 `AGENTS.md` / `CLAUDE.md` 进入模型上下文**——原生指令发现从会话 cwd 向上走,永远到不了附加根。
|
|
20
|
+
|
|
21
|
+
**已完成并发布:`v0.1.2`**——在 `v0.1.1` 契约不变的前提下,受支持的上游运行时扩展到 `0.1.6-alpha.2` 与 `0.1.7-alpha.1`(后者含 session format 4、进程内 `PluginPackages`、bash `execute().result()` 等适配);并修复 `0.1.6-alpha.2` 上 Workspace Folders 面板因 Session 目录删掉 `current` 而误显示「没有活动会话」的问题。详见 [CHANGELOG](./CHANGELOG.md)。
|
|
20
22
|
|
|
21
23
|
进度、编号与发布状态的唯一真源是[路线图 §进度总账](./docs/plans/active/2026-09-12-multi-root-workspace.md#进度总账)(M1–M4 是 MVP 里程碑编号,H1–H4 是 `v0.1.1` 批次编号,其中 H1 即 M4);逐项证据见各[已完成计划](./docs/plans/README.md),每个版本的用户可见变更见 [CHANGELOG](./CHANGELOG.md)。
|
|
22
24
|
|
|
@@ -41,7 +43,7 @@ dsh --profile web
|
|
|
41
43
|
|
|
42
44
|
## 环境要求
|
|
43
45
|
|
|
44
|
-
- **使用已发布的插件**:需要一个受支持的 DSH 运行时 —— 当前是 **`0.1.5-rc.2` 与 `0.1.
|
|
46
|
+
- **使用已发布的插件**:需要一个受支持的 DSH 运行时 —— 当前是 **`0.1.5-rc.2`、`0.1.6-alpha.1`、`0.1.6-alpha.2` 与 `0.1.7-alpha.1`**,别的版本装不上也不会跑(见下)。`dsh plugin` 会把包装进对应 profile,无需本地 Node 工具链
|
|
45
47
|
- **从源码构建 / 参与**:**Node.js** `^22.19.0 || >=24`(仓库 `engines` 钉住)、**Git**、**pnpm 11**(`packageManager` 钉 `pnpm@11.25.0`,建议经 corepack 启用)
|
|
46
48
|
- **DSH 运行时**:开发依赖精确 pin 在 `0.1.5-rc.2`(受支持版本里的基线);升级流程见[开发工作流](./docs/development/plugin-development-workflow.md)
|
|
47
49
|
- **平台支持**:macOS(Seatbelt)与 Linux(bwrap 或 Landlock)内核级多根全量;Windows 仅 `fs` 写路径覆盖附加根(受限 bash/PTY 不含,见[已知限制](#已知限制第一期))
|
|
@@ -82,8 +84,8 @@ dsh plugin --profile web add @dsh-electron/dsh-plugin-multi-root-workspace
|
|
|
82
84
|
```sh
|
|
83
85
|
pnpm pack @dsh-electron/dsh-plugin-multi-root-workspace
|
|
84
86
|
# 或从 GitHub Release 资产下载,例如:
|
|
85
|
-
# https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/download/v0.1.
|
|
86
|
-
dsh plugin --profile web add ./dsh-electron-dsh-plugin-multi-root-workspace-0.1.
|
|
87
|
+
# https://github.com/cherrchen/dsh-plugin-multi-root-workspace/releases/download/v0.1.2/dsh-electron-dsh-plugin-multi-root-workspace-0.1.2.tgz
|
|
88
|
+
dsh plugin --profile web add ./dsh-electron-dsh-plugin-multi-root-workspace-0.1.2.tgz
|
|
87
89
|
```
|
|
88
90
|
|
|
89
91
|
同样是预构建产物(不需要编译本插件本身),适合内网或离线环境交付;首次 `add` 同样要回答那一次 `allowBuilds`。
|
|
@@ -102,10 +104,10 @@ allowBuilds:
|
|
|
102
104
|
koffi: true
|
|
103
105
|
```
|
|
104
106
|
|
|
105
|
-
然后重新执行 `add` 即可。建议锁定 tag(如 `#v0.1.
|
|
107
|
+
然后重新执行 `add` 即可。建议锁定 tag(如 `#v0.1.2`),让后续推送无法悄悄改变实际运行的内容:
|
|
106
108
|
|
|
107
109
|
```sh
|
|
108
|
-
dsh plugin --profile web add github:cherrchen/dsh-plugin-multi-root-workspace#v0.1.
|
|
110
|
+
dsh plugin --profile web add github:cherrchen/dsh-plugin-multi-root-workspace#v0.1.2
|
|
109
111
|
```
|
|
110
112
|
|
|
111
113
|
### 从本地源码安装(开发调试)
|
package/lib/client.js
CHANGED
|
@@ -4,9 +4,96 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
//#region \0rolldown/runtime.js
|
|
8
|
+
var __create = Object.create;
|
|
9
|
+
var __defProp = Object.defineProperty;
|
|
10
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
11
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
12
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __copyProps = (to, from, except, desc) => {
|
|
15
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
16
|
+
key = keys[i];
|
|
17
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
18
|
+
get: ((k) => from[k]).bind(null, key),
|
|
19
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return to;
|
|
23
|
+
};
|
|
24
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
|
|
25
|
+
value: mod,
|
|
26
|
+
enumerable: true
|
|
27
|
+
}) : target, mod));
|
|
28
|
+
//#endregion
|
|
7
29
|
let react = require("react");
|
|
8
30
|
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
31
|
+
_deepseek_ai_dsh_client_ui_primitives = __toESM(_deepseek_ai_dsh_client_ui_primitives, 1);
|
|
9
32
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
33
|
+
//#region src/compat/client-session.ts
|
|
34
|
+
/**
|
|
35
|
+
* The session the composed client is showing, when it can name one.
|
|
36
|
+
* @param sessions - the client `sessions` service, or whatever this
|
|
37
|
+
* composition provided under that name. Absence is a supported state.
|
|
38
|
+
* @returns the session id, or `undefined` when no main view holds one.
|
|
39
|
+
*/
|
|
40
|
+
function currentSessionIdOf(sessions) {
|
|
41
|
+
const snapshot = listSnapshotOf(sessions);
|
|
42
|
+
if (snapshot === void 0) return void 0;
|
|
43
|
+
const current = snapshot.current;
|
|
44
|
+
if (typeof current === "string" && current !== "") return current;
|
|
45
|
+
return mainViewSessionId(snapshot.byId);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* The list snapshot, when the service actually exposes one.
|
|
49
|
+
*
|
|
50
|
+
* `getSnapshot` is invoked as a method so a real store can read `this`.
|
|
51
|
+
* Extracting the function and calling it unbound drops that binding and
|
|
52
|
+
* yields `undefined` even when a session is selected.
|
|
53
|
+
*/
|
|
54
|
+
function listSnapshotOf(sessions) {
|
|
55
|
+
if (sessions === null || typeof sessions !== "object") return void 0;
|
|
56
|
+
const list = sessions.list;
|
|
57
|
+
if (list === null || typeof list !== "object") return void 0;
|
|
58
|
+
const holder = list;
|
|
59
|
+
if (typeof holder.getSnapshot !== "function") return void 0;
|
|
60
|
+
let snapshot;
|
|
61
|
+
try {
|
|
62
|
+
snapshot = holder.getSnapshot();
|
|
63
|
+
} catch {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
if (snapshot === null || typeof snapshot !== "object") return void 0;
|
|
67
|
+
return snapshot;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The first catalog row retained by the main view.
|
|
71
|
+
*
|
|
72
|
+
* Enumeration order is the catalog's insertion order, which is the order
|
|
73
|
+
* upstream's own main-binding projection scans. A row counts only while
|
|
74
|
+
* `retainedBy.mainView` is a positive number: zero, a missing source, and a
|
|
75
|
+
* non-numeric value are not a selection.
|
|
76
|
+
* @param byId - the catalog map, or anything else the snapshot happened to carry.
|
|
77
|
+
* @returns that row's session id.
|
|
78
|
+
*/
|
|
79
|
+
function mainViewSessionId(byId) {
|
|
80
|
+
if (byId === null || typeof byId !== "object") return void 0;
|
|
81
|
+
for (const [key, row] of Object.entries(byId)) {
|
|
82
|
+
if (!isMainViewRow(row)) continue;
|
|
83
|
+
const id = row.id;
|
|
84
|
+
if (typeof id === "string" && id !== "") return id;
|
|
85
|
+
if (key !== "") return key;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** Whether one catalog value is a row the main view currently retains. */
|
|
89
|
+
function isMainViewRow(row) {
|
|
90
|
+
if (row === null || typeof row !== "object") return false;
|
|
91
|
+
const retainedBy = row.retainedBy;
|
|
92
|
+
if (retainedBy === null || typeof retainedBy !== "object") return false;
|
|
93
|
+
const count = retainedBy.mainView;
|
|
94
|
+
return typeof count === "number" && count > 0;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
10
97
|
//#region node_modules/.pnpm/zod@4.6.2/node_modules/zod/v4/core/util.js
|
|
11
98
|
function getEnumValues(entries) {
|
|
12
99
|
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
@@ -5434,11 +5521,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5434
5521
|
if (!parsed.ok) throw new PanelError("panel/bad-response", parsed.message);
|
|
5435
5522
|
return parsed.value;
|
|
5436
5523
|
}
|
|
5437
|
-
/** The current session id, when the composed client can name one. */
|
|
5438
|
-
function currentSessionIdOf(sessions) {
|
|
5439
|
-
const current = sessions?.list?.getSnapshot?.().current;
|
|
5440
|
-
return typeof current === "string" && current !== "" ? current : void 0;
|
|
5441
|
-
}
|
|
5442
5524
|
//#endregion
|
|
5443
5525
|
//#region src/client/styles.ts
|
|
5444
5526
|
/**
|
|
@@ -5815,6 +5897,43 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5815
5897
|
width: 32px;
|
|
5816
5898
|
}
|
|
5817
5899
|
`;
|
|
5900
|
+
//#endregion
|
|
5901
|
+
//#region src/compat/client-icons.ts
|
|
5902
|
+
/**
|
|
5903
|
+
* The installed icon module, addressed by export name.
|
|
5904
|
+
*
|
|
5905
|
+
* Named imports cannot spell both releases: each name is absent from the
|
|
5906
|
+
* other release's declaration, so the compiler is told once, here.
|
|
5907
|
+
*/
|
|
5908
|
+
const installed = _deepseek_ai_dsh_client_ui_primitives;
|
|
5909
|
+
/**
|
|
5910
|
+
* Pick the first export name this release actually provides.
|
|
5911
|
+
* @param module - the icon module to read.
|
|
5912
|
+
* @param names - candidate export names, preferred first.
|
|
5913
|
+
* @returns the component.
|
|
5914
|
+
* @throws {Error} when none of the names is exported. That is a compatibility
|
|
5915
|
+
* break to adapt here, not a missing optional peer.
|
|
5916
|
+
*/
|
|
5917
|
+
function selectIcon(module, names) {
|
|
5918
|
+
for (const name of names) {
|
|
5919
|
+
const found = module[name];
|
|
5920
|
+
if (found !== void 0) return found;
|
|
5921
|
+
}
|
|
5922
|
+
throw new Error(`multi-root workspace: @deepseek-ai/dsh-client-ui-primitives exports none of ${names.join(", ")}; the workspace-folders panel cannot render its icons. Adapt src/compat/client-icons.ts to the installed release.`);
|
|
5923
|
+
}
|
|
5924
|
+
/** Resolved once, against the installed module. */
|
|
5925
|
+
function icon(pixelName, regularName) {
|
|
5926
|
+
return selectIcon(installed, [pixelName, regularName]);
|
|
5927
|
+
}
|
|
5928
|
+
const IconChevronDown = icon("IconChevronDownOutline14", "IconChevronDownOutlineRegular");
|
|
5929
|
+
const IconChevronUp = icon("IconChevronUpOutline14", "IconChevronUpOutlineRegular");
|
|
5930
|
+
const IconCopy = icon("IconCopyOutline16", "IconCopyOutlineRegular");
|
|
5931
|
+
const IconEdit = icon("IconEditOutline16", "IconEditOutlineRegular");
|
|
5932
|
+
const IconEllipsis = icon("IconEllipsisOutline16", "IconEllipsisOutlineRegular");
|
|
5933
|
+
const IconFolderClose = icon("IconFolderClose16", "IconFolderCloseRegular");
|
|
5934
|
+
const IconFolderOpen = icon("IconFolderOpenOutline16", "IconFolderOpenOutlineRegular");
|
|
5935
|
+
const IconPlus = icon("IconPlusOutline16", "IconPlusOutlineRegular");
|
|
5936
|
+
const IconTrash = icon("IconTrashOutline16", "IconTrashOutlineRegular");
|
|
5818
5937
|
//#endregion
|
|
5819
5938
|
//#region src/client/WorkspaceFoldersAction.tsx
|
|
5820
5939
|
/**
|
|
@@ -5923,7 +6042,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5923
6042
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5924
6043
|
className: "mrfw-triggerIcon",
|
|
5925
6044
|
"aria-hidden": "true",
|
|
5926
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6045
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolderClose, { size: rail ? 18 : 16 })
|
|
5927
6046
|
}), rail ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5928
6047
|
className: "mrfw-triggerLabel",
|
|
5929
6048
|
children: props.t("action.label")
|
|
@@ -6321,7 +6440,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6321
6440
|
onClick: () => {
|
|
6322
6441
|
copyPath(root);
|
|
6323
6442
|
},
|
|
6324
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6443
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconCopy, {}),
|
|
6325
6444
|
label: copiedId === key ? t("panel.copied") : t("panel.copyPath")
|
|
6326
6445
|
}),
|
|
6327
6446
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
@@ -6329,7 +6448,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6329
6448
|
onClick: () => {
|
|
6330
6449
|
reveal(root);
|
|
6331
6450
|
},
|
|
6332
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6451
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconFolderOpen, {}),
|
|
6333
6452
|
label: t("panel.reveal")
|
|
6334
6453
|
}),
|
|
6335
6454
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
@@ -6337,7 +6456,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6337
6456
|
onClick: () => {
|
|
6338
6457
|
move(root, roots[index - 1]);
|
|
6339
6458
|
},
|
|
6340
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6459
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronUp, {}),
|
|
6341
6460
|
label: t("panel.moveUp")
|
|
6342
6461
|
}),
|
|
6343
6462
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconButton, {
|
|
@@ -6345,7 +6464,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6345
6464
|
onClick: () => {
|
|
6346
6465
|
move(root, roots[index + 2]);
|
|
6347
6466
|
},
|
|
6348
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6467
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconChevronDown, {}),
|
|
6349
6468
|
label: t("panel.moveDown")
|
|
6350
6469
|
}),
|
|
6351
6470
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
@@ -6356,11 +6475,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6356
6475
|
items: [{
|
|
6357
6476
|
id: "rename",
|
|
6358
6477
|
label: t("panel.rename"),
|
|
6359
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6478
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconEdit, {})
|
|
6360
6479
|
}, {
|
|
6361
6480
|
id: "remove",
|
|
6362
6481
|
label: t("panel.remove"),
|
|
6363
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6482
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconTrash, {}),
|
|
6364
6483
|
danger: true,
|
|
6365
6484
|
disabled: state.busy
|
|
6366
6485
|
}],
|
|
@@ -6380,7 +6499,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6380
6499
|
onClick: () => {
|
|
6381
6500
|
setMenuFor((current) => current === key ? void 0 : key);
|
|
6382
6501
|
},
|
|
6383
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6502
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconEllipsis, {}),
|
|
6384
6503
|
label: t("panel.more")
|
|
6385
6504
|
})
|
|
6386
6505
|
}),
|
|
@@ -6429,7 +6548,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6429
6548
|
onClick: () => {
|
|
6430
6549
|
addViaPicker();
|
|
6431
6550
|
},
|
|
6432
|
-
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
6551
|
+
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(IconPlus, {}),
|
|
6433
6552
|
label: t("panel.add")
|
|
6434
6553
|
}),
|
|
6435
6554
|
state.noSession ? null : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|