dsh-enhancement-suite 0.1.4 → 0.3.0
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/LICENSE +21 -21
- package/README.md +29 -132
- package/README.zh.md +27 -130
- package/VERIFICATION.md +7 -0
- package/bin/dsh-enhance.mjs +28 -81
- package/bin/validate-manifest.mjs +5 -4
- package/client.js +72 -0
- package/cordis.patch.yml +3 -0
- package/docs/architecture.md +11 -102
- package/index.js +13 -0
- package/locale/en.json +6 -0
- package/locale/zh.json +6 -0
- package/package.json +80 -44
- package/plugins.json +76 -54
package/LICENSE
CHANGED
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Scorp1o117
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Scorp1o117
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,132 +1,29 @@
|
|
|
1
|
-
# DeepSeek Harness Enhancement Suite
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
DSH
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
[→ upstream repository](https://github.com/Scorp1o117/dsh-tool-vision)
|
|
31
|
-
|
|
32
|
-
## 🎭 dsh-soul-md
|
|
33
|
-
|
|
34
|
-
为 Agent 增加 soul.md 人设、会话/工作区 Persona 和可演化人格。
|
|
35
|
-
|
|
36
|
-
[](https://www.npmjs.com/package/dsh-soul-md) [](https://github.com/Scorp1o117/dsh-soul-md/blob/main/LICENSE)
|
|
37
|
-
|
|
38
|
-
[→ upstream repository](https://github.com/Scorp1o117/dsh-soul-md)
|
|
39
|
-
|
|
40
|
-
## 🧠 dsh-tdai-memory
|
|
41
|
-
|
|
42
|
-
完整的长期分层记忆、召回与搜索。
|
|
43
|
-
|
|
44
|
-
[](https://www.npmjs.com/package/dsh-tdai-memory) [](https://github.com/Scorp1o117/dsh-tdai-memory/blob/main/LICENSE)
|
|
45
|
-
|
|
46
|
-
[→ upstream repository](https://github.com/Scorp1o117/dsh-tdai-memory)
|
|
47
|
-
|
|
48
|
-
## 🛒 dsh-plugin-marketplace
|
|
49
|
-
|
|
50
|
-
直接在 DSH Web UI 中发现和浏览插件。
|
|
51
|
-
|
|
52
|
-
[](https://www.npmjs.com/package/dsh-plugin-marketplace) [](https://github.com/Scorp1o117/dsh-plugin-marketplace/blob/main/LICENSE)
|
|
53
|
-
|
|
54
|
-
[→ upstream repository](https://github.com/Scorp1o117/dsh-plugin-marketplace)
|
|
55
|
-
|
|
56
|
-
---
|
|
57
|
-
|
|
58
|
-
## Requirements
|
|
59
|
-
|
|
60
|
-
- **Node.js >= 22.18** — the full suite inherits the `dsh-tdai-memory` engine requirement
|
|
61
|
-
- **dsh CLI** on `PATH` — the official DeepSeek Harness CLI (`dsh plugin --profile <p> add <pkg>` is the install mechanism)
|
|
62
|
-
- A target profile (default: `web`)
|
|
63
|
-
|
|
64
|
-
## Install & usage
|
|
65
|
-
|
|
66
|
-
From this repository (no install needed):
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
node bin/dsh-enhance.mjs list
|
|
70
|
-
node bin/dsh-enhance.mjs install --dry-run
|
|
71
|
-
node bin/dsh-enhance.mjs install
|
|
72
|
-
node bin/dsh-enhance.mjs doctor
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
As a global command (once published to npm):
|
|
76
|
-
|
|
77
|
-
```bash
|
|
78
|
-
npm install -g dsh-enhancement-suite
|
|
79
|
-
dsh-enhance list
|
|
80
|
-
dsh-enhance install
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
## CLI
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
dsh-enhance list Show the plugin registry (installed state per profile)
|
|
87
|
-
dsh-enhance install Install all four plugins into a profile
|
|
88
|
-
dsh-enhance update Update installed plugins to the latest versions
|
|
89
|
-
dsh-enhance doctor Check Node, dsh CLI, profile and per-plugin state
|
|
90
|
-
|
|
91
|
-
--profile <name> target profile (default: web)
|
|
92
|
-
--only <keys> comma-separated selection: vision,soul,memory,marketplace (or package names)
|
|
93
|
-
--dry-run print what would run without executing anything
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
Examples:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
dsh-enhance install --dry-run # preview everything
|
|
100
|
-
dsh-enhance install --profile web --only vision,soul
|
|
101
|
-
dsh-enhance update --profile headless
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
## How it installs
|
|
105
|
-
|
|
106
|
-
1. Every plugin is installed through the **official CLI**: `dsh plugin --profile <profile> add <package>`. This suite never loads the plugins through its own dependency graph or its own cordis patch — the four upstream packages stay independent in the profile.
|
|
107
|
-
2. All four plugins now declare `dsh.bundle.patch` (as of vision 0.3.9 / soul-md 0.5.4 / tdai-memory 0.2.9 / marketplace 0.2.4), so `dsh plugin add` reconciles each into `dsh.profile.bundles` and its own bundle layer auto-mounts it.
|
|
108
|
-
3. For profiles that mounted a plugin manually before it gained its bundle manifest, the suite **removes the stale manual row** from `cordis.patch.yml` — two mounts of the same entry id would abort boot. (Non-bundle third-party plugins still get the safe idempotent mount logic: empty `[]` patches are replaced correctly, duplicates are skipped, flow-style arrays are refused instead of corrupted.)
|
|
109
|
-
4. Restart `dsh web` and the plugins load.
|
|
110
|
-
|
|
111
|
-
Every step reports a clear `✓` / `✗`, failures are never swallowed, and no API key is read, printed, or forwarded.
|
|
112
|
-
|
|
113
|
-
## Integration / Adoption
|
|
114
|
-
|
|
115
|
-
The following plugins are adopted and shipped built-in by the **Deepseek Harness EAC** desktop client:
|
|
116
|
-
|
|
117
|
-
- 👁️ `dsh-tool-vision`
|
|
118
|
-
- 🎭 `dsh-soul-md`
|
|
119
|
-
- 🧠 `dsh-tdai-memory`
|
|
120
|
-
|
|
121
|
-
[Deepseek-Harness-EAC](https://github.com/zouyuxuan122/Deepseek-Harness-EAC)
|
|
122
|
-
|
|
123
|
-
> Note: EAC's built-in marketplace implementation is a separate project; it does not use `dsh-plugin-marketplace`.
|
|
124
|
-
|
|
125
|
-
## Documentation
|
|
126
|
-
|
|
127
|
-
- [Architecture](docs/architecture.md) — design decisions, manifest schema, safety rules
|
|
128
|
-
- [plugins.json](plugins.json) — the plugin manifest (npm name, repo, category, display name, description)
|
|
129
|
-
|
|
130
|
-
## License
|
|
131
|
-
|
|
132
|
-
MIT — see [LICENSE](LICENSE). Each plugin keeps its own MIT license in its upstream repository.
|
|
1
|
+
# DeepSeek Harness Enhancement Suite
|
|
2
|
+
|
|
3
|
+
Install and update **Vision, Soul / Persona, Memory, Marketplace, Reasoning Options and Motion UI** from a DSH plugin configuration page or the dsh-enhance CLI. Version 0.3.0 requires DSH 0.2.0-rc.2 or later 0.2.x and Node >=22.19.
|
|
4
|
+
|
|
5
|
+
## Desktop and Web configuration page
|
|
6
|
+
|
|
7
|
+
Use the Desktop-provided dsh command (Application → Manage dsh Command):
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
dsh plugin --profile desktop add dsh-enhancement-suite@0.3.0
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Use --profile web for Web. Restart DSH and open **Plugins → Installed → dsh-enhancement-suite**. Choose **Install all**, **Update installed plugins**, or an individual install/update button. Motion UI is included as dsh-motion-ui. The page displays installed versions, operation progress and errors. All operations target the active Host's profile and use its official CLI; no API credentials are needed. Updating installed plugins skips missing plugins; Install all installs or updates all six. Restart DSH afterwards.
|
|
14
|
+
|
|
15
|
+
The suite shares the marketplace's operation engine without mounting a duplicate marketplace plugin. Installing all adds the marketplace as its own independent bundle. Use the marketplace configuration page for uninstall and management of other installed plugins. Built-in DSH bundles are protected.
|
|
16
|
+
|
|
17
|
+
## CLI
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npx dsh-enhancement-suite list --profile desktop
|
|
21
|
+
npx dsh-enhancement-suite install --profile desktop
|
|
22
|
+
npx dsh-enhancement-suite update --profile desktop --only motion,reasoning
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
On Desktop, the dsh command on PATH must be installed by Desktop. If another global CLI shadows it on Windows, set DSH_ENHANCE_DESKTOP_EXECUTABLE to the absolute DeepSeek Harness.exe path before running dsh-enhance; this uses Desktop's bundled CLI and pnpm. --dry-run previews operations. --only accepts short keys or package names. Individual plugins remain independently maintained and are installed directly into the profile.
|
|
26
|
+
|
|
27
|
+
## Validation
|
|
28
|
+
|
|
29
|
+
npm run check validates syntax, the six-plugin registry and CLI help/list. npm test validates the bundle, configuration page and CLI selection.
|
package/README.zh.md
CHANGED
|
@@ -1,130 +1,27 @@
|
|
|
1
|
-
# DeepSeek Harness Enhancement Suite
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
[→ upstream 仓库](https://github.com/Scorp1o117/dsh-tool-vision)
|
|
29
|
-
|
|
30
|
-
## 🎭 dsh-soul-md
|
|
31
|
-
|
|
32
|
-
为 Agent 增加 soul.md 人设、会话/工作区 Persona 和可演化人格。
|
|
33
|
-
|
|
34
|
-
[](https://www.npmjs.com/package/dsh-soul-md) [](https://github.com/Scorp1o117/dsh-soul-md/blob/main/LICENSE)
|
|
35
|
-
|
|
36
|
-
[→ upstream 仓库](https://github.com/Scorp1o117/dsh-soul-md)
|
|
37
|
-
|
|
38
|
-
## 🧠 dsh-tdai-memory
|
|
39
|
-
|
|
40
|
-
完整的长期分层记忆、召回与搜索。
|
|
41
|
-
|
|
42
|
-
[](https://www.npmjs.com/package/dsh-tdai-memory) [](https://github.com/Scorp1o117/dsh-tdai-memory/blob/main/LICENSE)
|
|
43
|
-
|
|
44
|
-
[→ upstream 仓库](https://github.com/Scorp1o117/dsh-tdai-memory)
|
|
45
|
-
|
|
46
|
-
## 🛒 dsh-plugin-marketplace
|
|
47
|
-
|
|
48
|
-
直接在 DSH Web UI 中发现和浏览插件。
|
|
49
|
-
|
|
50
|
-
[](https://www.npmjs.com/package/dsh-plugin-marketplace) [](https://github.com/Scorp1o117/dsh-plugin-marketplace/blob/main/LICENSE)
|
|
51
|
-
|
|
52
|
-
[→ upstream 仓库](https://github.com/Scorp1o117/dsh-plugin-marketplace)
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## 环境要求
|
|
57
|
-
|
|
58
|
-
- **Node.js >= 22.18** —— 完整套件继承 `dsh-tdai-memory` 的引擎要求
|
|
59
|
-
- **dsh CLI** 在 `PATH` 上 —— 安装机制是官方 CLI:`dsh plugin --profile <p> add <pkg>`
|
|
60
|
-
- 目标 profile(默认:`web`)
|
|
61
|
-
|
|
62
|
-
## 安装与使用
|
|
63
|
-
|
|
64
|
-
从本仓库直接运行(无需安装):
|
|
65
|
-
|
|
66
|
-
```bash
|
|
67
|
-
node bin/dsh-enhance.mjs list
|
|
68
|
-
node bin/dsh-enhance.mjs install --dry-run
|
|
69
|
-
node bin/dsh-enhance.mjs install
|
|
70
|
-
node bin/dsh-enhance.mjs doctor
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
发布到 npm 后作为全局命令使用:
|
|
74
|
-
|
|
75
|
-
```bash
|
|
76
|
-
npm install -g dsh-enhancement-suite
|
|
77
|
-
dsh-enhance list
|
|
78
|
-
dsh-enhance install
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## CLI
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
dsh-enhance list 查看插件清单(含 profile 内的安装状态)
|
|
85
|
-
dsh-enhance install 把四个插件安装进 profile
|
|
86
|
-
dsh-enhance update 更新已安装插件到最新版本
|
|
87
|
-
dsh-enhance doctor 检查 Node、dsh CLI、profile 与各插件状态
|
|
88
|
-
|
|
89
|
-
--profile <name> 目标 profile(默认:web)
|
|
90
|
-
--only <keys> 逗号分隔的选择:vision,soul,memory,marketplace(或包名)
|
|
91
|
-
--dry-run 只打印将要执行的操作,不实际执行
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
示例:
|
|
95
|
-
|
|
96
|
-
```bash
|
|
97
|
-
dsh-enhance install --dry-run # 预览全部操作
|
|
98
|
-
dsh-enhance install --profile web --only vision,soul
|
|
99
|
-
dsh-enhance update --profile headless
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## 安装方式
|
|
103
|
-
|
|
104
|
-
1. 每个插件都通过**官方 CLI** 安装:`dsh plugin --profile <profile> add <package>`。本套件绝不通过自身的依赖图或自己的 cordis patch 间接加载插件——四个 upstream 包在 profile 中保持独立。
|
|
105
|
-
2. `dsh-plugin-marketplace` 声明了 `dsh.bundle.patch`,`dsh plugin add` 会把它对账进 `dsh.profile.bundles`,由 bundle 层自动挂载。
|
|
106
|
-
3. 其余三个是普通依赖;套件用与 marketplace 一键安装相同的安全、幂等逻辑,把挂载行追加到 profile 的 `cordis.patch.yml`(空 `[]` 补丁会被正确替换、重复挂载会被跳过、流式数组会被拒绝而不是损坏)。
|
|
107
|
-
4. 重启 `dsh web` 即可加载。
|
|
108
|
-
|
|
109
|
-
每一步都有清晰的 `✓` / `✗` 反馈,失败绝不吞掉,且不读取、不打印任何 API Key。
|
|
110
|
-
|
|
111
|
-
## 集成 / 采用
|
|
112
|
-
|
|
113
|
-
以下插件已被 **Deepseek Harness EAC** 桌面客户端内置采用:
|
|
114
|
-
|
|
115
|
-
- 👁️ `dsh-tool-vision`
|
|
116
|
-
- 🎭 `dsh-soul-md`
|
|
117
|
-
- 🧠 `dsh-tdai-memory`
|
|
118
|
-
|
|
119
|
-
[Deepseek-Harness-EAC](https://github.com/zouyuxuan122/Deepseek-Harness-EAC)
|
|
120
|
-
|
|
121
|
-
> 注意:EAC 内置的 marketplace 实现是另一个项目,并没有使用 `dsh-plugin-marketplace`。
|
|
122
|
-
|
|
123
|
-
## 文档
|
|
124
|
-
|
|
125
|
-
- [架构说明](docs/architecture.md) —— 设计决策、manifest 结构、安全规则
|
|
126
|
-
- [plugins.json](plugins.json) —— 插件 manifest(npm 包名、仓库、分类、显示名、描述)
|
|
127
|
-
|
|
128
|
-
## License
|
|
129
|
-
|
|
130
|
-
MIT —— 见 [LICENSE](LICENSE)。各插件在各自 upstream 仓库保留独立的 MIT License。
|
|
1
|
+
# DeepSeek Harness Enhancement Suite
|
|
2
|
+
|
|
3
|
+
在 DSH 插件配置页或 dsh-enhance 命令行中安装、更新 **视觉、Soul / Persona、长期记忆、插件市场、推理强度、Motion UI** 六个插件。0.3.0 需要 DSH 0.2.0-rc.2 或后续 0.2.x,以及 Node >=22.19。
|
|
4
|
+
|
|
5
|
+
## Desktop / Web 配置页
|
|
6
|
+
|
|
7
|
+
使用 Desktop 提供的 dsh 命令(应用 → 管理 dsh 命令):
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
dsh plugin --profile desktop add dsh-enhancement-suite@0.3.0
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Web 使用 --profile web。重启后打开 **插件 → 已安装 → dsh-enhancement-suite**,可一键安装全部、一键更新已安装插件,或单独安装/更新。Motion UI 对应 dsh-motion-ui。页面展示真实安装版本、进度和错误,不需要 API 密钥。更新已安装插件会跳过未安装项;安装全部则安装或更新全部六项。完成后重启 DSH。
|
|
14
|
+
|
|
15
|
+
套件共用插件市场的操作后端,不重复挂载市场插件。一键安装全部后,市场作为独立 bundle 挂载。卸载插件和管理套件之外的插件,请使用插件市场配置页。内置 DSH bundle 由 DSH 自身管理。
|
|
16
|
+
|
|
17
|
+
## 命令行
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
npx dsh-enhancement-suite list --profile desktop
|
|
21
|
+
npx dsh-enhancement-suite install --profile desktop
|
|
22
|
+
npx dsh-enhancement-suite update --profile desktop --only motion,reasoning
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Desktop 的 PATH 命令应通过 Desktop 安装。如果被全局 Web CLI 遮挡,Windows 可设置 DSH_ENHANCE_DESKTOP_EXECUTABLE 为 DeepSeek Harness.exe 的绝对路径,命令行会调用 Desktop 自带 CLI 和 pnpm。--dry-run 预览操作;--only 支持短名称和完整包名。各插件保持独立维护并直接安装到 Profile。
|
|
26
|
+
|
|
27
|
+
npm run check 验证语法、六插件清单和 CLI help/list;npm test 验证 bundle、配置页和命令行选择。
|
package/VERIFICATION.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# v0.3.0 validation — 2026-10-12
|
|
2
|
+
|
|
3
|
+
- npm run check and npm test passed (3 tests).
|
|
4
|
+
- Six-plugin registry includes dsh-motion-ui; suite page submits revision-checked batch requests and follows DSH locale.
|
|
5
|
+
- Packed suite started on the installed Desktop 0.2.0-rc.2 runtime in an isolated profile alongside the marketplace without duplicate mounts.
|
|
6
|
+
- Browser showed all six plugin rows and one-click install/update controls. Refresh completed through the actual Host settings channel.
|
|
7
|
+
- The shared engine's real Desktop install/update/uninstall path was exercised by the marketplace smoke; batch selection and serialization are covered by engine tests.
|
package/bin/dsh-enhance.mjs
CHANGED
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
* dsh-enhance — DeepSeek Harness Enhancement Suite CLI.
|
|
4
4
|
*
|
|
5
5
|
* Zero-dependency, cross-platform (Windows / Linux / macOS) installer and
|
|
6
|
-
* registry for the
|
|
6
|
+
* registry for the Scorp1o117 DSH plugins (see plugins.json):
|
|
7
7
|
*
|
|
8
8
|
* vision dsh-tool-vision Vision
|
|
9
9
|
* soul dsh-soul-md Persona
|
|
10
10
|
* memory dsh-tdai-memory Memory
|
|
11
11
|
* marketplace dsh-plugin-marketplace Marketplace
|
|
12
|
+
* reasoning dsh-reasoning-options Model
|
|
12
13
|
*
|
|
13
14
|
* Install always prefers the official DeepSeek Harness plugin CLI
|
|
14
15
|
* (`dsh plugin --profile <profile> add <package>`); this suite never loads
|
|
@@ -35,7 +36,7 @@ const DEFAULT_PROFILE = MANIFEST.defaultProfile ?? "web";
|
|
|
35
36
|
/** Short keys and full package names are both accepted for --only. */
|
|
36
37
|
const KEY_ALIASES = new Map(PLUGINS.map((p) => [p.key, p.name]));
|
|
37
38
|
const NODE_MIN = MANIFEST.node ?? ">=22.18";
|
|
38
|
-
const DSH_MIN = MANIFEST.dsh ?? ">=0.
|
|
39
|
+
const DSH_MIN = MANIFEST.dsh ?? ">=0.2.0-rc.2 <0.3.0";
|
|
39
40
|
|
|
40
41
|
const ok = (msg) => console.log(` ✓ ${msg}`);
|
|
41
42
|
const bad = (msg) => console.log(` ✗ ${msg}`);
|
|
@@ -71,7 +72,13 @@ function installedManifest(pkg, profile) {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
/** Locate the dsh CLI on PATH (dsh.cmd / dsh.exe on Windows, dsh elsewhere). */
|
|
74
|
-
function findDsh() {
|
|
75
|
+
function findDsh(profile) {
|
|
76
|
+
if (profile === "desktop" && process.env.DSH_ENHANCE_DESKTOP_EXECUTABLE) {
|
|
77
|
+
const executable = process.env.DSH_ENHANCE_DESKTOP_EXECUTABLE;
|
|
78
|
+
const cli = join(dirname(executable), "resources", "app.asar", "dsh", "node_modules", "@deepseek-ai", "dsh-desktop-host", "lib", "cli.js");
|
|
79
|
+
if (!existsSync(executable)) throw new CliError(`Desktop executable not found: ${executable}`);
|
|
80
|
+
return { executable, prefix: ["--expose-internals", cli], env: { ...process.env, ELECTRON_RUN_AS_NODE: "1" } };
|
|
81
|
+
}
|
|
75
82
|
const override = process.env.DSH_ENHANCE_DSH_BIN;
|
|
76
83
|
if (override) return override;
|
|
77
84
|
const names = process.platform === "win32" ? ["dsh.cmd", "dsh.exe", "dsh"] : ["dsh"];
|
|
@@ -97,14 +104,17 @@ function quoteArg(arg) {
|
|
|
97
104
|
* Node's `args + shell:true` deprecation (DEP0190) is not triggered.
|
|
98
105
|
*/
|
|
99
106
|
function run(bin, args, { capture = false, cwd } = {}) {
|
|
107
|
+
let env = process.env;
|
|
108
|
+
if (typeof bin === "object") { env = bin.env; args = [...bin.prefix, ...args]; bin = bin.executable; }
|
|
100
109
|
return new Promise((resolve) => {
|
|
101
110
|
const opts = {
|
|
102
111
|
stdio: capture ? ["ignore", "pipe", "pipe"] : "inherit",
|
|
103
112
|
windowsHide: true,
|
|
113
|
+
env,
|
|
104
114
|
...(cwd ? { cwd } : {}),
|
|
105
115
|
};
|
|
106
116
|
let child;
|
|
107
|
-
if (process.platform === "win32") {
|
|
117
|
+
if (process.platform === "win32" && /\.(cmd|bat)$/i.test(bin)) {
|
|
108
118
|
child = spawn([bin, ...args].map(quoteArg).join(" "), { ...opts, shell: true });
|
|
109
119
|
} else {
|
|
110
120
|
child = spawn(bin, args, opts);
|
|
@@ -365,7 +375,7 @@ Usage:
|
|
|
365
375
|
|
|
366
376
|
Commands:
|
|
367
377
|
list Show the plugin registry (installed state per profile)
|
|
368
|
-
install Install all
|
|
378
|
+
install Install all ${PLUGINS.length} plugins into a profile
|
|
369
379
|
update Update installed plugins to the latest versions
|
|
370
380
|
doctor Check Node, dsh CLI, profile and per-plugin state
|
|
371
381
|
|
|
@@ -384,9 +394,9 @@ Examples:
|
|
|
384
394
|
|
|
385
395
|
Notes:
|
|
386
396
|
- Install prefers the official CLI: dsh plugin --profile <profile> add <package>
|
|
387
|
-
- Requires DSH ${DSH_MIN};
|
|
397
|
+
- Requires DSH ${DSH_MIN}; use older suite releases for older DSH versions
|
|
388
398
|
- Requires Node ${NODE_MIN} (dsh-tdai-memory constraint)
|
|
389
|
-
-
|
|
399
|
+
- Plugins are installed directly into the selected profile`);
|
|
390
400
|
}
|
|
391
401
|
|
|
392
402
|
// ── commands ────────────────────────────────────────────────────────────────
|
|
@@ -408,7 +418,7 @@ function cmdList(profile) {
|
|
|
408
418
|
|
|
409
419
|
async function cmdInstall(profile, only, dryRun) {
|
|
410
420
|
const plugins = resolveSelection(only);
|
|
411
|
-
const dsh = findDsh();
|
|
421
|
+
const dsh = findDsh(profile);
|
|
412
422
|
if (!dsh) {
|
|
413
423
|
bad("dsh CLI not found on PATH — install dsh first (https://github.com/deepseek-ai/deepseek-harness)");
|
|
414
424
|
process.exitCode = 1;
|
|
@@ -420,7 +430,7 @@ async function cmdInstall(profile, only, dryRun) {
|
|
|
420
430
|
info(`${p.emoji} ${p.name}`);
|
|
421
431
|
const latest = await latestVersion(p.name);
|
|
422
432
|
const installed = installedVersion(p.name, profile);
|
|
423
|
-
const addArgs = ["plugin", "--profile", profile, "add", p.name];
|
|
433
|
+
const addArgs = ["plugin", "--profile", profile, "add", `${p.name}@latest`];
|
|
424
434
|
if (dryRun) {
|
|
425
435
|
ok(`npm latest: ${latest ?? "unknown (network?)"}; installed: ${installed ?? "not installed"}`);
|
|
426
436
|
if (latest && installed && installed !== latest) {
|
|
@@ -479,79 +489,16 @@ async function cmdInstall(profile, only, dryRun) {
|
|
|
479
489
|
console.log("Fix the reported plugin(s) and re-run dsh-enhance install. No partial state was hidden.");
|
|
480
490
|
process.exitCode = 1;
|
|
481
491
|
} else {
|
|
482
|
-
console.log("Restart
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
async function cmdUpdate(profile, only, dryRun) {
|
|
487
|
-
const plugins = resolveSelection(only);
|
|
488
|
-
const dsh = findDsh();
|
|
489
|
-
if (!dsh) {
|
|
490
|
-
bad("dsh CLI not found on PATH");
|
|
491
|
-
process.exitCode = 1;
|
|
492
|
-
return;
|
|
493
|
-
}
|
|
494
|
-
head(`Updating ${plugins.length} plugin(s) in profile "${profile}"`);
|
|
495
|
-
const failures = [];
|
|
496
|
-
for (const p of plugins) {
|
|
497
|
-
if (!installedManifest(p.name, profile)) {
|
|
498
|
-
info(`${p.emoji} ${p.name}: not installed — run "dsh-enhance install" first`);
|
|
499
|
-
continue;
|
|
500
|
-
}
|
|
501
|
-
const installed = installedVersion(p.name, profile);
|
|
502
|
-
info(`${p.emoji} ${p.name} (installed ${installed})`);
|
|
503
|
-
const latest = await latestVersion(p.name);
|
|
504
|
-
const args = ["plugin", "--profile", profile, "update", p.name];
|
|
505
|
-
if (dryRun) {
|
|
506
|
-
ok(`npm latest: ${latest ?? "unknown (network?)"}`);
|
|
507
|
-
if (latest && installed && installed !== latest) {
|
|
508
|
-
ok(`would bump range to ^${latest} (pnpm keeps stale lockfile versions otherwise)`);
|
|
509
|
-
ok(`would ensure minimumReleaseAgeExclude entry for ${p.name}@${latest}`);
|
|
510
|
-
}
|
|
511
|
-
ok(`would run: dsh ${args.join(" ")}`);
|
|
512
|
-
continue;
|
|
513
|
-
}
|
|
514
|
-
if (latest && installed && installed !== latest) {
|
|
515
|
-
if (bumpProfileRange(profile, p.name, latest)) info(`range align: ^${installed} → ^${latest}`);
|
|
516
|
-
ensureReleaseAgeExclude(profile, p.name, latest);
|
|
517
|
-
}
|
|
518
|
-
const result = await run(dsh, args, { capture: true });
|
|
519
|
-
if (result.code !== 0) {
|
|
520
|
-
bad(`${p.name} update failed (${result.code}): ${failureSummary(result)}`);
|
|
521
|
-
failures.push(`${p.name}: dsh plugin update exited ${result.code}`);
|
|
522
|
-
continue;
|
|
523
|
-
}
|
|
524
|
-
let after = installedVersion(p.name, profile);
|
|
525
|
-
ok(`updated: ${after ?? "latest"}`);
|
|
526
|
-
if (latest && after !== latest) {
|
|
527
|
-
const pnpm = findPnpm();
|
|
528
|
-
if (!pnpm) {
|
|
529
|
-
bad(`${p.name}: still at ${after ?? "?"}, npm latest ${latest} — install pnpm and re-run`);
|
|
530
|
-
failures.push(`${p.name}: version mismatch (${after ?? "?"} ≠ ${latest})`);
|
|
531
|
-
continue;
|
|
532
|
-
}
|
|
533
|
-
info(`installed ${after ?? "?"} ≠ latest ${latest} — running pnpm install as fallback`);
|
|
534
|
-
const pr = await run(pnpm, ["install"], { capture: true, cwd: profileDir(profile) });
|
|
535
|
-
after = installedVersion(p.name, profile);
|
|
536
|
-
if (pr.code !== 0 || after !== latest) {
|
|
537
|
-
bad(`${p.name}: still at ${after ?? "?"}, npm latest ${latest} (pnpm exit ${pr.code}): ${failureSummary(pr)}`);
|
|
538
|
-
failures.push(`${p.name}: version mismatch (${after ?? "?"} ≠ ${latest})`);
|
|
539
|
-
continue;
|
|
540
|
-
}
|
|
541
|
-
ok(`pnpm install fallback: ${after}`);
|
|
542
|
-
}
|
|
543
|
-
const mount = ensureMounted(p.name, profile);
|
|
544
|
-
if (mount.changed) ok(mount.note);
|
|
545
|
-
}
|
|
546
|
-
head("");
|
|
547
|
-
if (failures.length > 0) {
|
|
548
|
-
for (const f of failures) console.log(` ✗ ${f}`);
|
|
549
|
-
process.exitCode = 1;
|
|
550
|
-
} else {
|
|
551
|
-
console.log("Update finished. Restart dsh web to load the new versions.");
|
|
492
|
+
console.log("Restart DSH for the new plugins to load.");
|
|
552
493
|
}
|
|
553
494
|
}
|
|
554
495
|
|
|
496
|
+
async function cmdUpdate(profile, only, dryRun) {
|
|
497
|
+
const plugins = resolveSelection(only).filter(plugin => installedVersion(plugin.name, profile));
|
|
498
|
+
if (!plugins.length) { info("No installed suite plugins to update."); return; }
|
|
499
|
+
return cmdInstall(profile, plugins.map(plugin => plugin.name), dryRun);
|
|
500
|
+
}
|
|
501
|
+
|
|
555
502
|
function cmdDoctor(profile) {
|
|
556
503
|
let healthy = true;
|
|
557
504
|
head("DeepSeek Harness Enhancement Suite — doctor");
|
|
@@ -561,9 +508,9 @@ function cmdDoctor(profile) {
|
|
|
561
508
|
bad(`Node ${process.versions.node} — this suite requires ${NODE_MIN} (dsh-tdai-memory constraint)`);
|
|
562
509
|
healthy = false;
|
|
563
510
|
}
|
|
564
|
-
const dsh = findDsh();
|
|
511
|
+
const dsh = findDsh(profile);
|
|
565
512
|
if (dsh) {
|
|
566
|
-
ok(`dsh CLI found: ${dsh}`);
|
|
513
|
+
ok(`dsh CLI found: ${typeof dsh === "object" ? dsh.executable : dsh}`);
|
|
567
514
|
} else {
|
|
568
515
|
bad("dsh CLI not found on PATH — install DeepSeek Harness first");
|
|
569
516
|
healthy = false;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* validate-manifest — validates plugins.json for the suite.
|
|
4
4
|
*
|
|
5
|
-
* Checks:
|
|
5
|
+
* Checks: at least one plugin, no duplicate names/keys, all required
|
|
6
6
|
* fields present, repo URLs are https github.com links. Exits non-zero on
|
|
7
7
|
* any violation. Used by CI and `npm run check`.
|
|
8
8
|
*/
|
|
@@ -20,11 +20,11 @@ const fail = (message) => {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
const manifest = JSON.parse(readFileSync(join(ROOT, "plugins.json"), "utf8"));
|
|
23
|
-
if (manifest.dsh !== ">=0.
|
|
23
|
+
if (manifest.dsh !== ">=0.2.0-rc.2 <0.3.0") fail(`expected dsh requirement >=0.2.0-rc.2 <0.3.0, got ${manifest.dsh ?? "missing"}`);
|
|
24
24
|
if (!Array.isArray(manifest.plugins)) {
|
|
25
25
|
fail("plugins.json: missing plugins array");
|
|
26
26
|
} else {
|
|
27
|
-
if (manifest.plugins.length
|
|
27
|
+
if (manifest.plugins.length < 1) fail("plugins.json: plugins array is empty");
|
|
28
28
|
const names = manifest.plugins.map((p) => p.name);
|
|
29
29
|
const keys = manifest.plugins.map((p) => p.key);
|
|
30
30
|
if (new Set(names).size !== names.length) fail("duplicate plugin names");
|
|
@@ -35,7 +35,8 @@ if (!Array.isArray(manifest.plugins)) {
|
|
|
35
35
|
if (typeof p[field] !== "string" || p[field].length === 0) fail(`${p.name ?? "?"}: missing required field ${field}`);
|
|
36
36
|
}
|
|
37
37
|
if (!/^https:\/\/github\.com\//.test(p.repo ?? "")) fail(`${p.name ?? "?"}: repo must be an https github.com URL`);
|
|
38
|
-
|
|
38
|
+
const pin = rc6Pins[p.name];
|
|
39
|
+
if (pin !== "none" && !/^\d+\.\d+\.\d+$/.test(pin ?? "")) fail(`${p.name ?? "?"}: missing rc6 compatibility pin (semver, or "none" when the plugin requires DSH rc.7+)`);
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
|
package/client.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "dsh-enhancement-suite",
|
|
3
|
+
factory: function (require) {
|
|
4
|
+
var react = require("react"), h = react.createElement;
|
|
5
|
+
var zh = {
|
|
6
|
+
title: "增强套件", intro: "在当前 Profile 安装和更新六个增强插件。完成后请重启 DSH。",
|
|
7
|
+
installAll: "一键安装全部", updateAll: "一键更新已安装插件", refresh: "刷新列表",
|
|
8
|
+
install: "安装", update: "更新", missing: "未安装", busy: "正在处理…", ok: "操作完成,请重启 DSH", error: "操作失败", unavailable: "配置未加载", hostTimeout: "宿主尚未确认请求,请检查插件是否启用。",
|
|
9
|
+
};
|
|
10
|
+
var en = {
|
|
11
|
+
title: "Enhancement Suite", intro: "Install and update six enhancement plugins in the current profile. Restart DSH afterwards.",
|
|
12
|
+
installAll: "Install all", updateAll: "Update installed plugins", refresh: "Refresh list",
|
|
13
|
+
install: "Install", update: "Update", missing: "Not installed", busy: "Working…", ok: "Completed; restart DSH", error: "Operation failed", unavailable: "Configuration is not loaded", hostTimeout: "The host has not acknowledged the request; check that the plugin is enabled.",
|
|
14
|
+
};
|
|
15
|
+
var plugins = [
|
|
16
|
+
["dsh-tool-vision", "Vision"], ["dsh-soul-md", "Soul / Persona"], ["dsh-tdai-memory", "Memory"],
|
|
17
|
+
["dsh-plugin-marketplace", "Marketplace"], ["dsh-reasoning-options", "Reasoning"], ["dsh-motion-ui", "Motion UI"],
|
|
18
|
+
];
|
|
19
|
+
function SuitePage(props) {
|
|
20
|
+
var scope = props.scope, t = props.t;
|
|
21
|
+
var [snapshot, setSnapshot] = react.useState(function () { return scope.getSnapshot(); });
|
|
22
|
+
var [sending, setSending] = react.useState(false);
|
|
23
|
+
var [error, setError] = react.useState("");
|
|
24
|
+
var refreshLocale = react.useState(0)[1];
|
|
25
|
+
react.useEffect(function () { return props.locale.subscribe(function () { refreshLocale(function (v) { return v + 1; }); }); }, [props.locale]);
|
|
26
|
+
react.useEffect(function () { setSnapshot(scope.getSnapshot()); return scope.subscribe(function () { setSnapshot(scope.getSnapshot()); }); }, [scope]);
|
|
27
|
+
var channel = snapshot.status === "ready" ? snapshot.value : {};
|
|
28
|
+
var request = channel.install || {}, state = channel.installState || {};
|
|
29
|
+
react.useEffect(function () {
|
|
30
|
+
if (!request.ts) return;
|
|
31
|
+
var timer = setTimeout(function () { setError("hostTimeout"); }, 15000);
|
|
32
|
+
return function () { clearTimeout(timer); };
|
|
33
|
+
}, [request.ts]);
|
|
34
|
+
if (snapshot.status !== "ready") return h("p", null, t("unavailable"));
|
|
35
|
+
var busy = sending || Boolean(request.ts) || state.status === "running";
|
|
36
|
+
function run(pkg, action) {
|
|
37
|
+
if (busy || !snapshot.writable) return;
|
|
38
|
+
setSending(true); setError("");
|
|
39
|
+
var value = { pkg: pkg, action: action, ts: Date.now() };
|
|
40
|
+
Promise.resolve().then(function () { return scope.mutate([{ op: "set", path: ["install"], value: value }], snapshot.revision); }).then(function (accepted) {
|
|
41
|
+
setSnapshot(scope.getSnapshot());
|
|
42
|
+
if (!accepted) setError("error");
|
|
43
|
+
}).catch(function () { setError("error"); }).finally(function () { setSending(false); });
|
|
44
|
+
}
|
|
45
|
+
var rows = channel.inventory && channel.inventory.packages || [];
|
|
46
|
+
var button = function (label, pkg, action) { return h("button", { type: "button", disabled: busy || !snapshot.writable, onClick: function () { run(pkg, action); }, style: { padding: "8px 12px", borderRadius: 6, cursor: "pointer", font: "inherit" } }, t(label)); };
|
|
47
|
+
return h("section", { style: { maxWidth: 720, display: "flex", flexDirection: "column", gap: 16, fontSize: 13, color: "var(--dsw-alias-label-primary)" } },
|
|
48
|
+
h("h3", { style: { margin: 0 } }, t("title") + " · " + (channel.inventory?.profile || "")),
|
|
49
|
+
h("p", { style: { margin: 0 } }, t("intro")),
|
|
50
|
+
h("div", { style: { display: "flex", gap: 8, flexWrap: "wrap" } }, button("installAll", "~suite", "suite-install"), button("updateAll", "~suite", "suite-update"), button("refresh", "~refresh", "refresh")),
|
|
51
|
+
plugins.map(function (plugin) {
|
|
52
|
+
var installed = rows.find(function (row) { return row.name === plugin[0]; });
|
|
53
|
+
return h("div", { key: plugin[0], style: { display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap", padding: "12px 0", borderBottom: "1px solid var(--dsw-alias-border-l2)" } },
|
|
54
|
+
h("span", { style: { flex: "1 1 250px", overflowWrap: "anywhere" } }, plugin[0] + " · " + (installed?.version || t("missing"))), button(installed ? "update" : "install", plugin[0], installed ? "update" : "install"));
|
|
55
|
+
}),
|
|
56
|
+
error ? h("p", { role: "alert" }, t(error)) : null,
|
|
57
|
+
busy ? h("p", { role: "status" }, t("busy")) : state.status === "error" ? h("p", { role: "alert" }, t("error") + ": " + state.message) : state.status === "ok" ? h("p", { role: "status" }, t("ok")) : null);
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
inject: ["slots", "locale", "configForms"],
|
|
61
|
+
apply: function (ctx) {
|
|
62
|
+
ctx.effect(function () { return ctx.locale.register("enhancementSuite", { zh: zh, en: en }); });
|
|
63
|
+
var scope = ctx.configForms.get("enhancement-suite"), t = ctx.locale.bind("enhancementSuite");
|
|
64
|
+
ctx.slots.inject("plugins.bundle.config", function () {
|
|
65
|
+
return ctx.slots.register({ name: "plugins.bundle.config", key: "dsh-enhancement-suite", locale: "enhancementSuite" }, function (props) {
|
|
66
|
+
return h(SuitePage, Object.assign({}, props, { scope: scope, t: t, locale: ctx.locale }));
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
});
|
package/cordis.patch.yml
ADDED
package/docs/architecture.md
CHANGED
|
@@ -1,102 +1,11 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
┌─────────────────────────────────────────────────────────────┐
|
|
15
|
-
│ dsh-enhancement-suite (this repo) │
|
|
16
|
-
│ README / docs / manifest / CLI │
|
|
17
|
-
│ └── bin/dsh-enhance.mjs ── spawns ──▶ dsh plugin CLI │
|
|
18
|
-
│ │ │
|
|
19
|
-
│ plugins.json (registry metadata only) │ installs │
|
|
20
|
-
└──────────────────────────────────────────────│──────────────┘
|
|
21
|
-
▼
|
|
22
|
-
┌───────────────┬───────────────┬───────────────┬──────────────────┐
|
|
23
|
-
│ dsh-tool-vision│ dsh-soul-md │ dsh-tdai-memory│ dsh-plugin- │
|
|
24
|
-
│ (upstream) │ (upstream) │ (upstream) │ marketplace │
|
|
25
|
-
└───────────────┴───────────────┴───────────────┴──────────────────┘
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
## Why the official CLI, and why not transitive dependencies
|
|
29
|
-
|
|
30
|
-
Installing through `dsh plugin --profile <p> add <pkg>` (which forwards to pnpm
|
|
31
|
-
inside the profile and reconciles `dsh.profile.bundles`) keeps the plugins
|
|
32
|
-
resolvable from the **profile root**, exactly as if the user installed them by
|
|
33
|
-
hand. Loading the plugins as dependencies of this suite package would make them
|
|
34
|
-
resolve through the suite's `node_modules` chain, which pnpm may place outside
|
|
35
|
-
the profile — plugins then fail to load at boot. Hence:
|
|
36
|
-
|
|
37
|
-
- `package.json` has **zero dependencies**.
|
|
38
|
-
- The suite never emits its own cordis patch for the four plugins.
|
|
39
|
-
- Mounting (when required) is written into the **profile's own**
|
|
40
|
-
`cordis.patch.yml`, with the same idempotent logic the marketplace uses.
|
|
41
|
-
|
|
42
|
-
## Plugin manifest (`plugins.json`)
|
|
43
|
-
|
|
44
|
-
| Field | Meaning |
|
|
45
|
-
|---|---|
|
|
46
|
-
| `key` | Short CLI key (`vision`, `soul`, `memory`, `marketplace`) |
|
|
47
|
-
| `name` | npm package name (also the `dsh plugin add` argument) |
|
|
48
|
-
| `displayName` | Display name |
|
|
49
|
-
| `emoji` | Card emoji used by the CLI/README |
|
|
50
|
-
| `category` | Suite category |
|
|
51
|
-
| `repo` | Upstream GitHub repository (source of truth) |
|
|
52
|
-
| `description` / `descriptionEn` | Bilingual one-line descriptions |
|
|
53
|
-
|
|
54
|
-
CI validates: exactly four plugins, no duplicate names/keys, all required
|
|
55
|
-
fields present, `repo` is an https GitHub URL.
|
|
56
|
-
|
|
57
|
-
## Install flow
|
|
58
|
-
|
|
59
|
-
1. `dsh plugin --profile <profile> add <package>` (official CLI).
|
|
60
|
-
2. If the installed package declares `dsh.bundle.patch` (currently only
|
|
61
|
-
`dsh-plugin-marketplace`) → the reconcile step already registered it in
|
|
62
|
-
`dsh.profile.bundles`; the bundle layer auto-mounts it. **No patch edit.**
|
|
63
|
-
3. Otherwise (plain dependency) → append a mount row to the profile's
|
|
64
|
-
`cordis.patch.yml`:
|
|
65
|
-
- idempotent (scans for `name: '<pkg>'`);
|
|
66
|
-
- an empty `[]` patch (optionally after comment lines) is **replaced**
|
|
67
|
-
with a block-style `- insert:` list — appending after `[]` would create
|
|
68
|
-
two top-level YAML documents and crash boot;
|
|
69
|
-
- a non-empty flow-style array is **refused** with a manual-mount message;
|
|
70
|
-
- a package already in `dsh.profile.bundles` is skipped.
|
|
71
|
-
4. `update` maps to `dsh plugin --profile <profile> update <package>`, then
|
|
72
|
-
re-runs the idempotent mount check.
|
|
73
|
-
|
|
74
|
-
## Safety rules
|
|
75
|
-
|
|
76
|
-
- **No shell string concatenation.** Every subprocess is spawned with an
|
|
77
|
-
argument array; on Windows the `.cmd` shim is executed with Node's
|
|
78
|
-
per-argument quoting (`shell: true` + args array, never a joined command
|
|
79
|
-
string).
|
|
80
|
-
- **No secrets.** The CLI never reads, prints, or forwards API keys; it does
|
|
81
|
-
not touch environment secrets or the credentials store.
|
|
82
|
-
- **No swallowed failures.** Each plugin's install/update reports its own
|
|
83
|
-
`✓`/`✗`; failures are collected, summarized, and reflected in the exit code
|
|
84
|
-
(non-zero on any failure). Partial state is never hidden.
|
|
85
|
-
- **`--dry-run`** prints the exact commands and patch edits without executing.
|
|
86
|
-
|
|
87
|
-
## Doctor checks
|
|
88
|
-
|
|
89
|
-
- Node version ≥ `22.18` (suite-wide requirement inherited from
|
|
90
|
-
`dsh-tdai-memory`).
|
|
91
|
-
- `dsh` CLI present on `PATH` (override with `DSH_ENHANCE_DSH_BIN`).
|
|
92
|
-
- Target profile directory exists.
|
|
93
|
-
- Per plugin: installed version, mount state (bundles / patch / own bundle
|
|
94
|
-
layer).
|
|
95
|
-
|
|
96
|
-
## Versioning and release
|
|
97
|
-
|
|
98
|
-
- Suite version follows semver; the README badges query npm **live** for the
|
|
99
|
-
four plugins, so version numbers are never hard-coded.
|
|
100
|
-
- npm publishing is intentionally not automated yet; CI only syntax-checks the
|
|
101
|
-
CLI, validates the manifest, and optionally cross-checks npm availability
|
|
102
|
-
(network failures are informational, `continue-on-error`).
|
|
1
|
+
# Enhancement suite architecture
|
|
2
|
+
|
|
3
|
+
The suite has two entry points: a DSH bundle with a configuration page, and the standalone dsh-enhance CLI. plugins.json owns the six-plugin registry, including dsh-motion-ui.
|
|
4
|
+
|
|
5
|
+
The Host bundle registers enhancement-suite with the same management schema and request consumer exported by dsh-plugin-marketplace/management. It passes the six package names as the allowed batch selection. The browser uses configForms to submit revision-checked requests. The suite does not mount the marketplace Host itself; installing the marketplace as a profile dependency gives it its own independent bundle entry.
|
|
6
|
+
|
|
7
|
+
The shared engine discovers the active profile from profileContext and settings.documentPath. Desktop subprocesses use the packaged dsh-desktop-host CLI under Electron Node mode, which carries Desktop profile authorization and bundled pnpm. Web subprocesses use their active dsh CLI. A process-wide profile queue serializes suite and marketplace package operations, including when module copies differ.
|
|
8
|
+
|
|
9
|
+
Install and update invoke the official CLI with add package@latest. DSH reconciles bundle registrations. Uninstall invokes remove and structurally removes legacy manual YAML mounts and their configuration patches. Inventory reads direct profile dependencies plus built-in bundle names; built-ins remain managed by DSH. Progress, completion and errors use the plugin settings namespace outside HMR transactions. A failed batch reports partial installed state.
|
|
10
|
+
|
|
11
|
+
The CLI retains list/install/update/doctor and --only/--profile/--dry-run. Windows Desktop installations shadowed by a global Web CLI can set DSH_ENHANCE_DESKTOP_EXECUTABLE to select the packaged carrier explicitly. The UI always uses the active Host carrier. Package changes require restarting DSH.
|
package/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import z from "@deepseek-ai/schemastery";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { managementFields, installManagement } from "dsh-plugin-marketplace/management";
|
|
4
|
+
|
|
5
|
+
export const name = "enhancement-suite";
|
|
6
|
+
export const inject = ["settings", "profileContext"];
|
|
7
|
+
export const Config = z.object(managementFields).volatile();
|
|
8
|
+
const manifest = JSON.parse(readFileSync(new URL("./plugins.json", import.meta.url), "utf8"));
|
|
9
|
+
|
|
10
|
+
/** Mount the same Desktop-aware operation engine used by the marketplace. */
|
|
11
|
+
export function apply(ctx, config) {
|
|
12
|
+
installManagement(ctx, config, name, { packages: manifest.plugins.map(plugin => plugin.name) });
|
|
13
|
+
}
|
package/locale/en.json
ADDED
package/locale/zh.json
ADDED
package/package.json
CHANGED
|
@@ -1,44 +1,80 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "dsh-enhancement-suite",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
5
|
-
"type": "module",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"engines": {
|
|
8
|
-
"node": ">=22.
|
|
9
|
-
},
|
|
10
|
-
"bin": {
|
|
11
|
-
"dsh-enhance": "./bin/dsh-enhance.mjs"
|
|
12
|
-
},
|
|
13
|
-
"files": [
|
|
14
|
-
"bin",
|
|
15
|
-
"plugins.json",
|
|
16
|
-
"README.md",
|
|
17
|
-
"README.zh.md",
|
|
18
|
-
"LICENSE",
|
|
19
|
-
"docs"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"dsh",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "dsh-enhancement-suite",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Install and update six DSH enhancement plugins from Desktop/Web configuration or the CLI, including Motion UI.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=22.19"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"dsh-enhance": "./bin/dsh-enhance.mjs"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"bin",
|
|
15
|
+
"plugins.json",
|
|
16
|
+
"README.md",
|
|
17
|
+
"README.zh.md",
|
|
18
|
+
"LICENSE",
|
|
19
|
+
"docs",
|
|
20
|
+
"index.js",
|
|
21
|
+
"client.js",
|
|
22
|
+
"cordis.patch.yml",
|
|
23
|
+
"locale",
|
|
24
|
+
"VERIFICATION.md"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"check": "node --check index.js && node --check client.js && node --check bin/dsh-enhance.mjs && node bin/validate-manifest.mjs && node bin/dsh-enhance.mjs --help && node bin/dsh-enhance.mjs list",
|
|
28
|
+
"prepublishOnly": "npm run check",
|
|
29
|
+
"test": "node --test tests/*.test.mjs"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"deepseek-harness",
|
|
33
|
+
"dsh",
|
|
34
|
+
"dsh-plugin",
|
|
35
|
+
"ai-agent",
|
|
36
|
+
"vision",
|
|
37
|
+
"memory",
|
|
38
|
+
"persona",
|
|
39
|
+
"plugin-marketplace"
|
|
40
|
+
],
|
|
41
|
+
"repository": {
|
|
42
|
+
"type": "git",
|
|
43
|
+
"url": "git+https://github.com/Scorp1o117/dsh-enhancement-suite.git"
|
|
44
|
+
},
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/Scorp1o117/dsh-enhancement-suite/issues"
|
|
47
|
+
},
|
|
48
|
+
"homepage": "https://github.com/Scorp1o117/dsh-enhancement-suite",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"dsh-plugin-marketplace": "^0.5.0",
|
|
51
|
+
"@deepseek-ai/schemastery": "^3.18.4"
|
|
52
|
+
},
|
|
53
|
+
"main": "index.js",
|
|
54
|
+
"exports": {
|
|
55
|
+
".": "./index.js",
|
|
56
|
+
"./client": "./client.js",
|
|
57
|
+
"./package.json": "./package.json",
|
|
58
|
+
"./locale/*.json": "./locale/*.json"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@deepseek-ai/dsh-settings": ">=0.2.0-rc.2 <0.3.0",
|
|
62
|
+
"react": "^18.2.0"
|
|
63
|
+
},
|
|
64
|
+
"dsh": {
|
|
65
|
+
"bundle": {
|
|
66
|
+
"patch": "./cordis.patch.yml"
|
|
67
|
+
},
|
|
68
|
+
"client": {
|
|
69
|
+
"platform": "web"
|
|
70
|
+
},
|
|
71
|
+
"compatibility": {
|
|
72
|
+
"dsh": ">=0.2.0-rc.2 <0.3.0",
|
|
73
|
+
"node": ">=22.19",
|
|
74
|
+
"profiles": [
|
|
75
|
+
"web",
|
|
76
|
+
"desktop"
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
package/plugins.json
CHANGED
|
@@ -1,54 +1,76 @@
|
|
|
1
|
-
{
|
|
2
|
-
"suite": "dsh-enhancement-suite",
|
|
3
|
-
"node": ">=22.
|
|
4
|
-
"dsh": ">=0.
|
|
5
|
-
"defaultProfile": "web",
|
|
6
|
-
"rc6Pins": {
|
|
7
|
-
"dsh-tool-vision": "0.6.1",
|
|
8
|
-
"dsh-soul-md": "0.5.6",
|
|
9
|
-
"dsh-tdai-memory": "0.2.11",
|
|
10
|
-
"dsh-plugin-marketplace": "0.2.6"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"suite": "dsh-enhancement-suite",
|
|
3
|
+
"node": ">=22.19",
|
|
4
|
+
"dsh": ">=0.2.0-rc.2 <0.3.0",
|
|
5
|
+
"defaultProfile": "web",
|
|
6
|
+
"rc6Pins": {
|
|
7
|
+
"dsh-tool-vision": "0.6.1",
|
|
8
|
+
"dsh-soul-md": "0.5.6",
|
|
9
|
+
"dsh-tdai-memory": "0.2.11",
|
|
10
|
+
"dsh-plugin-marketplace": "0.2.6",
|
|
11
|
+
"dsh-reasoning-options": "none",
|
|
12
|
+
"dsh-motion-ui": "none"
|
|
13
|
+
},
|
|
14
|
+
"plugins": [
|
|
15
|
+
{
|
|
16
|
+
"key": "vision",
|
|
17
|
+
"name": "dsh-tool-vision",
|
|
18
|
+
"displayName": "dsh-tool-vision",
|
|
19
|
+
"emoji": "👁️",
|
|
20
|
+
"category": "Vision",
|
|
21
|
+
"repo": "https://github.com/Scorp1o117/dsh-tool-vision",
|
|
22
|
+
"description": "给文本模型增加视觉能力和图片桥接。",
|
|
23
|
+
"descriptionEn": "Adds vision capability and image bridging to text-only models."
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"key": "soul",
|
|
27
|
+
"name": "dsh-soul-md",
|
|
28
|
+
"displayName": "dsh-soul-md",
|
|
29
|
+
"emoji": "🎭",
|
|
30
|
+
"category": "Persona",
|
|
31
|
+
"repo": "https://github.com/Scorp1o117/dsh-soul-md",
|
|
32
|
+
"description": "为 Agent 增加 soul.md 人设、会话/工作区 Persona 和可演化人格。",
|
|
33
|
+
"descriptionEn": "soul.md personas, session/workspace persona switching, and an evolving personality with long-term memory."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
"key": "memory",
|
|
37
|
+
"name": "dsh-tdai-memory",
|
|
38
|
+
"displayName": "dsh-tdai-memory",
|
|
39
|
+
"emoji": "🧠",
|
|
40
|
+
"category": "Memory",
|
|
41
|
+
"repo": "https://github.com/Scorp1o117/dsh-tdai-memory",
|
|
42
|
+
"description": "完整的长期分层记忆、召回与搜索。",
|
|
43
|
+
"descriptionEn": "Full long-term layered memory (L0-L3), recall and search."
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"key": "marketplace",
|
|
47
|
+
"name": "dsh-plugin-marketplace",
|
|
48
|
+
"displayName": "dsh-plugin-marketplace",
|
|
49
|
+
"emoji": "🛒",
|
|
50
|
+
"category": "Marketplace",
|
|
51
|
+
"repo": "https://github.com/Scorp1o117/dsh-plugin-marketplace",
|
|
52
|
+
"description": "直接在 DSH Web UI 中发现和浏览插件。",
|
|
53
|
+
"descriptionEn": "Discover and browse plugins directly inside the DSH Web UI."
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"key": "reasoning",
|
|
57
|
+
"name": "dsh-reasoning-options",
|
|
58
|
+
"displayName": "dsh-reasoning-options",
|
|
59
|
+
"emoji": "🎚️",
|
|
60
|
+
"category": "Model",
|
|
61
|
+
"repo": "https://github.com/Scorp1o117/dsh-reasoning-options",
|
|
62
|
+
"description": "为第三方模型添加推理档位,支持 Default 不注入推理强度。",
|
|
63
|
+
"descriptionEn": "Reasoning levels with native Default (no injected effort)."
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"key": "motion",
|
|
67
|
+
"name": "dsh-motion-ui",
|
|
68
|
+
"displayName": "dsh-motion-ui",
|
|
69
|
+
"emoji": "✨",
|
|
70
|
+
"category": "UI",
|
|
71
|
+
"repo": "https://github.com/Scorp1o117/dsh-motion-ui",
|
|
72
|
+
"description": "交互界面、HTML/SVG 动画与本地计算。",
|
|
73
|
+
"descriptionEn": "Interactive UI, HTML/SVG animation and local calculations."
|
|
74
|
+
}
|
|
75
|
+
]
|
|
76
|
+
}
|