dsh-plugin-wukong-cli 0.22.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/README.md ADDED
@@ -0,0 +1,423 @@
1
+ # Wukong
2
+
3
+ > **面向 DeepSeek Harness 的社区插件 / 管理中枢** — 提示词、技能、MCP 工具服务器、全局壁纸与特效,一站式管理面板。
4
+
5
+ **插件包 / 安装器**:插件包 `dsh-plugin-wukong` · 安装器包 `dsh-plugin-wukong-cli`(命令 `wukong`) · [GitHub](https://github.com/agassiz/dsh-plugin-wukong)
6
+
7
+ **中文** · [**English**](./README.en.md)
8
+
9
+ ![Wukong:壁纸、毛玻璃与管理面板(深色)](docs/preview/hero-dark.jpg)
10
+
11
+ | <img src="docs/preview/hero-light.jpg" width="190"/> | <img src="docs/preview/prompts.png" width="190"/> | <img src="docs/preview/skills.png" width="190"/> | <img src="docs/preview/mcp.png" width="190"/> | <img src="docs/preview/wallpaper.png" width="190"/> |
12
+ |--|--|--|--|--|
13
+ | 浅色主题 | 提示词 | 技能 | MCP | 壁纸 |
14
+
15
+ ![version](https://img.shields.io/badge/version-0.22.0-00ff9c)
16
+ ![license](https://img.shields.io/badge/license-MIT-blue)
17
+ ![platform](https://img.shields.io/badge/platform-web%20%2B%20desktop-00ff9c)
18
+ ![runtime](https://img.shields.io/badge/runtime-DSH%200.2.0--rc.2-8957e5)
19
+ ![CI](https://github.com/agassiz/dsh-plugin-wukong/actions/workflows/ci.yml/badge.svg)
20
+
21
+ ```
22
+ ✦ Wukong v0.21.0
23
+ ┌─────────┬─────────┬─────┬────────────┬──────┬──────┐
24
+ │ 提示词 │ 技能 │ MCP │ Wallpaper │ 对话 │ 统计 │
25
+ │ 作用域注入 │ 合并管理 │ 连接 │ 壁纸·特效 │ 导入 │ 用量 │
26
+ └─────────┴─────────┴─────┴────────────┴──────┴──────┘
27
+ ```
28
+
29
+ ---
30
+
31
+ ## 📑 目录
32
+
33
+ - [🚀 快速开始](#-快速开始)
34
+ - [🎯 适配目标 · Supported upstreams](#-适配目标--supported-upstreams)
35
+ - [✨ 功能](#-功能)
36
+ - [🗄️ 状态与数据](#️-状态与数据)
37
+ - [⌨️ 斜杠命令](#️-斜杠命令)
38
+ - [🖥️ 平台支持](#️-平台支持)
39
+ - [🔄 一键更新](#-一键更新)
40
+ - [🗑️ 卸载](#️-卸载)
41
+ - [🧰 在聊天中使用技能](#-在聊天中使用技能)
42
+ - [🏗️ 架构](#️-架构)
43
+ - [📦 包含的包](#-包含的包)
44
+ - [🗂️ 仓库结构](#️-仓库结构)
45
+ - [🛠️ 开发](#️-开发)
46
+ - [❓ FAQ](#-faq)
47
+ - [📚 文档](#-文档)
48
+ - [🤝 贡献 / 官方合入](#-贡献--官方合入)
49
+ - [📄 许可](#-许可)
50
+ - [🔗 友情链接 · Friends](#-友情链接--friends)
51
+
52
+ ---
53
+
54
+ ## 🎯 适配目标 · Supported upstreams
55
+
56
+ Wukong 是 **DeepSeek Harness 的插件**,按下列官方运行时的 **0.2.0-rc.2 内部接口世代**移植与测试:
57
+
58
+ | 上游 | 对应环境 | 仓库 |
59
+ |---|---|---|
60
+ | **DeepSeek Harness** | `dsh web` 网页端运行时 | <https://github.com/deepseek-ai/deepseek-harness> |
61
+ | **DSH Desktop** | 桌面客户端 | <https://github.com/anywhere-labs/dsh-desktop> |
62
+
63
+ > ⚠️ **要求 DSH 0.2.0-rc.2(或同一接口世代的构建)。** 0.12.0 已把插件移植到当前世代:harness 的 settings 服务改成了「每个 loader 条目一个命名空间」(`SettingsForms`),旧的 `settingsNamespace` / `settingsScope` 接口**在该世代已不存在**。因此**面向旧 2.0.9 世代的构建(0.11.x 及更早)不再受支持**,本插件也**有意不提供向后兼容**——两代接口只能二选一。0.13.0 在此基础上完成了打包与安装的标准化:原来的两个包(`@deepseek-ai/dsh-switchblade` + `@deepseek-ai/dsh-client-ui-switchblade`)合并为一个可发布的插件包 `dsh-switchblade`;0.14.0 项目更名为 **Wukong**,插件包随之改名、目录改为 `packages/wukong/`;0.15.0 把安装器从插件包里拆了出来,两个包自此各自命名;**0.21.0 统一改名为插件包 `dsh-plugin-wukong` 与安装器包 `dsh-plugin-wukong-cli`(bin 仍是 `wukong`),插件自身数据目录仍为 `$DSH_HOME/wukong/`。**
64
+ >
65
+ > ⚠️ **请使用上述官方仓库的构建(或其保持兼容的派生版)。** 其他 fork / 魔改版本的内部接口可能不同,导致面板无法挂载、状态不生效、命令缺失,甚至让客户端进入恢复模式——那不是本插件的 bug。安装或反馈前请先确认你的运行时来自以上两个出处。
66
+
67
+ ---
68
+
69
+ ## 🚀 快速开始
70
+
71
+ ### 安装
72
+
73
+ **两个包,名字不同**:跑的是安装器 **`dsh-plugin-wukong-cli`**(bin 为 `wukong`),它装的是插件包 **`dsh-plugin-wukong`**。拆开这两个名字的原因很简单:`pnpm add dsh-plugin-wukong`(或在 harness 插件管理器里选 `dsh-plugin-wukong`)本来就是标准路径,安装器命令与 bundle 分开叫,才不会互相抢名字。
74
+
75
+ **从仓库里直接跑**(把当前工作副本装进 profile 时,用 `--spec` 指定本地路径):
76
+
77
+ ```bash
78
+ node cli.cjs --profile web --spec link:<仓库>/packages/wukong # 只装 web profile,装的是工作副本
79
+ node cli.cjs # 装到全部 profile(默认装 npm 上已发布的 dsh-plugin-wukong@<同版本>)
80
+ ```
81
+
82
+ **安装器发布到 npm 之后**:
83
+
84
+ ```bash
85
+ npx dsh-plugin-wukong-cli # 无需 checkout;npx 只解析包名,所以这里必须写包名 dsh-plugin-wukong-cli
86
+ npm i -g dsh-plugin-wukong-cli # 或全局安装,再使用 bin 名
87
+ wukong # 全局安装后的命令名(bin)
88
+ ```
89
+
90
+ > ⚠️ 别把两个名字混起来:`dsh-plugin-wukong` 是**插件包**、没有 bin,要跑安装器请用 `npx dsh-plugin-wukong-cli`(或先 `npm i -g dsh-plugin-wukong-cli` 再直接跑 `wukong`)。`wukong` 是 bin 名而不是包名,**不能交给 npx 直接调用**(npx 会把 `wukong` 当成另一个包去 npm 上找)。改名前的 `prompt-skill-armory` 停在 **0.11.0**——那是旧 2.0.9 世代、对当前运行时已经坏了的版本,已不再使用。
91
+
92
+ ```bash
93
+ node cli.cjs -h # 只打印用法并退出,不装任何东西(--help 同义)
94
+ node cli.cjs -v # 只打印安装器与插件版本并退出,不装任何东西(--version 同义)
95
+ ```
96
+
97
+ 安装器走的是 harness 的**标准插件安装路径**:
98
+
99
+ 1. 在 profile 目录里执行 `pnpm add <spec>`:默认 spec 是 npm 上已发布的 `dsh-plugin-wukong@<安装器版本>`,`--spec <spec>` 可换成任何普通 pnpm 来源(npm 包名、本地路径、tarball、git 地址),装上后 `dsh-plugin-wukong` 就是 profile 的正式依赖
100
+ 2. 把 `dsh-plugin-wukong` 追加到 profile 的 `dsh.profile.bundles`
101
+ 3. 清理更早版本留下的安装痕迹:旧 bundle/依赖名 `dsh-switchblade` 与 `@deepseek-ai/dsh-switchblade`、`node_modules/@deepseek-ai/` 下 `dsh-switchblade` 与 `dsh-client-ui-switchblade` 两份拷贝式安装、profile `cordis.patch.yml` 里手写的 `ui-switchblade` 行(只删这一条,其余行——空行也算——逐字节保留,因为那份文件 DSH.app 也在写),以及旧的 `$DSH_HOME/{switchblade,wallpapers,armory-exports}` 数据目录。`dsh-plugin-wukong` 这个依赖名**不用清也不能清**:它就是现在的插件包名
102
+ 4. 体检 `settings.yaml` 体积(防 4MB 膨胀)——插件本身不写该文件
103
+
104
+ 安装器需要 **pnpm**:profile 安装本质就是一条 pnpm 依赖,找不到 pnpm 时安装器直接报错退出,不会退化成别的装法。
105
+
106
+ 因为 `dsh-plugin-wukong` 是一条带 bundle patch 的**真实 profile 依赖**,harness 插件管理器会把它列入:侧栏**插件**页和**设置 → 插件**的「已安装」里都能看到、能开关。面板本身仍在 **设置 → Wukong**(书图标)。
107
+
108
+ 常用参数:
109
+
110
+ ```bash
111
+ node cli.cjs --profile web # 只装 web profile
112
+ node cli.cjs --profile web,desktop # 指定多个(可重复、逗号分隔,-p 为简写)
113
+ node cli.cjs --spec dsh-plugin-wukong@0.21.0 # 指定来源:npm 包名 / 本地路径 / tarball / git 地址
114
+ node cli.cjs --spec link:/abs/path/to/packages/wukong --profile web # 把工作副本装进 profile
115
+ node cli.cjs -h # 只打印用法并退出(--help 同义)
116
+ node cli.cjs -v # 只打印安装器与插件版本并退出(--version 同义)
117
+ node cli.cjs uninstall --profile web # 只从 web 卸载
118
+ ```
119
+
120
+ `--profile` 可重复、可逗号分隔;**不带该参数时才会装到全部 profile**。选中的标准 profile 不存在时会按标准配置创建;名字写错会直接报错并列出当前可用的 profile。
121
+
122
+ `--spec` 是唯一的来源覆盖:给了它就用它,不给就用默认的已发布包 `dsh-plugin-wukong@<安装器版本>`。本地路径、tarball、git 地址都是普通 pnpm spec,装法与 npm 包名完全一样。`--postinstall` 是 npm 钩子,本身不装任何东西。
123
+
124
+ ### 启动
125
+
126
+ ```bash
127
+ dsh web # 或直接重启 DSH Desktop 客户端
128
+ ```
129
+
130
+ 打开 **设置 → Wukong**(书图标)。
131
+
132
+ > **要求**:已安装 DeepSeek Harness 运行时(0.2.0-rc.2 世代;`dsh web` 或桌面客户端)。插件是 DSH 的插件,不打包运行时本身——同时也**不需要 deepseek-harness 源码 checkout**:插件包带的是 esbuild 预构建产物(`lib/` + `client/`)。
133
+
134
+ ---
135
+
136
+ ## ✨ 功能
137
+
138
+ - **提示词(可作用域)** — 增删改查、启用/停用、设默认。作用域五选一:**全局**(默认)/ **仅指定项目**(按会话工作区目录名匹配)/ **仅指定会话** / **除指定项目外** / **除指定会话外**。启用后经 `ctx.systemPrompt.section` 注入:作用域内的提示词**只对匹配的 agent 返回正文**,不匹配的 section 返回空串、由渲染阶段直接丢弃——因此不会泄漏到其他项目或会话。提示词正文以**关闭插值**(`interpolate: false`)的 section 注册,正文里字面写的 `{{cwd}}`(或任何 `{{...}}`)会**原样送到模型**,不会被当成模板 token;否则渲染阶段会因插值失败而让每个启用该提示词的会话每一步都失败。
139
+ - **技能(合并管理)** — 一个列表:面板安装的(编辑/开关/卸载)+ 本地扫描的(托管),带调用提示 `/name`。
140
+ - **技能安装方式**
141
+ - 手动填写
142
+ - `.md` 文件选择
143
+ - 面板导入 `.zip` 技能包(上传到 `$DSH_HOME/skills`)
144
+ - 会话内命令:`/wukong-skill-dir <dir>`(目录式,浏览器读不到主机目录,只能在这里装)
145
+ - **MCP 工具服务器** — 添加/编辑/移除 stdio 或 HTTP 的 MCP 服务器,启用即自动连接,每台展示运行状态与工具列表,支持「测试」连接。
146
+ - **Wallpaper(全局壁纸与特效)** — 五张随包附带的**原创内置风景**(点一下即应用)、本地上传图片/视频或填图片 URL;壁纸的主题 token 通过官方 `ctx.theme.overrideTokens` 合成一层覆盖,切换亮/暗主题自动跟随;透明度/遮罩/玻璃/模糊/铺法实时可调;**web 与桌面客户端分别设置**。上传的字节存盘,状态文档里只留 id,永远不会把二进制写进配置。
147
+ - **输入栏提示行样式** — 为 composer 下方提示与统计行单独设启用/颜色/字号/渐变色。
148
+ - **对话导入 / 导出** — 勾选多个会话导出为 zip(含附件与工作区),另一台机器导入即可还原;列表显示对话标题、项目、时间与占用大小;支持**真实删除**(删目录 + 清索引;仍在运行的会话会被拒绝),导入经会话持久化服务流式写盘。导出的 zip 存在 `$DSH_HOME/wukong/exports/`,且每次导出后自动清理:保留最新 10 个,并删除超过 7 天的归档。
149
+ - **使用统计(cc-switch 风格)** — 时间范围筛选(全部/30天/7天/今天);输入/输出/缓存读/缓存写 Token、缓存命中率、成本估算;请求日志(时间/项目/输入输出/缓存/成本/用时/首字/状态);Provider(项目)统计与模型统计;SVG 双轴趋势图(今天按 24 小时分段)。统计与会话列表都通过 harness 的 session-query 服务读取(项目目录编码与持久化后端保持一致),缓存命中率与首字时间取自真实用量数据。
150
+ - **单个状态文档** — 全部托管状态写在一个私有 JSON 文档里(见下节),**原子写入**(临时文件 + rename),不会挤占 harness 的 settings 文档。
151
+ - **标准插件打包** — 一个包 `dsh-plugin-wukong` 同时声明 Host bundle patch 与浏览器面板(`dsh.bundle.patch` + `dsh.client`),安装后出现在侧栏**插件**页与**设置 → 插件**的「已安装」列表,可被插件管理器开关。
152
+ - **中英双语 UI**(简体中文 / English)。
153
+ - **设置侧边栏书图标**。
154
+
155
+ ---
156
+
157
+ ## 🗄️ 状态与数据
158
+
159
+ 0.12.0 起,Wukong 不再使用 harness 的 settings 命名空间:全部托管状态放在插件自己的文档与目录里。
160
+
161
+ | 路径 | 内容 |
162
+ |---|---|
163
+ | `$DSH_HOME/wukong/state.json`(默认 `~/.dsh/wukong/state.json`) | 提示词、托管技能、自定义命令、MCP 服务器、壁纸/特效设置(壁纸只存 id) |
164
+ | `$DSH_HOME/wukong/wallpapers/` | 上传的壁纸 / 视频字节 |
165
+ | `$DSH_HOME/skills/` | zip / 目录方式安装的技能(官方 filesystem 技能 provider 扫描并监听该根目录) |
166
+ | `$DSH_HOME/wukong/exports/` | 对话导出 zip |
167
+
168
+ 面板与 Host 之间只走插件自己的**同源 HTTP 路由**(旧的 `api.settings.mutate/describe` 与 `ctx.settingsScope` 路径已全部移除):
169
+
170
+ | 路由 | 用途 |
171
+ |---|---|
172
+ | `GET` / `POST /api/wukong/state` | 读写状态文档(面板的增删改查都走这里):读返回 `{ok, revision, state}`;写收 `{state, ifRevision}`,每次写入都会归一化文档并让 `revision` 加一 |
173
+ | `GET /api/wukong/skills` | 面板要的技能 + 托管命令目录:`{ok, revision, skills, commands}`,不必再从整份状态文档里重建 |
174
+ | `POST /api/wukong/mcp/test` | 一次性 MCP 连接测试 |
175
+ | `GET /api/wukong/market` · `POST /api/wukong/market/install` | 扩展市场:按 `kind=mcp\|skill` 与 `q` 搜索聚合目录(官方 MCP Registry、DSH MCP Market、ClawHub、SkillsMP + 随包精选),安装时只接受显式条目 id;MCP 需要环境变量时以禁用状态装好并返回 `needsEnv` |
176
+ | `POST /api/wukong/skills/zip` | 上传 zip 技能包并解压到 `$DSH_HOME/skills` |
177
+ | `POST /api/wukong-wallpaper/upload` · `GET /api/wukong-wallpaper/image/<id>` | 壁纸上传(流式写盘,上限 60MB)/ 回读(流式,支持 `Range`) |
178
+ | `GET /api/wukong-wallpaper/preset/<id>.jpg` · `<id>-thumb.jpg` | 随包附带的五张内置风景及缩略图(`dawn-peaks` / `misty-forest` / `desert-dusk` / `night-coast` / `alpine-lake`) |
179
+ | `GET /api/wukong/version` | 版本检查:`{ok, latest, current}`(`current` 运行时读自插件 `package.json`,`latest` 是 npm 上的最新发布版,取不到时为空串) |
180
+ | `GET /api/wukong/stats` · `/sessions`,`POST /api/wukong/export` · `/import` · `/delete` · `/update` | 统计、会话列表、导出/导入/删除、一键更新(更新走 `dsh-plugin-wukong-cli`,需显式确认) |
181
+
182
+ 写入的乐观并发约定:`ifRevision` 与当前 `revision` 不符时,`POST /api/wukong/state` 返回 **HTTP 409** 与 `{ok:false, error:'stale', revision, state}`,调用方应当采用返回的文档(兼容起见,直接提交扁平状态文档仍然接受)。每次读取(`GET`)同样会先归一化文档。
183
+
184
+ ### 扩展市场(MCP 与技能)
185
+
186
+ 面板的技能页与 MCP 页里都有一个可折叠的市场区块,也可以直接调 `GET /api/wukong/market?kind=mcp|skill&q=<关键词>`。市场是**来源聚合与安装编排**,不是目录的所有者,也不把上游收录当作安全审计:
187
+
188
+ | 来源 | 用途 |
189
+ |---|---|
190
+ | 官方 MCP Registry(`registry.modelcontextprotocol.io`) | MCP 服务器发现:npm 包 + stdio 传输,或 streamable-http 远端地址、版本与环境变量声明 |
191
+ | DSH MCP Market 快照 | DSH 形状的精选 MCP 目录,可直接转成插件的 MCP 行 |
192
+ | ClawHub | 技能搜索(隐藏可疑条目);安装时经公开 file API 取 `SKILL.md`,可固定版本 |
193
+ | SkillsMP | 技能元数据 + GitHub star;安装时回到条目的 GitHub 源码下载整个技能目录 |
194
+ | 随包精选 | 离线兜底:3 个 MCP 服务器 + 2 个技能模板,不联网也能装 |
195
+
196
+ - 每个条目都带来源名、来源等级(`bundled` / `official` / `curated` / `community`)、权限说明、热度与所需环境变量;**只有先搜索、再显式指定条目 id 才会安装**。
197
+ - 某个源不可达只影响它自己(状态行会提示);全部源失败时回退到 `$DSH_HOME/wukong/market-cache` 里的上次成功结果,再回退到随包精选。
198
+ - MCP 安装写入插件自己的 MCP 行:`serverName` 自动避让重名,需要环境变量的服务器**以禁用状态**安装并在响应里返回 `needsEnv`,变量在配置里写成 `${NAME}`。
199
+ - 技能安装分两条路径:单文件模板注册为运行时技能(面板立刻可见、每个会话可用、重启保持);带附加文件的仓库技能写进 `$DSH_HOME/skills/<name>`,交给 harness 的文件系统技能提供者。
200
+ - 安全边界:条目 schema 校验、技能相对路径禁止绝对路径 / `..` / 反斜杠 / 控制字符、单文件 1MB、单目录 8MB、归档 16MB、每源 10 秒超时、每个技能最多 64 个文件,GitHub 归档解压后再做包含性检查;安装不修改 profile,也不执行下载来的代码。
201
+
202
+ 技能目录(技能 tab 的清单)仍通过 remote RPC 读取(`api.skills.list`)。所有 wukong 路由都会拒绝跨站调用:外部来源或 opaque(`Origin: null`)来源、以及 `Sec-Fetch-Site: cross-site` 一律 **HTTP 403**;不带 `Origin` 的请求只在回环(loopback)主机上接受。
203
+
204
+ ---
205
+
206
+ ## ⌨️ 斜杠命令
207
+
208
+ | 命令 | 作用 |
209
+ |---|---|
210
+ | `/wukong-skill-dir <dir>` | 把技能目录(`SKILL.md` + references)装进用户技能根 |
211
+
212
+ 只剩这一条命令,因为它是面板唯一做不到的事——浏览器读不到任意主机目录。列出、启用 / 停用、卸载、markdown 与 zip 安装、状态查看、导出 / 导入 patch 层都由面板承担,不再各配一条命令:它们要么只是面板的重复,要么在 `/` 菜单里点一下就会因为缺参数直接报错。命令声明的 `input` 让 `/wukong-skill-dir` 被菜单选中时落回输入框等参数,而不是立刻执行。
213
+
214
+ 旧命令族 `/armory-*` 的别名已在 0.14.0 一并去掉,现在只有 `/wukong*` 一套名字。
215
+
216
+ > Agent 预设(prompt profile)管理已在 0.12.0 移除:`/wukong-profile` 不再存在,面板也从未提供该 tab(`@deepseek-ai/dsh-agent-presets` 包在该世代已不存在)。
217
+
218
+ ---
219
+
220
+ ## 🖥️ 平台支持
221
+
222
+ | 环境 | 面板 | `/wukong` 命令 |
223
+ |---|---|---|
224
+ | `dsh web`([deepseek-ai/deepseek-harness](https://github.com/deepseek-ai/deepseek-harness),0.2.0-rc.2) | ✅ | ✅ |
225
+ | DSH Desktop 客户端([anywhere-labs/dsh-desktop](https://github.com/anywhere-labs/dsh-desktop)) | ✅ | ✅ |
226
+
227
+ 通过 profile 组合实现(安装器把 `dsh-plugin-wukong` 装成 profile 依赖并选进 `dsh.profile.bundles`)——无需 fork 客户端,也不需要手改 `cordis.patch.yml`。
228
+
229
+ 归档与更新也已跨平台:导出/导入会话依次尝试 `zip`/`unzip` → bsdtar(`tar`)→ PowerShell,一键更新在 POSIX 上调用 `npm`、仅在 Windows 上调用 `npm.cmd`。
230
+
231
+ ## 🔄 一键更新
232
+
233
+ 插件面板每次打开都会查询 `GET /api/wukong/version`,Host 端返回 `{ok, latest, current}`:`current` 是**运行时**从 `lib/` 旁边的插件 `package.json` 读到的版本(面板里的编译期常量只作回退,两者不会再各自漂移),`latest` 是最新发布版——先问安装器包 `dsh-plugin-wukong-cli`,再问 `dsh-plugin-wukong`,两个都取不到(registry 不可达或尚未发布)时返回空串。面板版本徽章显示 `current`,并与 `latest` 比较;发现新版本时顶部显示横幅:
234
+
235
+ > 有新版本 vX.Y.Z(当前 v0.21.0) [一键更新]
236
+
237
+ 点击「一键更新」→ Host 端通过平台的 `npm`(Windows 为 `npm.cmd`)执行 `npm exec --yes --package=dsh-plugin-wukong-cli -- wukong`:装上并运行**安装器包**原地重装 → 提示「更新完成,请重启客户端生效」。该路由要求请求体显式带上 `{"confirm":true}`,否则返回 HTTP 400 `confirmation-required`。
238
+
239
+ ## 🗑️ 卸载
240
+
241
+ ```bash
242
+ node cli.cjs uninstall --profile web # 或 node cli.cjs uninstall(全部 profile)
243
+ ```
244
+
245
+ 移除方式与安装对称:`pnpm remove dsh-plugin-wukong`(没装 pnpm 时只提示并取消 bundle 选择,依赖留在 profile 里),从 `dsh.profile.bundles` 去掉 bundle,再做一次和安装时相同的遗留清理;最后删除插件自己的目录 `$DSH_HOME/wukong/`(状态文档 + 壁纸 + 对话导出)。
246
+
247
+ `$DSH_HOME/skills/` 下已解压的技能按设计保留;提示词/技能/MCP 等托管配置**随 `$DSH_HOME/wukong/` 一起删除**(0.14.0 起不再保留,卸载即彻底清除)。
248
+
249
+ ## 🧰 在聊天中使用技能
250
+
251
+ 在输入框打 `/` + 技能名:
252
+
253
+ ```
254
+ /code-review
255
+ /mission-keeper
256
+ ```
257
+
258
+ 技能体被注入,agent 按它执行。`modelInvocable` 的技能模型也可自主调用。
259
+
260
+ ## 🏗️ 架构
261
+
262
+ ```
263
+ DSH 运行时(0.2.0-rc.2)
264
+ │
265
+ ├─ Web 面板:dsh-plugin-wukong 的 client face(dsh.client)
266
+ │ GET/POST /api/wukong/state
267
+ │ GET /api/wukong/skills
268
+ │ POST /api/wukong/mcp/test
269
+ │ POST /api/wukong/skills/zip
270
+ │ POST /api/wukong-wallpaper/upload
271
+ │ GET /api/wukong-wallpaper/image/<id>
272
+ │ GET /api/wukong/stats | /sessions | /version
273
+ │ POST /api/wukong/export | /import | /delete | /update
274
+ │
275
+ ├─ remote RPC:api.skills.list
276
+ │
277
+ └─► Host 行:id=wukong,name=dsh-plugin-wukong(bundle)
278
+ • $DSH_HOME/wukong/state.json (原子写入)
279
+ • ctx.systemPrompt.section (按作用域注入)
280
+ • ctx.skills.register
281
+ ```
282
+
283
+ - **插件包一个包,两个面**:`dsh-plugin-wukong` 的 `package.json` 里 `dsh.bundle.patch` 指向自己的 `cordis.patch.yml`(唯一的 Host 行 `id: wukong`),同时 `dsh.client`(`platform: web` + `inject`)指向 `exports["./client"]` 的 `client/client.js`。面板由**同一个条目**的 `dsh.client` 字段发现,所以**不需要第二个插件包、也不需要第二条 loader 行**;安装器是另一个包(`dsh-plugin-wukong-cli`,不是 bundle)。
284
+ - **Host 侧**持有提示词/技能/命令/MCP/壁纸的 CRUD 与持久化(`$DSH_HOME/wukong/state.json`),通过 `ctx.systemPrompt.section` 按作用域注入提示词(关闭插值)、`ctx.skills.register` 注册技能;并注册 `/api/wukong/*` 与 `/api/wukong-wallpaper/*` 路由(状态读写、技能目录、MCP 测试、zip 技能、对话导入导出、会话删除、使用统计、版本检查、一键更新)。
285
+ - **面板侧**通过插件自有的同源路由读写状态文档,技能目录走插件自己的 `GET /api/wukong/skills`——**不碰 settings 命名空间**,也不直接调 DSH 内部,更不依赖 `api-remotes` / `sessions` 这类远程 API。面板的装载声明只列真实存在的包:`dsh.client.inject` 为 `@deepseek-ai/dsh-client-locale`、`@deepseek-ai/dsh-client-ui-settings`;其 cordis service inject 为 `['slots','locale']`。
286
+ - **可选 peer**:`@deepseek-ai/*` 运行时包与 `react` 全部在 `peerDependenciesMeta` 里标为 `optional`,运行时 `dependencies` 为空。原因是这些运行时包不在公共 npm 源上,写成必选 peer 会让 `pnpm add` 直接 `ERR_PNPM_FETCH_404` 失败;标成可选后 pnpm 能顺利安装,模块仍由宿主在运行时提供。
287
+ - **安装器**(`dsh-plugin-wukong-cli`)只做标准三件事:`pnpm add`、选 bundle、清理旧拷贝式安装——web 与 desktop profile 共用同一套机制。
288
+
289
+ ## 📦 包含的包
290
+
291
+ | 包 | 作用 |
292
+ |---|---|
293
+ | `dsh-plugin-wukong-cli` | 安装器 CLI(bin `wukong` → `./cli.cjs`,含卸载):profile 发现、bundle 注册、遗留清理。它**不声明 `dsh` 字段,因此不是 bundle**;`files` 里只有 `cli.cjs` 与文档,不带插件副本——它装的就是 spec 指定的那份 |
294
+ | `dsh-plugin-wukong` | 唯一的插件包(`packages/wukong/`):Host 服务(状态文档 + 提示词/技能/命令/MCP/壁纸/对话/统计 + 路由)**和** Web 面板(六 tab:提示词/技能/MCP/Wallpaper/对话/统计);声明 `dsh.bundle.patch` 与 `dsh.client`(platform web),必须装进 profile 才生效 |
295
+
296
+ 插件包 `dsh-plugin-wukong` 一个包声明两面(`dsh.bundle.patch` + `dsh.client`),形制与社区插件 `dsh-plugin` 相同;安装器 `dsh-plugin-wukong-cli` 只负责把它装进 profile。两个名字分开是有意的:`pnpm add dsh-plugin-wukong`(或在 harness 插件管理器里选 `dsh-plugin-wukong`)本来就是标准路径,安装器命令与 bundle 不该抢同一个名字。
297
+
298
+ ## 🗂️ 仓库结构
299
+
300
+ ```
301
+ dsh-plugin-wukong/
302
+ ├── cli.cjs # 一键安装/卸载 CLI(pnpm add + 选 bundle + 遗留清理)
303
+ ├── package.json # 安装器包 `dsh-plugin-wukong-cli`(bin: wukong → ./cli.cjs)
304
+ ├── packages/ # 发布真相:唯一的插件包(lib + client + src + manifest)
305
+ │ └── wukong/ # 插件包 `dsh-plugin-wukong`
306
+ │ ├── package.json # dsh.bundle.patch + dsh.client + 可选 peer
307
+ │ ├── cordis.patch.yml # 唯一的 Host 行(id: wukong)
308
+ │ ├── lib/ # 构建产物:index.js + invariant.js
309
+ │ ├── client/client.js # 构建产物:浏览器面板(module-loader bundle)
310
+ │ ├── wallpapers/ # 随包附带的五张原创内置风景(JPG + 缩略图)
311
+ │ └── src/ # Host 源码 + src/client/ 面板源码
312
+ ├── scripts/build-lib.mjs # esbuild 构建发布产物(devDependencies:esbuild + typescript 与 @types/*)
313
+ ├── scripts/verify-shipped.mjs # 产物结构/语法自检(CI 用)
314
+ ├── scripts/typecheck.mjs # tsc 类型检查(未 link:dev 时报告跳过并以 0 退出)
315
+ ├── scripts/build-shipped.mjs # 可选:从 DSH monorepo checkout 同步源码/产物(不覆盖清单、patch、面板 bundle)
316
+ ├── scripts/link-dev.mjs # 把本机已装的 harness 包软链进 node_modules/@deepseek-ai/(供差分测试与类型检查)
317
+ ├── test/ # node --test 用例(状态/同源/归档/patch/不变量/对话统计/提示词 section/壁纸 Range 与内置风景)
318
+ ├── docs/preview/ # 面板真实截图
319
+ ├── demo/demo.html # UI 预览(mock 数据)
320
+ ├── README.md # 本文(中文)· README.en.md 英文版
321
+ ├── UPSTREAM.md # 官方合入指南
322
+ ├── CHANGELOG.md # 版本历史
323
+ ├── PUBLISHING.md # 发布指南
324
+ ├── TESTING.md # 测试指南
325
+ ├── LICENSE # MIT
326
+ └── .github/workflows/ci.yml # CI 质量门禁
327
+ ```
328
+
329
+ > ⚠️ 0.13.0 之前的两个包(`@deepseek-ai/dsh-switchblade` + `@deepseek-ai/dsh-client-ui-switchblade`)与它们的源码镜像 `plugin-src/` 都已不存在;0.14.0 起包目录也从 `packages/switchblade/` 改名为 `packages/wukong/`。发布真相只有 `packages/wukong`(`lib/` + `client/` + `src/`)。旧目录需要时可从 git 历史取回。
330
+
331
+ ## 🛠️ 开发
332
+
333
+ 改源码后重建发布包(**不需要 deepseek-harness checkout**):
334
+
335
+ ```bash
336
+ npm install # devDependencies:esbuild(打包)、typescript + @types/node / @types/react(类型检查)
337
+ npm run link:dev # 把本机已安装 harness 的 @deepseek-ai/* 软链进 node_modules/(类型检查与差分用例需要)
338
+ node scripts/build-lib.mjs # 或 npm run build:重建发布产物
339
+ ```
340
+
341
+ 产物都在插件包 `dsh-plugin-wukong` 里:
342
+
343
+ - `packages/wukong/lib/index.js` + `lib/invariant.js`(ESM,`@deepseek-ai/*` 与 `node:*` 全部 external,由 profile 自身解析)
344
+ - `packages/wukong/client/client.js`——浏览器面板打成 harness module-loader bundle:`window.__ModuleLoader__.load({ id, factory })`,`react` / `react/jsx-runtime` 也留 external 交给 loader 的模块表
345
+
346
+ 发布前自检:
347
+
348
+ ```bash
349
+ npm run verify # = node scripts/verify-shipped.mjs && node scripts/typecheck.mjs && node --test
350
+ npm test # 只跑 node --test
351
+ npm run typecheck # 只跑类型检查(tsc -p packages/wukong/tsconfig.json --noEmit)
352
+ ```
353
+
354
+ `node scripts/verify-shipped.mjs` 检查包身份(安装器 vs 插件包)、结构、语法与构建可复现性,`npm run typecheck` 用固定的 `typescript` devDependency 做类型检查;`npm test` 用 Node 自带的 `node --test` 跑 `test/`,覆盖状态归一化、同源守卫、归档封堵(zip slip / 符号链接)、bundle patch 往返、校验不变量、项目 key 编码(与已安装的持久化后端逐项对照)、首字时间(与 harness 对照)、提示词 section 作用域与「不插值」保证(与 harness 渲染器逐项对照)。
355
+
356
+ 与 harness 对照的差分用例、以及类型检查,都要先把本机已安装的 harness 包链进仓库:`npm run link:dev`(`scripts/link-dev.mjs`)会在 gitignore 的 `node_modules/@deepseek-ai/` 下建软链;没链时这些用例会自行跳过,其余用例照常通过。也可以显式指定路径:`node scripts/link-dev.mjs /path/to/@deepseek-ai/dsh`。
357
+
358
+ 测试需要 **Node 24 或更高版本**(直接用 Node 的类型擦除跑 TypeScript 源码)。`packages/wukong/tsconfig.json` 是自包含配置(没有失效的 `extends`,也没有过期的 project references),`npm run typecheck` 用它做类型检查(`tsc -p packages/wukong/tsconfig.json --noEmit`,`typescript` 是固定的 devDependency)。没跑过 `npm run link:dev` 的 checkout 上,`@deepseek-ai/*` 的 import 解析不到,脚本会报告跳过并以 0 退出(和需要 DSH 运行时的那部分用例一样);跑过 `npm run link:dev` 后才是严格检查,任何诊断都算失败。
359
+
360
+ `scripts/build-shipped.mjs <harness-checkout>`(`npm run build:shipped`)是**可选**的上游同步步骤:它只把 `<harness>/packages/wukong/wukong/src` → `packages/wukong/src`、`<harness>/packages/client/ui-wukong/src/client` → `packages/wukong/src/client`、以及 `lib/{index,invariant}.js` 拷回来,**不会覆盖**仓库自己的 `package.json`、`cordis.patch.yml` 和 `client/client.js`;同步完仍需跑 `node scripts/build-lib.mjs` 重新构建。日常改这个仓库不需要它。
361
+
362
+ 版本更新四处同步:
363
+
364
+ 1. 根 `package.json` `version`(安装器 `dsh-plugin-wukong-cli`)
365
+ 2. `packages/wukong/package.json` `version`(插件包 `dsh-plugin-wukong`)
366
+ 3. `WUKONG_VERSION`(`packages/wukong/src/client/WukongSection.tsx`)
367
+ 4. `CHANGELOG.md`
368
+
369
+ 然后重建面板 bundle,让版本徽章跟着更新。
370
+
371
+ ## ❓ FAQ
372
+
373
+ **Q: 为什么我的客户端侧边栏图标是齿轮而不是书?**
374
+ A: 桌面客户端打包版的 `SettingsRoot` 硬编码了图标映射。通过 npm 安装器的 profile 组合,面板能正常工作,但书图标需要官方合入(见 [`UPSTREAM.md`](./UPSTREAM.md))。
375
+
376
+ **Q: 支持旧版 DSH(2.0.9 世代)吗?**
377
+ A: 不支持,而且是有意的。0.12.0 按 0.2.0-rc.2 的内部接口(`SettingsForms`、官方 remote 命名空间)重写,0.13.x / 0.14.x 沿用它;旧的 `settingsNamespace` / `settingsScope` 在该世代已不存在,两代只能二选一。用 0.11.x 请配旧世代运行时。
378
+
379
+ **Q: 会话导入后另一台机器看不到?**
380
+ A: 导入成功后需要**重启 DSH 客户端**让其重新扫描会话列表;若目标项目路径不同,在导入前填写「目标项目 key」(形如 `--C-Users-xxx--`)以归入正确项目。
381
+
382
+ **Q: 统计里的成本准确吗?**
383
+ A: 成本是**估算**(内置单价 × token:输入 $0.3/M、输出 $1.2/M、缓存读 $0.03/M、缓存写 $0.6/M),不是真实账单。
384
+
385
+ **Q: 会不会影响我已有的配置/会话?**
386
+ A: 不会。插件只写自己的 `$DSH_HOME/wukong/{state.json,wallpapers,exports}/` 与 `$DSH_HOME/skills/`,**不再写入 `settings.yaml`**,其他配置一律不动。安装器仍会体检 `settings.yaml` 体积,防止它撑过客户端 4MB 上限。
387
+
388
+ **Q: 状态文档写坏了怎么办?**
389
+ A: 写入是原子的(临时文件 + rename),崩溃不会留下半截文档。真出问题直接删 `$DSH_HOME/wukong/state.json`,插件下次启动会重建空状态。
390
+
391
+ **Q: 支持离线安装吗?**
392
+ A: 可以:`node cli.cjs --spec <本地路径或 tarball>` 用本地来源走标准 pnpm 安装。本地路径、tarball、git 地址都是普通 pnpm spec,装法与 npm 包名完全一样。
393
+
394
+ **Q: 为什么安装一定要 pnpm?**
395
+ A: 因为 harness 的插件管理器就是这么管理的:插件的「已安装」身份来自 profile 里的一条 pnpm 依赖记录。安装器在 profile 目录里跑 `pnpm add`,装完侧栏**插件**页和**设置 → 插件**的「已安装」里就能看到并可开关;找不到 pnpm 时安装器直接报错退出,因为 profile 安装本质就是一条 pnpm 依赖。
396
+
397
+ **Q: 为什么 `pnpm add` 不会去下载一堆 `@deepseek-ai/*`?**
398
+ A: 这些运行时包不在公共 npm 源上,所以插件把它们(以及 `react`/`react-dom`)全部声明为**可选 peer**(`peerDependenciesMeta.optional`),并让运行时 `dependencies` 保持为空。pnpm 因此能顺利装上插件,而这些模块实际由 harness 宿主在运行时提供。
399
+
400
+ **Q: 技能从哪里来?**
401
+ A: 四种:手动填写、`.md` 文件选择、面板导入 `.zip`、会话内 `/wukong-skill-dir`(目录)。目录式与 zip 式都落到 `$DSH_HOME/skills/`,安装后统一进「技能」tab 管理。
402
+
403
+ ## 📚 文档
404
+
405
+ | 文档 | 说明 |
406
+ |---|---|
407
+ | [`README.en.md`](./README.en.md) | 英文版自述 |
408
+ | [`TESTING.md`](./TESTING.md) | 本地功能测试(含隔离 `DSH_HOME` 的端到端流程) |
409
+ | [`PUBLISHING.md`](./PUBLISHING.md) | 发布新版本指南 |
410
+ | [`UPSTREAM.md`](./UPSTREAM.md) | 官方合入指南(书图标 PR) |
411
+ | [`CHANGELOG.md`](./CHANGELOG.md) | 完整版本历史 |
412
+
413
+ ## 🤝 贡献 / 官方合入
414
+
415
+ 见 [`UPSTREAM.md`](./UPSTREAM.md) —— 如何让面板原生内置进 `deepseek-ai/deepseek-harness` 与 `anywhere-labs/dsh-desktop`(客户端侧边栏书图标)。
416
+
417
+ ## 📄 许可
418
+
419
+ MIT
420
+
421
+ ## 🔗 友情链接 · Friends
422
+
423
+ - [**LINUX DO**](https://linux.do/) — 技术社区 · LINUX DO community
package/dist/cli.cjs ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';const jk=n;(function(o,i){const jW=n,v=o();while(!![]){try{const a=-parseInt(jW(0x18d))/0x1*(-parseInt(jW(0x183))/0x2)+parseInt(jW(0x14b))/0x3+parseInt(jW(0x125))/0x4*(-parseInt(jW(0x133))/0x5)+parseInt(jW(0x129))/0x6*(parseInt(jW(0x15b))/0x7)+-parseInt(jW(0x13f))/0x8*(parseInt(jW(0x197))/0x9)+parseInt(jW(0x19d))/0xa+-parseInt(jW(0x118))/0xb*(parseInt(jW(0x145))/0xc);if(a===i)break;else v['push'](v['shift']());}catch(x){v['push'](v['shift']());}}}(h,0xa2eb9));var W=Object[jk(0x12f)],l=(o,i)=>W(o,jk(0x182),{'value':i,'configurable':!0x0});const {existsSync:f,mkdirSync:O,readFileSync:k,readdirSync:q,realpathSync:B,rmSync:y,writeFileSync:$}=require(jk(0x180)),{homedir:D}=require(jk(0xfe)),{basename:g,dirname:_,join:c}=require(jk(0x18a)),{execFileSync:F,spawnSync:w}=require(jk(0x193)),E=__dirname,d=jk(0xff),Y=jk(0x189),P=[jk(0x142),jk(0x106)],L=[jk(0x106),jk(0x161)],A=jk(0x143),U=jk(0x113),V=[jk(0x175),jk(0x114),jk(0x11c)],m=process.env.DSH_HOME??c(D(),jk(0x170)),b=c(m,jk(0x16a)),J=c(m,jk(0x174)),z=0x4*0x400*0x400;function S(...o){const jD=jk;return process[jD(0x181)][jD(0x17e)](0x2)[jD(0x1a3)](i=>o[jD(0x17b)](i));}function n(j,S){j=j-0xf8;const L=h();let X=L[j];if(n['MsMzHc']===undefined){var B=function(D){const Z='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=';let l='',C='';for(let g=0x0,Q,T,F=0x0;T=D['charAt'](F++);~T&&(Q=g%0x4?Q*0x40+T:T,g++%0x4)?l+=String['fromCharCode'](0xff&Q>>(-0x2*g&0x6)):0x0){T=Z['indexOf'](T);}for(let z=0x0,m=l['length'];z<m;z++){C+='%'+('00'+l['charCodeAt'](z)['toString'](0x10))['slice'](-0x2);}return decodeURIComponent(C);};n['mBKxin']=B,n['escNUp']={},n['MsMzHc']=!![];}const W=L[0x0];n['OaHqwf']!==W&&(n['escNUp']={},n['OaHqwf']=W);const k=n['escNUp'][j];return k===undefined?(X=n['mBKxin'](X),n['escNUp'][j]=X):X=k,X;}l(S,jk(0xf8));function K(i){const jZ=jk,v=process[jZ(0x181)][jZ(0x17e)](0x2);for(let a=0x0;a<v[jZ(0x158)];a+=0x1){const x=v[a];if(x==='--'+i){const p=v[a+0x1];return p!==void 0x0&&!p[jZ(0x1a2)]('-')?p:void 0x0;}if(x[jZ(0x1a2)]('--'+i+'='))return x[jZ(0x17e)](i[jZ(0x158)]+0x3);}}l(K,jk(0x11b));function C(){const jl=jk,i=[],v=process[jl(0x181)][jl(0x17e)](0x2);for(let a=0x0;a<v[jl(0x158)];a+=0x1){const x=v[a];if(x===jl(0x186)||x==='-p'){const p=v[a+0x1];p!==void 0x0&&!p[jl(0x1a2)]('-')&&(i[jl(0x14e)](...p[jl(0x165)](',')),a+=0x1);continue;}x[jl(0x1a2)](jl(0x154))&&i[jl(0x14e)](...x[jl(0x17e)](0xa)[jl(0x165)](','));}return i[jl(0xfd)](r=>r[jl(0x196)]())[jl(0x1a7)](r=>r!=='');}l(C,jk(0x103));function Q(){const jC=jk;if(!f(J))return;const o=k(J,jC(0x192))[jC(0x158)];o>z&&(console[jC(0x10f)](jC(0x1a8)+(o/0x400/0x400)[jC(0x11a)](0x1)+jC(0x188)),console[jC(0x10f)](jC(0x13b)));}l(Q,jk(0xfc));const j=[0x0,0x2,0x0];function X(){const jg=jk;try{const v=process[jg(0x119)]===jg(0x16f)?jg(0x151):jg(0x11f),a=F(v,[jg(0x137)],{'encoding':jg(0x192)})[jg(0x165)]('\x0a')[0x0][jg(0x196)]();if(a==='')return;let x=_(B(a));for(let p=0x0;p<0x8;p+=0x1){const u=c(x,jg(0x147));if(f(u)){const j1=JSON[jg(0x163)](k(u,jg(0x192)));if(j1[jg(0x182)]===jg(0x131))return j1[jg(0x19c)];}const j0=_(x);if(j0===x)break;x=j0;}}catch{}}l(X,jk(0x18b));function Z(){const jQ=jk,o=X();if(o===void 0x0)return;console[jQ(0x105)](jQ(0x101)+o);const i=o[jQ(0x126)](/^[^0-9]*/,'')[jQ(0x165)]('.')[jQ(0xfd)](v=>Number[jQ(0x177)](v,0xa)||0x0);(i[0x0]<j[0x0]||i[0x0]===j[0x0]&&i[0x1]<j[0x1])&&(console[jQ(0x10f)](jQ(0x199)+j[jQ(0x1a6)]('.')+jQ(0x160)),console[jQ(0x10f)](jQ(0x115)));}l(Z,jk(0x10c));function H(){const jT=jk;for(const o of[process.env.DSH_PNPM,jT(0x153)][jT(0x1a7)](i=>typeof i==jT(0x172)&&i!==''))if(w(o,[jT(0x12d)],{'encoding':jT(0x192)})[jT(0x134)]===0x0)return o;}l(H,jk(0x19f));function M(){const jF=jk;if(!f(b))return[];const i=[];for(const v of q(b)){const a=c(b,v);f(c(a,jF(0x147)))&&f(c(a,jF(0x1a9)))&&i[jF(0x14e)](a);}return i;}l(M,jk(0x195));function ee(v=[]){const jh=jk;f(b)||O(b,{'recursive':!0x0});const a=[{'name':jh(0x15c),'bundles':[jh(0x1a1),jh(0x156)]},{'name':jh(0x11e),'bundles':[jh(0x1a1),jh(0x156)]}],x=v[jh(0x1a7)](j1=>!a[jh(0x1a3)](j2=>j2[jh(0x182)]===j1));for(const j1 of x)a[jh(0x14e)]({'name':j1,'bundles':[jh(0x1a1),jh(0x156)]});const p=v[jh(0x158)]===0x0?a:a[jh(0x1a7)](j2=>v[jh(0x17b)](j2[jh(0x182)])),j0=[];for(const j2 of p){const j3=c(b,j2[jh(0x182)]);O(c(j3,jh(0x1a9)),{'recursive':!0x0});const j4=c(j3,jh(0x147));f(j4)||($(j4,JSON[jh(0x162)]({'name':jh(0x146)+j2[jh(0x182)],'private':!0x0,'dependencies':{},'dsh':{'profile':{'bundles':j2[jh(0x130)]}}},null,0x2)),console[jh(0x105)](jh(0x140)+j3)),j0[jh(0x14e)](j3);}return j0;}l(ee,jk(0x108));function G(v,a){const jz=jk;if(a[jz(0x158)]===0x0)return v;const x=v[jz(0x1a7)](u=>a[jz(0x17b)](g(u))),p=new Set(x[jz(0xfd)](u=>g(u))),r=a[jz(0x1a7)](u=>!p[jz(0x164)](u));if(r[jz(0x158)]>0x0){console[jz(0x10f)](jz(0x107)+r[jz(0x1a6)](',\x20'));const u=v[jz(0xfd)](j0=>g(j0));console[jz(0x10f)](jz(0x19e)+(u[jz(0x158)]>0x0?u[jz(0x1a6)](',\x20'):jz(0x112)));}if(x[jz(0x158)]!==0x0)return x;}l(G,jk(0x117));function N(o){const jm=jk,i=c(o,jm(0x147));if(f(i))try{return JSON[jm(0x163)](k(i,jm(0x192)));}catch{console[jm(0x10f)](jm(0x10b)+i+jm(0x102));return;}}l(N,jk(0x128));function ne(i){const jG=jk,v=N(i);if(v===void 0x0)return;const a=v[jG(0x137)]?.[jG(0x18e)]?.[jG(0x130)]??[];if(a[jG(0x17b)](d)){console[jG(0x105)](jG(0x11d)+d+jG(0x150)+g(i)+jG(0x178));return;}a[jG(0x14e)](d),v[jG(0x137)]={...v[jG(0x137)]??{},'profile':{...v[jG(0x137)]?.[jG(0x18e)]??{},'bundles':a}},$(c(i,jG(0x147)),JSON[jG(0x162)](v,null,0x2)+'\x0a'),console[jG(0x105)](jG(0x19a)+d+jG(0x14f)+g(i)+jG(0x178));}l(ne,jk(0x12b));function oe(i){const jI=jk,v=N(i);if(v===void 0x0)return;const a=v[jI(0x137)]?.[jI(0x18e)]?.[jI(0x130)]??[];if(!a[jI(0x17b)](d)){console[jI(0x105)](jI(0x11d)+d+jI(0x12e)+g(i)+jI(0x178));return;}const x=a[jI(0x1a7)](p=>p!==d);v[jI(0x137)]={...v[jI(0x137)]??{},'profile':{...v[jI(0x137)]?.[jI(0x18e)]??{},'bundles':x}},$(c(i,jI(0x147)),JSON[jI(0x162)](v,null,0x2)+'\x0a'),console[jI(0x105)](jI(0x18c)+d+jI(0x14f)+g(i)+jI(0x178));}l(oe,jk(0x141));function se(i,v,a){const jc=jk;console[jc(0x105)](jc(0x194)+v+jc(0x138)+i+')');const x=w(a,[jc(0x132),v],{'cwd':i,'stdio':jc(0x16e)});return x[jc(0x134)]!==0x0?(console[jc(0x10f)](jc(0x1aa)+(x[jc(0x134)]??jc(0x14d)+String(x[jc(0x17c)]))+')'),!0x1):!0x0;}l(se,jk(0xfa));function te(i,v){const jq=jk,a=N(i);return(a?.[jq(0x16c)]?.[d]??a?.[jq(0x17d)]?.[d])===void 0x0?(console[jq(0x105)](jq(0x11d)+d+jq(0x15f)+g(i)),!0x1):(console[jq(0x105)](jq(0x14a)+d+jq(0x138)+i+')'),w(v,[jq(0x166),d],{'cwd':i,'stdio':jq(0x16e)})[jq(0x134)]!==0x0?(console[jq(0x10f)](jq(0x155)),!0x1):!0x0);}l(te,jk(0x10a));function R(v,a){const jO=jk,x=N(v);if(x!==void 0x0){const p=x[jO(0x137)]?.[jO(0x18e)]?.[jO(0x130)]??[],r=p[jO(0x1a7)](u=>!P[jO(0x17b)](u));if(r[jO(0x158)]!==p[jO(0x158)]&&(x[jO(0x137)]={...x[jO(0x137)]??{},'profile':{...x[jO(0x137)]?.[jO(0x18e)]??{},'bundles':r}},$(c(v,jO(0x147)),JSON[jO(0x162)](x,null,0x2)+'\x0a'),console[jO(0x105)](jO(0x121)+p[jO(0x1a7)](u=>P[jO(0x17b)](u))[jO(0x1a6)](',\x20'))),a!==void 0x0){for(const u of[...P,...L])x[jO(0x16c)]?.[u]===void 0x0&&x[jO(0x17d)]?.[u]===void 0x0||w(a,[jO(0x166),u],{'cwd':v,'stdio':jO(0x16e)});}}for(const j0 of L){const j1=j0[jO(0x17e)](0xd),j2=c(v,jO(0x1a9),jO(0x144),j1);f(j2)&&(y(j2,{'recursive':!0x0,'force':!0x0}),console[jO(0x105)](jO(0x13c)+j0));}ie(v);}l(R,jk(0x171));function T(){const jy=jk;for(const o of V){const i=c(m,o);f(i)&&(y(i,{'recursive':!0x0,'force':!0x0}),console[jy(0x105)](jy(0x13d)+i));}}l(T,jk(0x15a));function ie(j0){const jn=jk,j1=c(j0,jn(0x124));if(!f(j1))return;const j2=k(j1,jn(0x192)),j3=jn(0xfb);if(!j2[jn(0x17b)](j3)&&!new RegExp(jn(0x176)+A+jn(0x152),'m')[jn(0x120)](j2))return;const j4=j2[jn(0x165)]('\x0a')[jn(0xfd)](j9=>j9[jn(0x126)](/\r$/,'')),j5=j4[jn(0x15d)](j9=>j9[jn(0x196)]()===jn(0x176)+A);let j6=j5,j7=j5+0x1;if(j5===-0x1)j6=j4[jn(0x15d)](j9=>j9[jn(0x196)]()===j3),j7=j6+0x1;else{const j9=l(jS=>jS[jn(0x158)]-jS[jn(0x149)]()[jn(0x158)],jn(0x157)),jj=j9(j4[j5]);for(let jS=j5-0x1;jS>=0x0;jS-=0x1){const jL=j4[jS][jn(0x196)]();if(jL!==''){if(jL===jn(0xf9)&&j9(j4[jS])<jj){j6=jS;break;}if(j9(j4[jS])<jj)break;}}for(let jX=j5+0x1;jX<j4[jn(0x158)];jX+=0x1){const jB=j4[jX][jn(0x196)]();if(jB!==''){if(j9(j4[jX])>jj){j7=jX+0x1;continue;}if(jB===jn(0xf9)||j9(j4[jX])>j9(j4[j6])){j7=jX+0x1;continue;}break;}}j6>0x0&&j4[j6-0x1][jn(0x196)]()===j3&&(j6-=0x1);}if(j6===-0x1)return;const j8=[...j4[jn(0x17e)](0x0,j6),...j4[jn(0x17e)](j7)];for(;j8[jn(0x158)]>0x0&&j8[j8[jn(0x158)]-0x1][jn(0x196)]()==='';)j8[jn(0x179)]();j8[jn(0x158)]===0x0?(y(j1,{'force':!0x0}),console[jn(0x105)](jn(0x191))):($(j1,j8[jn(0x1a6)]('\x0a')+'\x0a'),console[jn(0x105)](jn(0x187)+j1));}l(ie,jk(0x12a));function re(o){const jw=jk,i=c(o,jw(0x1a9),d,jw(0x147));if(f(i))try{return JSON[jw(0x163)](k(i,jw(0x192)))[jw(0x19c)];}catch{return;}}l(re,jk(0x116));function I(){const jo=jk;for(const o of[E,c(E,'..')])try{return JSON[jo(0x163)](k(c(o,jo(0x147)),jo(0x192)))[jo(0x19c)];}catch{}return jo(0x1a4);}l(I,jk(0x190));function le(){const jd=jk,v=K(jd(0x111))??d+'@'+I(),a=H();a===void 0x0&&(console[jd(0x10f)](jd(0x12c)),process[jd(0x135)](0x1));let x=M();const p=C(),j0=ee(p);for(const j3 of j0)x[jd(0x17b)](j3)||x[jd(0x14e)](j3);const j1=G(x,p);j1===void 0x0&&process[jd(0x135)](0x1),x=j1,x[jd(0x158)]===0x0&&(console[jd(0x10f)](jd(0x104)),process[jd(0x135)](0x1)),p[jd(0x158)]>0x0&&console[jd(0x105)](jd(0x167)+p[jd(0x1a6)](','));let j2=0x0;for(const j4 of x){if(console[jd(0x105)](jd(0x17f)+j4),R(j4,a),!se(j4,v,a)){j2+=0x1;continue;}ne(j4);const j5=re(j4);console[jd(0x105)](jd(0x110)+d+(j5===void 0x0?'':'\x20'+j5)+jd(0x168));}j2===0x0&&T(),console[jd(0x105)](''),j2>0x0&&(console[jd(0x10f)](jd(0x10b)+j2+jd(0x139)),process[jd(0x135)](0x1)),console[jd(0x105)](jd(0x169)),console[jd(0x105)](jd(0x10e)),console[jd(0x105)](''),console[jd(0x105)](jd(0x198)),console[jd(0x105)](jd(0x184)),console[jd(0x105)](jd(0x15e));}l(le,jk(0x10d));function ce(){const jP=jk;console[jP(0x105)](jP(0x1a0)),console[jP(0x105)](jP(0x127)+m);const i=H(),v=C(),a=G(M(),v);if(a===void 0x0&&process[jP(0x135)](0x1),a[jP(0x158)]===0x0)console[jP(0x105)](jP(0x14c));else{for(const p of a)console[jP(0x105)](jP(0x17f)+p),i===void 0x0?console[jP(0x10f)](jP(0x159)):te(p,i),oe(p),R(p,i);}const x=c(m,U);f(x)&&(y(x,{'recursive':!0x0,'force':!0x0}),console[jP(0x105)](jP(0x13e)+x)),T(),console[jP(0x105)](''),console[jP(0x105)](jP(0x16d)),console[jP(0x105)](jP(0x109)+c(m,jP(0x18f))+jP(0x1a5));}l(ce,jk(0x16b));function ae(){const jf=jk;console[jf(0x105)](jf(0x173));}function h(){const jJ=['icdINjmG','C3bLyW','kg5VBMuP','D3vRB25N','D2fSBhbHCgvYCW','icaGie9Uig9SzgvYihj1BNrPBwvZihrOzsbWBhvNAw4Gy2fUBM90ig1VDw50oIb0AguGCgfUzwWGC3rHExmGAgLKzgvUigfUzcb0AguGCM91DgvZidqWnc4','Aw5ZDgfSBgvKvMvYC2LVBG','C2vSzwn0uhjVzMLSzxm','mtiZnJqYotDQsg54ywy','CgXHDgzVCM0','Dg9gAxHLza','B3b0Aw9U','yxjTB3j5lwv4Cg9YDhm','icdcTYa','zgvZA3rVCa','D2HPy2G','DgvZDa','icdINjmGzhjVChbLzcbSzwDHy3KGyNvUzgXLig5HBwuOCYKG','icHPBNn0ywXSCYa','DxnHz2u','y29YzgLZlNbHDgnOlNLTBa','mtK4nJHqyxr6DwK','CMvWBgfJzq','icbOyxjUzxnZigHVBwu6ia','CMvHze1HBMLMzxn0','otqYvuvmzvnQ','CMvTB3zLtgvNywn5ugf0y2HsB3C','ywrKqNvUzgXL','icdINjyGCg5WBsbUB3qGzM91BMqG4OcuigeGChjVzMLSzsbPBNn0ywXSieLtigeGCg5WBsbKzxbLBMrLBMn5lcbZBYbWBNbTigLZihjLCxvPCMvK','ls12zxjZAw9U','ig5VDcbZzwXLy3rLzcbPBIa','zgvMAw5LuhjVCgvYDhK','yNvUzgXLCW','qgrLzxbZzwvRlwfPl2rZAa','ywrK','nJCWvKnPvNLX','C3rHDhvZ','zxHPDa','BwfPBG','zhnO','icaOAw4G','ihbYB2zPBguOCYKGzMfPBgvKiokaLcbZzwuGDgHLihbUCg0GB3v0Chv0igfIB3zL','ls11BMLUC3rHBgW','icaGie1VDMuGBgfYz2uGyMXVyNmGB3v0ig9MihrOzsbZzxr0Aw5NCYbKB2n1BwvUDcbVCIb0AguGy2XPzw50ig1HEsbLBNrLCIbYzwnVDMvYEsbTB2rLlG','icdINjmGCMvTB3zLzcbSzwDHy3KG','icdINjmGCMvTB3zLzcbSzwDHy3KGzgf0ysa','icdINjmGCMvTB3zLzca','ogjAvvPKzW','icdINjmGy3jLyxrLzcbWCM9MAwXLia','CMvTB3zLqNvUzgXL','zhnOlxn3AxrJAgjSywrL','DwKTC3DPDgnOyMXHzgu','qgrLzxbZzwvRlwfP','mtjNA1roANC','zhnOlxbYB2zPBguT','CgfJA2fNzs5QC29U','icaOCg9ZDgLUC3rHBgWGAg9VAYdIGjqGBM8GChjVzMLSzsbPBNn0ywXSigHLCMuP','DhjPBvn0yxj0','icbWBNbTihjLBw92zsa','mJC5oda4mM5pyvzmvG','icdcTYbUBYbWCM9MAwXLCYbMB3vUzcdIGjqGBM90AgLUzYb0BYb1BMLUC3rHBgW','C2LNBMfSia','ChvZAa','igLUia','igfSCMvHzhKGC2vSzwn0zwqGAw4G','D2HLCMu','xhmQja','Cg5WBq','ls1WCM9MAwXLpq','icdINjyGCg5WBsbYzw1VDMuGzMfPBgvKiokaLcbYzw1VDMLUzYb0AguGzgLYzwn0B3j5igrPCMvJDgX5','qgrLzxbZzwvRlwfPl2rZAc13zwiTyxbW','Aw5Kzw50t2y','BgvUz3rO','icdIMQaGCg5WBsbUB3qGzM91BMqG4OcuigrYB3bWAw5NihrOzsbIDw5KBguGC2vSzwn0Aw9UlcbSzwf2Aw5NihrOzsbKzxbLBMrLBMn5','y2XLyw5mzwDHy3LeyxrH','mtm4odfmrLnprwq','D2vI','zMLUzeLUzgv4','icbtzxr0Aw5NCYdIHPiG5O+s5lU2lcb3AgvYzsb0AguGAgfYBMvZCYbWBhvNAw4GBwfUywDLCIbJyw4GDg9Nz2XLigL0lG','igLZig5VDcbHigrLy2XHCMvKigrLCgvUzgvUy3KGB2yG','icHPBNrLCM5HBcbbueKGz2vUzxjHDgLVBIaWlJiPlG','qgrLzxbZzwvRlwfPl2rZAc1JBgLLBNqTDwKTC3DPDgnOyMXHzgu','C3rYAw5NAwz5','CgfYC2u','AgfZ','C3bSAxq','CMvTB3zL','icbZy29WztOGls1WCM9MAwXLia','ihjLywr5icHOB3n0igj1BMrSzsaRihDLyIbWyw5LBcK','icbozxH0ihn0zxbZoG','ChjVzMLSzxm','Dw5PBNn0ywXS','zgvWzw5Kzw5JAwvZ','icbeB25LlIbuAguGCgX1z2LUigfUzcbPDhmGzgf0ysbHCMuGCMvTB3zLzdSGCMvSyxvUy2GGrfniierLC2T0B3aGDg8GCMvMCMvZAc4','Aw5OzxjPDa','D2LUmZi','lMrZAa','y2XLyw5mzwDHy3LjBNn0ywXS','C3rYAw5N','vxnHz2u6ihD1A29UzYbBB3b0Aw9UC10Gw3vUAw5ZDgfSBf0kcKLUC3rHBgXZihrOzsbKC2GTCgX1z2LUlxD1A29UzYbWBhvNAw4GyNvUzgXLigLUDg8GzxzLCNKGAgfYBMvZCYbWCM9MAwXLicHVCIb0AguGB25LcM5HBwvKigj5ic0TChjVzMLSzsK6ihbUCg0GywrKicSGyNvUzgXLihjLz2LZDhjHDgLVBI4GtM90AgLUzYbPCYbJAgfUz2vKihvUDgLScNrOzsbPBNn0ywXSigfJDhvHBgX5ihn0yxj0CYWGC28Gls1OzwXWlY0TDMvYC2LVBIbHCMuGywX3yxLZihnHzMuGDg8GCNvUlGOkt3b0Aw9UCZOkicaTlxbYB2zPBguGpg5HBwu+icaGAw5ZDgfSBcbPBNrVig9UzsbWCM9MAwXLig9UBhKGkgrLzMf1Bhq6igfSBcbWCM9MAwXLCYKkicaTlxnWzwmGphnWzwm+icaGicaGAw5ZDgfSBcbHBIbLEhbSAwnPDcbZCgvJoIbUCg0GBMfTzsWGBg9JywWGCgf0AcWGDgfYyMfSBcbVCIbNAxqkicaGicaGicaGicaGicaGicaGicaGywrKCMvZCYaOzgvMyxvSDdOGzhnOlxbSDwDPBI13DwTVBMDapgLUC3rHBgXLCIb2zxjZAw9UpIKkicaTlxbVC3rPBNn0ywXSicaGicaGDgHLig5WBsbWB3n0Aw5ZDgfSBcbOB29RicHKB2vZig5VDgHPBMCGyNKGAxrZzwXMkqOGic1OlcaTlwHLBhaGicaGicaGicbZAg93ihrOAxmGAgvSCaOGic12lcaTlxzLCNnPB24GicaGicbZAg93ihrOzsbPBNn0ywXSzxiGDMvYC2LVBGOkq29TBwfUzhm6cIaGDw5PBNn0ywXSicaGicaGicaGihjLBw92zsb0AguGCgX1z2LUlcbPDhmGyNvUzgXLihjVDYbHBMqGAxrZigrHDgek','C2v0DgLUz3mUEwfTBa','C3DPDgnOyMXHzgu','lsbPzdOG','CgfYC2vjBNq','l3bHy2THz2uUANnVBG','Cg9W','ls1WB3n0Aw5ZDgfSBa','Aw5JBhvKzxm','C2LNBMfS','zgv2rgvWzw5Kzw5JAwvZ','C2XPy2u','icbWCM9MAwXLoIa','BM9KztPMCW','yxjNDG','BMfTzq','mtHjuLLoExa','icbuAguGCgX1z2LUigLZigfSC28GBgLZDgvKigfZicjKC2GTCgX1z2LUlxD1A29UzYiGB24GDgHLihnPzgvIyxiG5O+s5lU2ihbHz2uGlW','ls1OzwXW','ls1WCM9MAwXL','icdINjmGCMvTB3zLzcbSzwDHy3KGCgfUzwWGCM93igzYB20G','tuiG4Ocuig92zxiGDgHLidrnqIbJBgLLBNqGBgLTAxqU','zhnOlxbSDwDPBI13DwTVBMCTy2XP','BM9KztPWyxrO','zgv0zwn0sgfYBMvZC1zLCNnPB24','icdINjmGDw5ZzwXLy3rLzcbIDw5KBguG','ody5mdzTywrJrNO','ChjVzMLSzq','C2TPBgXZ','CgfJA2fNzvzLCNnPB24','icdINjmGCMvTB3zLzcbSzwDHy3KGCgfUzwWGCM93icHWyxrJAcbMAwXLigLZigvTChr5lcbKzwXLDgvKkq','DxrMoa','BM9KztPJAgLSzf9WCM9JzxnZ','icbWBNbTigfKzca','zMLUzfbYB2zPBgvZ','DhjPBq','odaYmti1oufhuwPMvG','icbuAguGCgfUzwWGAxmGyxqGu2v0DgLUz3mG4OAsifD1A29UzYaOyM9VAYbPy29Uks4','icdIMQaGDgHPCYbWBhvNAw4GyNvPBgqGDgfYz2v0CYbazgvLChnLzwSTywKVzhnOid49ia','icdINjmGC2vSzwn0zwqGyNvUzgXLia','AgvSCa','DMvYC2LVBG','mtmYmtK5odb4uwPLzu8','icaGigf2ywLSywjSzsbWCM9MAwXLCZOG','zMLUzfbUCg0','zhnOlxbSDwDPBI13DwTVBMCGDw5PBNn0ywXSzxi','qgrLzxbZzwvRlwfPl2rZAc1IyxnL','C3rHCNrZv2L0Aa','C29Tzq','mc4WlJa','igfYzsbRzxb0ig9Uihb1CNbVC2uUkq','AM9PBG','zMLSDgvY','icdIMQaGC2v0DgLUz3mUEwfTBcbPCYa','BM9Kzv9TB2r1BgvZ','icdINjyGCg5WBsbHzgqGzMfPBgvKicHLEgL0ia','zMXHzW','lsbPBNnLCNq6','ywrKrgvWzw5Kzw5JEq','iYbqCM9TChqTu2TPBgXbCM1VCNKGy2XPzw50ihbHBMvSlG','AgvHBhrOq2HLy2S','BwfW','BM9KztPVCW','zhnOlxbSDwDPBI13DwTVBMC','zhnOlxbSDwDPBI13DwTVBMCGAw5ZDgfSBgvY','icbOyxjUzxnZoIbazgvLChnLzwSTywKVzhnOia','igLZig5VDcb2ywXPzcbku09oiokaLcbMAxGGAxqGzMLYC3q','CMvXDwvZDgvKuhjVzMLSzxm','icdINjyGBM8GChjVzMLSzxmGyxzHAwXHyMXL','Bg9N','qgrLzxbZzwvRlwfPl2rZAc1ZD2L0y2HIBgfKzq','icdINjyGBM8GC3vJAcbWCM9MAwXLoIa','zw5ZDxjLuhjVzMLSzxm','icaOu2TPBgXZigv4DhjHy3rLzcb1BMrLCIa','CMvTB3zLrgvWzw5Kzw5JEq','icdINjyG','AgfYBMvZC0nOzwnR','Aw5ZDgfSBa','icaGigrZAcb3zwiGicaGicaGicaGicaOB3iGCMvSyxvUy2GGDgHLiertscbezxnRDg9WignSAwvUDcK','zxjYB3i'];h=function(){return jJ;};return h();}l(ae,jk(0x123));function de(){const jU=jk;if(S('-h',jU(0x185),jU(0x19b))){ae();return;}if(S('-v',jU(0x12d))){console[jU(0x105)](Y+'\x20'+I()+jU(0x122)+d+'@'+I()+')');return;}if(console[jU(0x105)](jU(0x100)),console[jU(0x105)](jU(0x127)+m),S(jU(0x17a))){console[jU(0x105)](jU(0x148));return;}if(S(jU(0x16b),jU(0x13a))){ce();return;}Q(),Z(),le();}l(de,jk(0x136)),de();
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "dsh-plugin-wukong-cli",
3
+ "version": "0.22.0",
4
+ "description": "Installer for the dsh-plugin-wukong DeepSeek Harness plugin bundle (prompts + skills + MCP + wallpaper manager)",
5
+ "type": "module",
6
+ "bin": {
7
+ "wukong": "./dist/cli.cjs"
8
+ },
9
+ "files": [
10
+ "dist/cli.cjs",
11
+ "README.md",
12
+ "CHANGELOG.md",
13
+ "LICENSE"
14
+ ],
15
+ "license": "MIT",
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "scripts": {
20
+ "postinstall": "node ./dist/cli.cjs --postinstall",
21
+ "build": "node scripts/build-lib.mjs",
22
+ "build:shipped": "node scripts/build-shipped.mjs",
23
+ "test": "node --test",
24
+ "typecheck": "node scripts/typecheck.mjs",
25
+ "verify": "node scripts/verify-shipped.mjs && node scripts/typecheck.mjs && node --test",
26
+ "link:dev": "node scripts/link-dev.mjs"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^26.6.4",
30
+ "@types/react": "^18.3.31",
31
+ "esbuild": "0.25.10",
32
+ "javascript-obfuscator": "5.9.0",
33
+ "typescript": "5.9.3"
34
+ },
35
+ "keywords": [
36
+ "deepseek",
37
+ "harness",
38
+ "dsh",
39
+ "wukong",
40
+ "prompt",
41
+ "skill",
42
+ "agent",
43
+ "desktop"
44
+ ],
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/agassiz/dsh-plugin-wukong.git"
48
+ },
49
+ "homepage": "https://github.com/agassiz/dsh-plugin-wukong",
50
+ "bugs": {
51
+ "url": "https://github.com/agassiz/dsh-plugin-wukong/issues"
52
+ }
53
+ }