dsh-plugin-wukong-cli 0.25.1 → 0.26.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +118 -402
- package/README.md +112 -396
- package/dist/cli.cjs +1 -1
- package/package.json +8 -16
- package/CHANGELOG.md +0 -589
- package/LICENSE +0 -21
package/CHANGELOG.md
DELETED
|
@@ -1,589 +0,0 @@
|
|
|
1
|
-
# 更新日志
|
|
2
|
-
|
|
3
|
-
> **Wukong**(插件包 `dsh-plugin-wukong`;0.14.0 之前叫 Armory / 包名 `dsh-switchblade`,更早为 `@deepseek-ai/dsh-switchblade` + `@deepseek-ai/dsh-client-ui-switchblade`)的所有重要变更。
|
|
4
|
-
|
|
5
|
-
**中文** · [**English**](./CHANGELOG.en.md)
|
|
6
|
-
|
|
7
|
-
格式基于 [Keep a Changelog](https://keepachangelog.com/),版本遵循 [Semantic Versioning](https://semver.org/)。
|
|
8
|
-
|
|
9
|
-
## [0.25.1] - 2026-10
|
|
10
|
-
|
|
11
|
-
### 修复 · Fixed
|
|
12
|
-
- **生图后回复里时有时无地不显示大图**:工具卡片只画缩略图,大图要靠助手在回复里用 Markdown 嵌入,但这条要求只写在工具说明与技能末尾,离回复太远,部分模型(如 DeepSeek)会漏掉。现在 `generate_image` / `edit_image` 的工具结果末尾多一行提醒,并直接给出带真实路径、可照抄的 ``;工具卡片仍只读第一行,界面不变。
|
|
13
|
-
**The full image sometimes missing from the reply after generation**: the tool card only shows a thumbnail and the full image relies on the assistant embedding it with Markdown, but that request lived only in the tool description and at the end of the skill, too far from the reply, so some models (e.g. DeepSeek) skipped it. The `generate_image` / `edit_image` result now ends with a reminder carrying a ready-to-copy `` with the real path; the tool card still reads only the first line, so the UI is unchanged.
|
|
14
|
-
|
|
15
|
-
## [0.25.0] - 2026-10
|
|
16
|
-
|
|
17
|
-
### 新增 · Added
|
|
18
|
-
- **提示词页新增「初始化模型」**(在「提示词增强」上面):输入 provider 名(默认 `cpa`),一键给它下面所有模型声明图片输入(`input: [text, image]`,即多模态)并统一标准思考等级(`off→none, low, medium, high, xhigh, max`),provider 的 `defaultInput` 也设成同一集合。规则与 DSH.app「工具 → 初始化 cpa 模型」的脚本一致,区别是不写死 `profiles/web`:改的是当前运行的那个 profile(按启动参数 `--profile` / 桌面宿主的 profile 目录参数 / `dsh web` 等子命令认出来,认不出就报错,不碰别的 profile)。点完在按钮下面显示改了哪个环境、哪个文件、改了什么。用 `yaml` 按节点修改,注释、`!!js` 表达式与其他条目原样保留;写回前备份 `cordis.patch.yml.models-bak-<时间戳>`(只留最近三份),先写临时文件再改名,profile 是 live 重载的,无需重启;已经是目标配置时提示无需改动,也不留备份。新增路由 `POST /api/wukong/models/init`。`yaml` 作为开发依赖打包进宿主 bundle,插件包本身仍无运行时依赖。
|
|
19
|
-
**"Initialize models" on the Prompts page**: type a provider name (default `cpa`) and one click declares image input (`input: [text, image]`, i.e. multimodal) on every model under it and sets the standard reasoning levels (`off→none, low, medium, high, xhigh, max`); the provider's `defaultInput` becomes the same set. The rules match the script behind DSH.app's "Tools → Initialize cpa models", except it does not hard-code `profiles/web`: it edits the profile that is running (recognised from `--profile`, the desktop host's profile-directory argument or a `dsh web`-style subcommand; refusing rather than guessing, and touching no other profile), and shows under the button which environment and file it changed and what changed. It edits nodes with `yaml`, so comments, `!!js` expressions and other entries are kept as written; before writing it backs up `cordis.patch.yml.models-bak-<timestamp>` (the latest three are kept) and writes a temp file then renames, and the profile reloads live, so no restart; an already set-up provider says "nothing to change" and leaves no backup. New route `POST /api/wukong/models/init`. `yaml` is a dev dependency bundled into the host bundle, so the plugin package still has no runtime dependencies.
|
|
20
|
-
|
|
21
|
-
## [0.24.2] - 2026-10
|
|
22
|
-
|
|
23
|
-
### 修复 · Fixed
|
|
24
|
-
- **桌面端图片编辑器里的圆形变成了圆角方块**:宿主主题给所有元素设了 `corner-shape: superellipse(1.5)`,`border-radius: 50%` 在支持该属性的 Chromium 里会被画成圆角方块(颜色块、调色盘、橡皮圈、粗细滑块的圆钮、评论编号、重发按钮、加载转圈、壁纸开关)。这些圆形元素现在都显式写了 `corner-shape: round`。
|
|
25
|
-
**Circles in the image editor turned into rounded squares in the desktop client**: the host theme sets `corner-shape: superellipse(1.5)` on every element, so a `border-radius: 50%` is drawn as a rounded square in Chromium builds that support the property (colour swatches, the colour picker, the eraser ring, the thickness-slider knob, comment badges, the resend button, the spinner and the wallpaper switch). All of those circles now say `corner-shape: round` explicitly.
|
|
26
|
-
- **拖粗细滑块时正在输入的文字框消失**:按住滑块会让文字框失焦,空文字被当成"输入结束"收掉。现在按住滑块、点颜色按钮和调色板都不再抢文字框的焦点,文字大小与颜色实时跟着变。
|
|
27
|
-
**The text box disappeared while dragging the thickness slider**: pressing the slider blurred the text box, and an empty text was treated as "done" and dropped. Pressing the slider, the colour button and the palette no longer takes focus from the text box, so the size and colour follow live.
|
|
28
|
-
- **评论多了盖住图片**:图片最大高度写死成"视口高度减 250px",评论条变高后图片不会让位。现在图片按中间舞台区域剩下的高度缩放;评论排成整齐的两列、最多三行,再多在条内滚动。没有评论或一两条评论时高度不变,图片不动。
|
|
29
|
-
**Many comments covered the image**: the image's maximum height was fixed at "viewport minus 250px", so it did not give way when the comment bar grew. The image now scales to the height the stage has left; comments sit in two tidy columns, at most three rows, and scroll beyond that. With no comments or one or two the height is unchanged and the image does not move.
|
|
30
|
-
|
|
31
|
-
### 变更 · Changed
|
|
32
|
-
- **选择工具下拖粗细滑块,改的是选中的那条标注**:文字改字号,线条与形状改线宽,一次拖动只记一条撤销记录;点选标注时滑块会指到它当前的粗细。
|
|
33
|
-
**With the Select tool, the thickness slider edits the selected mark**: a text's font size, a line's or shape's width, one undo entry per drag; selecting a mark moves the slider to its current thickness.
|
|
34
|
-
|
|
35
|
-
## [0.24.1] - 2026-10
|
|
36
|
-
|
|
37
|
-
### 修复 · Fixed
|
|
38
|
-
- **生图页的说明不再重复**:页面顶部和「图像生成」卡片里各显示了一遍同一段说明,现在只保留页面顶部那一条。
|
|
39
|
-
**The Images page no longer says the same thing twice**: the same blurb showed both at the top of the page and inside the "Image generation" card; only the one at the top is kept.
|
|
40
|
-
- **技能页不再列出插件自己注入的 `wukong-imagegen`**:它是只给模型用的内置技能,出现在「本地扫描技能」里会让人误以为要「托管」。面板的技能目录现在把它过滤掉;技能本身照常随生图工具注册,`/wukong` 命令的目录不受影响。
|
|
41
|
-
**The Skills page no longer lists the plugin's own `wukong-imagegen`**: it is a built-in skill for the model only, and showing it under "Scanned skills" made people think it needed to be "managed". The panel's skill catalog now filters it out; the skill itself is still registered with the image tools, and the `/wukong` command's catalog is unchanged.
|
|
42
|
-
|
|
43
|
-
## [0.24.0] - 2026-10
|
|
44
|
-
|
|
45
|
-
### 新增 · Added
|
|
46
|
-
- **改图与图片查看器**:新增 `edit_image` 工具(`POST {baseURL}/images/edits`,原图 + 提示词 + 可选蒙版;只能改项目或保存目录里的图,结果存成 `<原名>-edited` 且不覆盖;不发 `input_fidelity` 与 `background`,照 Codex `imagegen` 技能记的 `gpt-image-2` 约束)。工具结果那一行加了缩略图与「编辑图片」,点开是全屏查看器(交互照 Codex):**标注**(点开后工具栏换成选择 / 画笔 / 文字 / 形状(直线、箭头、矩形、椭圆、三角形、菱形、五角星、爱心)/ 颜色(13 个预设 + 自定义取色面板)/ 橡皮(像素橡皮,一点点擦掉自己画的)/ 撤销重做 / 退出,左边竖向滑块调粗细;标注是可选中、移动、局部擦除的矢量对象)、**添加评论**(框区域写意见,带编号,同时生成蒙版)、**擦除**(画笔涂抹,面板直接带蒙版让 Host 改图)、**移除背景**(点击后先确认;先请模型直接给透明背景,返回的图已带透明区域就原样采用,否则让模型出纯绿底图、浏览器里按 Codex `remove_chroma_key.py` 的软抠像把绿色抠成透明)、**调整大小**(浏览器里缩放另存);结果都存在原图旁边,可「上一版」退回。标注与评论通过「发送给助手」在当前会话发一条带标注图的新消息。新增路由 `GET /api/wukong/imagegen/file`、`POST /api/wukong/imagegen/{edit,save}`。
|
|
47
|
-
**Editing and an image viewer**: a new `edit_image` tool (`POST {baseURL}/images/edits`, the original plus a prompt and an optional mask; it can only edit images inside the project or the save folder, saves the result as `<name>-edited` and never overwrites; it sends neither `input_fidelity` nor `background`, following the `gpt-image-2` notes in Codex's `imagegen` skill). The result row gains a thumbnail and an "Edit image" button that opens a full-screen viewer (the interaction follows Codex): **Annotate** (the bar turns into select / pen / text / shape (line, arrow, rectangle, ellipse, triangle, diamond, star, heart) / colour (13 presets plus a custom picker) / eraser (a pixel eraser that rubs out parts of what you drew) / undo-redo / exit, with a vertical thickness slider; marks are vector objects that can be selected, moved and partly rubbed out), **Comment** (box a region and write what to change, numbered, which also yields a mask), **Erase** (paint, and the panel has the Host edit with the mask directly), **Remove background** (asks for confirmation first; the model is first asked for a transparent background and a result that already has transparent areas is used as it is, otherwise the model draws the subject on pure green and the browser turns it transparent with a soft matte ported from Codex's `remove_chroma_key.py`), **Resize** (scaled in the browser and saved); every result is saved beside the original and "Previous version" steps back. Annotations and comments go through "Send to assistant", a new message with the annotated image in the current session. New routes: `GET /api/wukong/imagegen/file` and `POST /api/wukong/imagegen/{edit,save}`.
|
|
48
|
-
- **随工具注入的 `wukong-imagegen` 技能**:只给模型用,写明图片提示词怎么写、编辑时「只改 X、保留 Y」、收到标注图怎么处理、透明背景怎么做;改写自 Codex 的 `imagegen` 技能(Apache-2.0)。与两个生图工具同生共死:没选好模型时不注入,不占上下文。
|
|
49
|
-
**A `wukong-imagegen` skill injected with the tools**: for the model only, covering how to write image prompts, "change only X; keep Y unchanged" for edits, what to do with an annotated image and how to get a transparent background; adapted from Codex's `imagegen` skill (Apache-2.0). It lives and dies with the two image tools: not injected until a model is chosen, so it takes no context for nothing.
|
|
50
|
-
|
|
51
|
-
### 变更 · Changed
|
|
52
|
-
- **`generate_image` 的保存目录只由面板「保存目录」决定,工具改收 `file_name`**:模型原来可以传 `output_path`(比如 `summer.png`),一传就绕开用户配置的目录、把图丢进项目根目录。现在工具只接受文件名,传目录或 `../` 都会被收成最后一段名字;保存目录(默认 `output/imagegen`,相对当前会话项目,也可填绝对路径)只由面板设置决定;同名文件不覆盖,自动加 `-2`、`-3`。
|
|
53
|
-
**`generate_image` saves only into the panel's save folder, and the tool now takes `file_name`**: the model used to be able to pass `output_path` (say `summer.png`), which bypassed the folder the user had configured and dropped the image into the project root. The tool now accepts a file name only — a directory or `../` is cut down to its last segment — and the save folder (default `output/imagegen`, relative to the current session project, or an absolute path) is decided by the panel setting alone; an existing file is never overwritten (`-2`, `-3` is appended).
|
|
54
|
-
- **没选好 Provider 与模型时不再注册生图工具**:以前工具在启动时无条件注册,没配模型时模型也看得到它,调用后才被拒绝。现在只有保存了 Provider 与模型才注册 `generate_image`、`edit_image` 和 `wukong-imagegen` 技能,保存后立即出现,清除后立即卸载,无需重启。
|
|
55
|
-
**The image tools are no longer registered until a Provider and a model are chosen**: they used to be registered unconditionally at startup, so the model saw the tool and was refused only after calling it. `generate_image`, `edit_image` and the `wukong-imagegen` skill are now registered only once a Provider and a model are saved, appearing the moment they are saved and disappearing the moment they are cleared, with no restart.
|
|
56
|
-
- **工具结果那一行多了缩略图和「编辑图片」按钮**:成功后的一行文字旁边有一张小缩略图和按钮,点开是图片查看器;`edit_image` 的结果也用同一个视图。
|
|
57
|
-
**The result row gains a thumbnail and an "Edit image" button**: next to the one-line text there is a small thumbnail and a button that opens the image viewer; `edit_image` results use the same view.
|
|
58
|
-
|
|
59
|
-
## [0.23.0] - 2026-10
|
|
60
|
-
|
|
61
|
-
### 新增 · Added
|
|
62
|
-
- **生图:`generate_image` 工具与面板「生图」页**:给会话注册一个生图工具,模型按文字提示词调用 OpenAI 兼容的 Images API(`POST {baseURL}/images/generations`,认 `b64_json` 或 `url`),图片存进会话工作区(默认 `output/imagegen/<slug>-<时间戳>.<ext>`,可用 `output_path` 指定),有附件服务时同时登记为会话附件。参数:`prompt`(必填)、`size`、`quality`、`output_format`、`output_path`,缺省用面板默认值。设置 → Wukong → 生图页从宿主模型目录(与提示词增强、模型选择器同一份)选 Provider 与模型,并设默认尺寸 / 质量 / 格式 / 输出目录;**不预置任何模型名**,没选全就调用报 `imagegen-unset`。端点与密钥不存进插件状态:按次从宿主 settings 里该 Provider 的 `baseURL` / `apiKeyEnv` 与 `credentials` 服务解析。状态文档新增 `imagegen` 一段(写入 `null` 清回默认值,非法偏好回落默认、Provider / 模型原样保留)。工具注册在 `tools` 服务上(独立 fiber),headless profile 也能用。详见 README「🖼️ 生图」。
|
|
63
|
-
**Image generation: the `generate_image` tool and an Images page in the panel**: registers an image tool in the session; the model calls an OpenAI-compatible Images API with a text prompt (`POST {baseURL}/images/generations`, reading `b64_json` or `url`) and the image is saved into the session workspace (by default `output/imagegen/<slug>-<timestamp>.<ext>`, or wherever `output_path` says), also registered as a session attachment when the attachment service exists. Parameters: `prompt` (required), `size`, `quality`, `output_format`, `output_path`, defaulting to the panel's values. Settings → Wukong → Images picks the Provider and model from the host's model catalog (the same one as Prompt enhancement and the model picker) and sets the default size / quality / format / output directory; **no model name is built in**, and calling it before both are chosen fails with `imagegen-unset`. The endpoint and key are not stored in the plugin's state: they are resolved per call from that Provider's `baseURL` / `apiKeyEnv` in the host's settings and the `credentials` service. The state document gains an `imagegen` section (writing `null` clears it to the defaults; an invalid preference falls back to its default while Provider / model are kept as-is). The tool is registered on the `tools` service in its own fiber, so a headless profile can use it. See the README's "🖼️ Image generation".
|
|
64
|
-
- **生图在对话里的展示**:用 `tool.call.toolview` 按工具名 `generate_image` 注册自己的视图,替换宿主默认的工具卡片。进行中显示与成图同比例的骨架占位(点阵加一道很淡的扫光,浅色 / 深色主题都可见,开了「减少动态效果」时不动);成功后收成一行「Generated … at <路径>」,图由助手在回复里用 Markdown 嵌入(工具说明里要求了),避免同一张图在工具卡片与回复里各出现一次;失败显示一行错误文字。
|
|
65
|
-
**How an image shows in the chat**: registers its own view for the tool name `generate_image` in `tool.call.toolview`, replacing the host's default tool card. While running it shows a skeleton placeholder in the image's aspect ratio (a dot grid with one faint sweep, visible in light and dark themes and still under reduced motion); on success it collapses to one "Generated … at <path>" line, and the image is embedded by the assistant in its reply with Markdown (the tool description asks for it) so the same image does not appear in both the tool card and the reply; a failure shows one line of error text.
|
|
66
|
-
|
|
67
|
-
### 修复 · Fixed
|
|
68
|
-
- **`generate_image` 调用时传的 `size` / `quality` 之前不会发给 API**:工具算出了覆盖后的值并写进返回结果,但请求体用的仍是面板里的默认值,返回的尺寸与实际出图参数对不上。现在覆盖值真正进入请求,并补了断言请求体的测试。
|
|
69
|
-
**The `size` / `quality` passed in a `generate_image` call were not sent to the API**: the tool worked out the overridden values and put them in its result, but the request body still used the panel's defaults, so the reported size did not match what was actually requested. The overrides now reach the request, with a test that asserts the request body.
|
|
70
|
-
|
|
71
|
-
## [0.22.2] - 2026-10
|
|
72
|
-
|
|
73
|
-
### 新增 · Added
|
|
74
|
-
- **会话「编辑重发」与「分叉」**:把鼠标移到某条用户消息上,「时间 + 复制」那一行(整行只在悬停时显示)多出「编辑」「分叉」两个图标。「编辑」把这条消息就地换成与底部输入框同款的编辑框(带圆形发送按钮),发送后跳转到新会话,原会话移入回收站,可恢复:编辑**第一条**消息等同新建对话(同一工作区新建会话,标题由宿主按新对话生成);编辑**后面**的消息从该消息所在轮次之前分叉,并沿用原标题。「分叉」只从该消息之前分叉并跳转,不发送。入口通过 Portal 落到宿主的用户消息节点上(依赖 `data-chat-flow-kind="user"` 与 `data-clock="start"`),宿主没有给用户消息开扩展座位。
|
|
75
|
-
**Edit & resend and Fork on a user message**: hover a user message and its "time + copy" row (shown only on hover) gains two icons, Edit and Fork. Edit swaps the message in place for an editor styled like the composer below (with a round send button); sending switches to the new session and moves the original to the recycle bin, where it can be restored. Editing the **first** message is a brand-new conversation (a fresh session in the same workspace, titled by the host like any new one); editing a **later** message forks from just before its turn and keeps the original title. Fork only forks from just before the message and switches, sending nothing. The entry points are portalled onto the host's user-message node (relying on `data-chat-flow-kind="user"` and `data-clock="start"`); the host exposes no extension seat for user messages.
|
|
76
|
-
- **归档管理(设置 → 归档管理)**:已归档 / 未归档 / 回收站三个页签,按工作区分组;支持单条与工作区/全部的归档、取消归档、移入回收站、恢复,永久删除与清空回收站先确认范围与数量。宿主日志只追加、没有删除接口,所以「移入回收站」是把会话目录 `rename` 到 `$DSH_HOME/wukong/trash/`、写入 `trash.json` 并清理工作区注册表;宿主里一直驻留内存的已归档会话会先按宿主自己的销毁顺序卸载再移动;永久删除先持久化意图再删数据,中断后启动时自动续作或修复。设计参考 [Ultronen/dsh-archived-chats](https://github.com/Ultronen/dsh-archived-chats)(MIT),为本插件独立实现,本版不含预览、搜索、备份、保留策略与来源树。新增路由 `GET /api/wukong/archive/state`,`POST /api/wukong/archive/{archive,unarchive,trash,restore,purge,discard,fork-point}`。设置导航里「归档管理」使用宿主自带的归档盒图标,「Wukong」换成自己的图标。
|
|
77
|
-
**Archive management (Settings → Archive Management)**: Archived / Active / Recycle bin tabs grouped by workspace, with archive, unarchive, move to the bin and restore for one session, a workspace or everything; permanent delete and emptying the bin confirm the scope and count first. The host log is append-only and has no delete API, so "move to the bin" `rename`s the session directory into `$DSH_HOME/wukong/trash/`, records it in `trash.json` and cleans the workspace registry; an archived session the host keeps resident is first unloaded with the host's own teardown sequence; a permanent delete persists its intent before deleting bytes, and an interrupted one is finished or repaired at startup. The design follows [Ultronen/dsh-archived-chats](https://github.com/Ultronen/dsh-archived-chats) (MIT) but is an independent implementation; this version has no preview, search, backup, retention policy or lineage tree. New routes: `GET /api/wukong/archive/state` and `POST /api/wukong/archive/{archive,unarchive,trash,restore,purge,discard,fork-point}`. In the settings navigation, Archive Management uses the host's own archive-box icon and Wukong gets its own glyph.
|
|
78
|
-
|
|
79
|
-
### 修复 · Fixed
|
|
80
|
-
- **编辑重发不再留下空的「已完成」轮次**:宿主日志里用户消息位于 `turn/start` 之后,原先在「消息 seq − 1」处分叉会切在未结束的轮次中间,宿主补出空轮次,每次编辑多一个。现在由宿主按日志算出干净的分叉点(上一轮的 `turn/end`,跳过排队用的 `agent/inbox/spliced`)。
|
|
81
|
-
**Edit & resend no longer leaves empty "completed" turns**: in the host log a user message sits after its `turn/start`, so forking at "message seq − 1" cut inside an open turn and the host closed it with an empty one — one more per edit. The host now computes a clean fork point from the log (the previous turn's `turn/end`, skipping the `agent/inbox/spliced` that queued the message).
|
|
82
|
-
|
|
83
|
-
## [0.22.1] - 2026-10
|
|
84
|
-
|
|
85
|
-
### 新增 · Added
|
|
86
|
-
- **`npm run build:dev`:不压缩、不混淆的开发版构建**:写出与正式构建相同的文件、相同的位置(软链着本仓库的 profile 重启即可使用),代码可读、堆栈里有真实函数名,用来调试混淆后读不出的报错。每个开发版产物首行是 `DEV BUILD` 注释;`npm run verify`、`build-lib.mjs --check` 与两个包新增的 `prepublishOnly` 钩子见到它都会失败并提示先跑 `npm run build`,所以它不会被误提交或误发布。
|
|
87
|
-
**`npm run build:dev`: a readable, non-minified, non-obfuscated build**: it writes the same files to the same places as the official build (a profile linked to this repo just needs a restart), with readable code and real function names in stack traces, for debugging what the obfuscated build makes unreadable. Every dev artifact starts with a `DEV BUILD` comment; `npm run verify`, `build-lib.mjs --check` and the new `prepublishOnly` hook of both packages fail on it and say to run `npm run build` first, so it cannot be committed or published by accident.
|
|
88
|
-
- **README「开发」章节补上「连接本地开发版 / 切回已发布版」**:怎么用 `--spec link:` 把 profile 连到工作副本、改完怎么重建生效、怎么确认连的是哪一份、怎么切回 npm 版,以及隔离 `DSH_HOME`、混淆产物难读堆栈、`npm install` 清掉 `link:dev` 软链这几个坑;PUBLISHING 补上两个包的发布前钩子说明。
|
|
89
|
-
**The README's Development chapter gains "Connecting to the local dev build / switching back to the published one"**: how to point a profile at the working copy with `--spec link:`, how to rebuild for an edit to take effect, how to tell which one a profile is on, how to switch back to the npm build, and the traps — an isolated `DSH_HOME`, unreadable stack traces from the obfuscated build, and `npm install` removing the `link:dev` symlinks; PUBLISHING documents the pre-publish hook of both packages.
|
|
90
|
-
|
|
91
|
-
### 变更 · Changed
|
|
92
|
-
- **成功提示改成绿色,失败仍是红色**:顶部的提示条原来不论成败都是红色错误样式,「已保存增强模型」「已复制 …的配置」「已复制 N 台服务器」这类成功消息看起来像出错了。现在提示条带语气:成功用成功色(绿),失败保持红色,`名称未更改` 这类说明用琥珀色;成功与说明的 `role` 是 `status`,失败仍是 `alert`,读屏软件不会把成功当成警报念出来。所有原有调用默认仍是失败,只有明确成功的几处改了。
|
|
93
|
-
**A success notice is now green; a failure stays red**: the bar at the top used the red error style whatever happened, so a success such as "Saved the enhancement model", "Copied the config for …" or "Copied N servers" looked like an error. The bar now carries a tone: green for a success, red for a failure, amber for a plain note such as "Name unchanged"; a success or a note has `role="status"` while a failure keeps `role="alert"`, so a screen reader does not announce a success as an alarm. Every existing call still defaults to a failure; only the ones that clearly succeed changed.
|
|
94
|
-
- **提示词增强的 Provider / 模型改成下拉选择,不再手填**:两个输入框换成两个下拉,选项来自宿主模型选择器用的同一份目录(`sessionController.modelCatalog()`,经新增的 `GET /api/wukong/models` 读出,按提供商分组),所以固定下来的一定是真实存在的模型。选了 Provider 会自动带出它的模型,并预选部署默认模型(若属于它);选项显示名称,id 放在悬浮提示里,仅两项重名时才附上 id。之前存下的路由如果已不在目录里(提供商被移除、换了账号),仍显示为「xxx(不在可用列表中)」,可以看见、替换或清除。宿主没有该服务、读取失败或目录为空时,退回原来的手填输入框并给出刷新按钮,功能不受影响。目录逐项校验,畸形或重复的条目会被丢弃,没有可选模型的提供商不出现。
|
|
95
|
-
**The Prompt-enhancement Provider / Model fields are now dropdowns instead of free text**: the two inputs became two selects fed by the same catalog the host's model picker uses (`sessionController.modelCatalog()`, read through the new `GET /api/wukong/models`, grouped by provider), so a pinned route is always a model that exists. Choosing a provider fills in its model, preselecting the deployment default when it belongs to that provider; options show the name with the id in the tooltip, appending the id only when two entries share a name. A route stored earlier that the catalog no longer lists (a provider removed, a different account) still shows as "xxx (not in the available list)", so it can be seen, replaced or cleared. When the host has no such service, the read fails or the catalog is empty, the original free-text fields come back with a refresh button, so nothing stops working. The catalog is validated entry by entry: malformed or duplicate entries are dropped and a provider with no model to pick does not appear.
|
|
96
|
-
|
|
97
|
-
### 修复 · Fixed
|
|
98
|
-
- **「今天」统计的测试在整点后的第一分钟会误报失败**(仅测试,不影响发布产物):它把「1 分钟前」的步骤断言落在当前这一小时里,整点后第一分钟会跨进上一小时甚至上一天。改为用当前整点,并核对了几个边界时刻。
|
|
99
|
-
**The test for the "today" usage view failed during the first minute after each hour** (test only; the published artifacts are unaffected): it asserted a step from "a minute ago" into the current hour, which crosses into the previous hour — or day — right after a boundary. It now uses the top of the current hour, checked at several boundary times.
|
|
100
|
-
|
|
101
|
-
## [0.22.0] - 2026-10
|
|
102
|
-
|
|
103
|
-
### 新增 · Added
|
|
104
|
-
- **内置风景壁纸**:随插件附带五张原创风景(雪山日出、薄雾森林、沙漠黄昏、海岸星夜、高山湖泊,程序生成、无第三方素材,随包 MIT),壁纸页新增「内置风景」缩略图选择区,点一下即应用并启用壁纸。宿主新增 `GET /api/wukong-wallpaper/preset/<id>.jpg`(及 `<id>-thumb.jpg`),名字走固定白名单、同样流式并支持 `Range`;所选风景只是把路径写进现有的 `url` 字段,状态文档没有新字段。
|
|
105
|
-
**Bundled landscape wallpapers**: five original landscapes ship with the plugin (dawn peaks, misty forest, desert dusk, night coast, alpine lake — generated procedurally, no third-party imagery, MIT with the rest of the package), and the Wallpaper tab gains a thumbnail picker where one click applies one and turns the wallpaper on. The host gains `GET /api/wukong-wallpaper/preset/<id>.jpg` (and `<id>-thumb.jpg`), served from a fixed name whitelist, streamed, with `Range` support; picking one just stores its path in the existing `url` field, so the state document has no new field.
|
|
106
|
-
- **README 截图换成当前版本的真实截图**:旧截图是重构前的界面,已全部替换(深色 / 浅色主图 + 提示词、技能、MCP、壁纸四页)。
|
|
107
|
-
**README screenshots replaced with the current UI**: the old ones showed the pre-refactor panel; they are all replaced (dark and light hero shots plus the Prompts, Skills, MCP and Wallpaper pages).
|
|
108
|
-
|
|
109
|
-
### 变更 · Changed
|
|
110
|
-
- **发布的包只含压缩并混淆后的产物,不带源码**:插件包的 `lib/`、`client/` 与安装器的 `dist/cli.cjs` 都先经 esbuild 压缩(标识符、空白、注释),再经 `javascript-obfuscator` 把字符串字面量放进编码查表并重命名局部标识符;**属性名不动**,因为宿主按属性名(`apply`、`inject`、服务成员)调用这份代码,改了插件就失效。控制流平坦化、死代码注入、自我防御与调试陷阱一概不开,它们会让体积成倍增长、拖慢启动,也是最常见的出错来源。固定了随机种子,产物逐字节可复现,`npm run verify` 的「构建可复现」检查照常工作。插件包不再带 `src/`(也去掉了 `./src/*` 导出),安装器包发布的入口改为 `dist/cli.cjs`(`bin` 与 `postinstall` 随之改指它);仓库里仍保留可读的 `cli.cjs` 与 `src/`。`verify-shipped` 随之更新:改为在沙箱里真正执行 client bundle,核对它向模块表请求的只有 `react` 与 `react/jsx-runtime`,不再依赖产物里的字符串,并新增「发布包不含源码」的检查。
|
|
111
|
-
**The published packages carry only the compressed, obfuscated build — no sources**: the plugin's `lib/` and `client/` and the installer's `dist/cli.cjs` are minified by esbuild (identifiers, whitespace, comments), then `javascript-obfuscator` moves string literals into an encoded lookup table and renames the remaining local identifiers; **property names are left alone**, because the harness calls this code by property name (`apply`, `inject`, service members) and renaming them would break the plugin. Control-flow flattening, dead-code injection, self-defending and debug traps are all off: they multiply the size, slow the start-up and are the usual source of breakage. The random seed is fixed, so the output is byte-for-byte reproducible and the build-reproducibility check in `npm run verify` keeps working. The plugin package no longer ships `src/` (and its `./src/*` export is gone), and the installer package publishes `dist/cli.cjs` as its entry (`bin` and `postinstall` point at it); the repo keeps the readable `cli.cjs` and `src/`. `verify-shipped` follows: it now runs the client bundle in a sandbox and checks that it asks the module table for `react` and `react/jsx-runtime` only, no longer depending on strings in the output, and gains a check that the published packages carry no sources.
|
|
112
|
-
- **提示词与技能的新增 / 编辑改成居中弹窗**:两个 tab 不再在列表上方铺一块内联表单,技能 tab 也不再让「添加」整页替换列表——点右上角「添加」或卡片上的「编辑」都会开一个最高 720px 宽、640px 高的弹窗,正文文本域吃掉剩余高度(不低于 240px,内部滚动),列表留在背景里可见。Esc / 点遮罩 / ✕ 都能取消,焦点进入首个字段、关闭后回到触发它的按钮,弹窗打开期间锁定背景滚动;保存失败保留弹窗与已填内容,成功后回到列表。
|
|
113
|
-
**Prompt and skill create/edit moved into a centered dialog**: neither tab pads the top with an inline form any more, and the Skills tab no longer swaps the whole list out for an add view — the top-right "Add" button and each row's "Edit" open a dialog (up to 720px wide, 640px tall) whose body textarea takes the remaining height (never below 240px, scrolling inside) while the list stays visible behind it. Escape, the scrim and ✕ all cancel, focus enters the first field and returns to the triggering button, background scrolling is locked while it is open, and a failed save keeps the dialog and what was typed.
|
|
114
|
-
|
|
115
|
-
- **壁纸的主题 token 改走官方 `ctx.theme.overrideTokens`**:背景层之上让应用外壳透明、输入卡片 / 气泡 / 代码块的毛玻璃填充,现在合成**一层**主题覆盖,每个值给 light / dark 一对,由主题服务按当前配色选取、在切主题时重新应用、释放时只移除这一层。不再手写内联变量再自己保存还原,也不再需要监听暗色属性的 MutationObserver;此前换主题会把壁纸洗掉。玻璃的亮度与高光改为纯 CSS 按配色切换。`--wk-*` 数值旋钮仍是插件命名空间内的内联变量,关闭时全部移除。
|
|
116
|
-
**Wallpaper theme tokens now go through the official `ctx.theme.overrideTokens`**: the transparent app chrome and the frosted-glass fill on the input card / bubbles / code blocks are one composed theme override layer, each value a light/dark pair that the theme service picks for the active scheme, re-applies on a theme change and removes alone on release. No more hand-written inline variables with a hand-rolled save/restore, and no MutationObserver on the dark attribute; switching theme used to wash the wallpaper out. Glass brightness and sheen switch per scheme in plain CSS. The `--wk-*` numeric knobs stay inline variables in the plugin's own namespace and are all removed when the wallpaper is turned off.
|
|
117
|
-
- **面板填满设置对话框,不再写死 600px 内容高度**:此前面板自己的页眉加 600px 内容区会超出宿主滚动区 16px,出现第二根滚动条;现在页眉与标签页固定,只有页面列滚动,矮窗口下同样只有一处滚动。滑块行的最小列宽从 230px 调到 280px,数值与 ↺ 不再被挤到下一行;字体改为继承宿主。
|
|
118
|
-
**The panel fills the settings dialog instead of a fixed 600px content area**: its header plus 600px overshot the host's scroll region by 16px and added a second scrollbar; now the header and tabs stay put and only the page column scrolls, on a short window too. Slider rows have a 280px minimum column (was 230px), so the value and ↺ no longer wrap under the slider; the font is inherited from the host.
|
|
119
|
-
|
|
120
|
-
### 修复 · Fixed
|
|
121
|
-
- **换壁纸后界面里最暗的那档灰字看不清**:应用里「创造模式」「对话 / 轨迹」「工作区」标题、状态行、文件夹图标这类最淡的文字,是按主题自带的纯色背景调的;浅色壁纸压在深色主题上(或深色壁纸压在浅色主题上)时会被吃掉,而固定的 25% 遮罩无从得知是哪种情况。新增**「自动遮罩」**(默认开启,旧配置无需迁移):首次载入壁纸时在画布上缩小采样,测出它最暗 / 最亮部分的亮度,再按当前主题把遮罩加深或提亮到刚好让文字站得住(深色主题压到亮部不超过目标亮度,浅色主题抬到暗部不低于目标亮度,上限 70%);「遮罩」滑块变成它的最低值。深浅两个强度同时交给 CSS 按主题属性选取,切换主题不需要脚本。视频取第一帧;外部链接的图片因跨域读不到像素,仍只用滑块的值。
|
|
122
|
-
**The dimmest tier of interface text was unreadable after setting a wallpaper**: text such as "创造模式", the "对话 / 轨迹" tabs, the "工作区" heading, the status line and the folder icon is tuned for the theme's own flat background, so a pale wallpaper under the dark theme (or a dark one under the light theme) swallowed it, and a fixed 25% scrim cannot know which case it is in. New **"Auto scrim"** (on by default, no migration for existing settings): the wallpaper is sampled small on a canvas when it first loads to measure its darkest and brightest parts, and the scrim is deepened or lightened for the active theme just far enough for the text to stand (the bright parts no brighter than the target under the dark theme, the dark parts no darker under the light theme, capped at 70%); the Scrim slider becomes its floor. Both strengths are handed to CSS, which picks one by the theme attribute, so a theme switch needs no script. A video is sampled on its first frame; an image from another site cannot be read back across origins and keeps using the slider alone.
|
|
123
|
-
- **键盘可用性**:输入框、文本域与搜索框去掉内联 `outline: none`,统一补上与宿主 Switch 同源 token 的 `:focus-visible` 焦点环;四处文件上传按钮此前用 `display:none` 导致键盘根本够不到,现在留在 Tab 顺序里并显示焦点环;标签页补全 ARIA 标签页模式(`tabpanel`、`aria-controls`、roving tabindex、方向键 / Home / End);壁纸开关补 `aria-label`,空格键不再滚动页面;所有过渡动画尊重 `prefers-reduced-motion`。
|
|
124
|
-
**Keyboard use**: the inline `outline: none` is gone from the input, textarea and search fields, and one `:focus-visible` ring using the same tokens as the host's Switch covers every control; the four file-upload buttons used `display:none`, which put them out of keyboard reach, and now stay in the tab order with a visible ring; the tabs follow the ARIA tabs pattern (`tabpanel`, `aria-controls`, roving tabindex, arrow keys / Home / End); the wallpaper switch has an `aria-label` and Space no longer scrolls the page; every transition respects `prefers-reduced-motion`.
|
|
125
|
-
- **拖动壁纸滑块不再每个像素写一次整份状态文档**:绘制仍是即时的,保存改为停手 350ms 后一次(一次 30 步的拖动由 31 次写入降为 1 次),关闭对话框时会补写未保存的改动;写入遇到并发冲突(409)会在最新文档上重放一次;保存失败会提示,不再静默。副作用同时移出了 `setState` 的 updater。
|
|
126
|
-
**Dragging a wallpaper slider no longer rewrites the whole state document per pixel**: painting is still immediate, while the save waits 350ms after the drag settles (a 30-step drag went from 31 writes to 1), a change still waiting is flushed when the dialog closes, a write that hits a concurrency conflict (409) is replayed once on top of the newer document, and a failed save now says so instead of staying silent. The side effects also left the `setState` updater.
|
|
127
|
-
- **图片切换为视频(或反过来)后背景不显示**:背景元素只按首次的类型创建一次,之后换类型仍复用,视频地址被塞进 `<img>`。现在类型变化时重建元素。
|
|
128
|
-
**A wallpaper stopped showing after switching from an image to a video (or back)**: the backdrop element was created once for the first media kind and reused, so a video URL ended up in an `<img>`. It is now rebuilt when the kind changes.
|
|
129
|
-
- **视频壁纸**:创建后只 `setAttribute('muted')` 不会让元素真正静音,自动播放可能被拒,现在同时设置属性与 `muted` 属性;页面隐藏时暂停、恢复后继续,系统要求减少动态效果时不自动播放。
|
|
130
|
-
**Video wallpaper**: setting only the `muted` attribute after creation does not mute the element, so autoplay could be refused; the property is now set as well. The video pauses while the page is hidden and resumes after, and does not autoplay when the system asks for reduced motion.
|
|
131
|
-
- **壁纸媒体路由支持 Range 与流式读取**:`GET /api/wukong-wallpaper/image/<id>` 现在回应 `Accept-Ranges`,处理单段 `Range`(206 / 416),多段或畸形的 Range 回退为整文件;文件走流而不是整个读进内存(Safari 不会播放不支持 Range 的视频)。上传同样改为流式写入临时文件再重命名,主机在 `Content-Length` 超过 60MB 时直接 413,面板在发送前就检查同一上限并给出提示。
|
|
132
|
-
**The wallpaper media route supports Range and streams**: `GET /api/wukong-wallpaper/image/<id>` now answers `Accept-Ranges`, serves a single `Range` (206 / 416) and falls back to the whole file for a multi-range or malformed one; the file is streamed instead of read into memory whole (Safari plays no video from a server that ignores Range). Uploads stream to a temp file and are renamed on success too, the host answers 413 as soon as `Content-Length` is over 60MB, and the panel checks the same limit before sending and says so.
|
|
133
|
-
- **被替换或清除的壁纸文件不再永远留在磁盘上**:每次壁纸 section 写入和每次启动后,主机清理未被任何 section 引用的 `up-<24 位十六进制>.<扩展名>` 上传(及中断上传留下的 `.part`);刚上传的文件有 10 分钟宽限期,因为面板先上传、后保存引用;目录里其他文件一概不动。
|
|
134
|
-
**Replaced or cleared wallpaper files no longer stay on disk forever**: after every wallpaper-section write and after startup, the host removes `up-<24 hex>.<ext>` uploads (and the `.part` of an interrupted one) that no section references; a fresh upload has a 10-minute grace period because the panel uploads first and saves the reference after; nothing else in the directory is touched.
|
|
135
|
-
- **启动时不再先闪一下未应用壁纸的页面**:浏览器把最近一次的壁纸设置缓存在 localStorage,启动时先按缓存绘制,再由主机文档校正;缓存不可用时行为与以前一致。默认值也收敛到 `state-schema.ts` 一处,不再在主机与面板各写一份。
|
|
136
|
-
**No more flash of the unthemed page on start**: the browser caches the last wallpaper section in localStorage and paints from it first, then the host document corrects it; without storage the behaviour is as before. The defaults also live in one place, `state-schema.ts`, instead of one copy each in the host and the panel.
|
|
137
|
-
- **面板版本徽章的回退常量**停在 0.21.0(`WUKONG_VERSION`),README 徽章停在 0.15.0,均已同步到 0.22.0。
|
|
138
|
-
**The panel's fallback version constant** (`WUKONG_VERSION`) was stuck at 0.21.0 and the README badge at 0.15.0; both now read 0.22.0.
|
|
139
|
-
|
|
140
|
-
### 移除 · Removed
|
|
141
|
-
- **`/wukong-*` 命令族只剩 `/wukong-skill-dir`**:列出、启用 / 停用、卸载、markdown 与 zip 安装、状态查看、bundle patch 层导出 / 导入,面板都已具备,不再各配一条命令。被删掉的这些都需要参数却没声明 `input`,于是在 `/` 菜单里点一下就会**立刻不带参数执行**并直接报错(`/wukong-enable` 点开就是一句用法提示);留下的 `/wukong-skill-dir` 声明了 `input`,菜单选中时落回输入框等参数,补上目录再回车才执行——它也是面板唯一做不到的事(浏览器读不到任意主机目录)。随之下线的是 `patch.ts`(bundle patch 层序列化)、它的 6 项测试与 `exportBundle` / `importBundle`:那条导入会把托管技能**整体替换**,而面板与安装器都不消费这种 patch 层。
|
|
142
|
-
**The `/wukong-*` family is down to `/wukong-skill-dir`**: listing, enable/disable, uninstall, markdown and zip installs, state inspection, and bundle-patch export/import all already exist in the panel and no longer have a command each. Every removed command took an argument without declaring `input`, so picking one from the `/` menu **ran it bare on the spot** and answered with an error (`/wukong-enable` opened straight into a usage line); the survivor declares `input`, so a menu pick stays in the composer until the directory is typed — and it is the one thing the panel cannot do, since a browser cannot read an arbitrary host directory. `patch.ts` (the bundle-patch serializer), its 6 tests and `exportBundle`/`importBundle` went with them: that import replaced the whole managed-skill list wholesale, and neither the panel nor the installer consumes such a patch layer.
|
|
143
|
-
|
|
144
|
-
## [0.21.0] - 2026-10
|
|
145
|
-
|
|
146
|
-
### 变更 · Changed
|
|
147
|
-
- **包名与仓库名统一改为 `dsh-plugin-wukong`(安装器 `dsh-plugin-wukong-cli`),插件自身数据目录仍为 `$DSH_HOME/wukong/`**:插件包改名 `dsh-plugin-wukong`,安装器包改名 `dsh-plugin-wukong-cli`(bin 仍是 `wukong` → `./cli.cjs`),仓库迁到 [`agassiz/dsh-plugin-wukong`](https://github.com/agassiz/dsh-plugin-wukong);插件自己的数据仍在 `$DSH_HOME/wukong/…`(状态文档、`market-cache`、`market-tmp`、`exports`、壁纸目录),技能仍在 `$DSH_HOME/skills/`——harness 的文件系统技能提供者扫的就是这个路径,我们没有改它。
|
|
148
|
-
**Package and repository names unified as `dsh-plugin-wukong` (installer `dsh-plugin-wukong-cli`), and the plugin's own data directory stays `$DSH_HOME/wukong/`**: the plugin package is renamed to `dsh-plugin-wukong`, the installer package to `dsh-plugin-wukong-cli` (bin still `wukong`), and the repository is now [`agassiz/dsh-plugin-wukong`](https://github.com/agassiz/dsh-plugin-wukong); the plugin's own data stays under `$DSH_HOME/wukong/…` (the state document, `market-cache`, `market-tmp`, `exports`, wallpaper directory), while skills stay in `$DSH_HOME/skills/` — the path the harness filesystem skill provider scans, which we do not control.
|
|
149
|
-
- **安装器只做一件事,而且走标准路径**:`cli.cjs` 在每个选中的 profile 里执行 `pnpm add <spec>`(默认 spec 是 npm 上已发布的 `dsh-plugin-wukong@<安装器版本>`;`--spec` 可换成 npm 包名 / 本地路径 / tarball / git 地址),把 `dsh-plugin-wukong` 追加进 profile 的 `dsh.profile.bundles`,再清理更早版本留下的安装痕迹(旧 bundle/依赖名、`node_modules/@deepseek-ai/` 作用域下的拷贝式安装、profile patch 里手写的面板行、旧的 `$DSH_HOME/{switchblade,wallpapers,armory-exports}` 目录)。profile 里的这条依赖记录就是插件管理器的「已安装」身份。pnpm 是必需项(找不到时安装器直接报错退出),安装器包的 `files` 里只有 `cli.cjs` 与文档,不带插件副本。
|
|
150
|
-
**The installer does one thing, the standard way**: `cli.cjs` runs `pnpm add <spec>` inside every selected profile (the default spec is the published `dsh-plugin-wukong@<installer version>`; `--spec` swaps in an npm name / local path / tarball / git address), appends `dsh-plugin-wukong` to the profile's `dsh.profile.bundles`, and cleans up what much older releases left behind (the old bundle/dependency names, the copy-style installs under `node_modules/@deepseek-ai/`, the hand-written panel row in the profile patch, the old `$DSH_HOME/{switchblade,wallpapers,armory-exports}` directories). That dependency record in the profile is the plugin manager's "installed" identity. pnpm is required (a missing pnpm stops the installer with an error), and the installer's `files` list is `cli.cjs` plus the docs, with no plugin copy.
|
|
151
|
-
|
|
152
|
-
## [0.16.0] - 2026-10
|
|
153
|
-
|
|
154
|
-
### 新增 · Added
|
|
155
|
-
- **扩展市场:MCP 与技能都可以从目录里搜索并安装**:新增 `GET /api/wukong/market?kind=mcp|skill&q=<关键词>` 与 `POST /api/wukong/market/install`。市场把多个上游目录聚合成同一种条目:MCP 来自**官方 MCP Registry** 与 **DSH MCP Market 快照**,技能来自 **ClawHub** 与 **SkillsMP**。每个条目都带来源名、来源等级(`bundled` / `official` / `curated` / `community`)、权限说明、热度(上游给 star 或下载量时)和**所需环境变量**;只有先搜索、再显式指定某个条目 id,才会真正安装——市场只是索引,不会自动装任何东西。
|
|
156
|
-
**Marketplace for MCP servers and skills**: `GET /api/wukong/market?kind=mcp|skill&q=<query>` and `POST /api/wukong/market/install` are new. The market normalizes several upstream directories into one item shape: MCP from the **official MCP Registry** and the **DSH MCP Market snapshot**, skills from **ClawHub** and **SkillsMP**. Every item carries its source name, a source-level trust label (`bundled` / `official` / `curated` / `community`), permission notes, popularity when the upstream reports stars or downloads, and the **environment variables it needs**; nothing installs until a search has listed it and an explicit item id is chosen.
|
|
157
|
-
- **离线可用**:某个源不可达或限流时,其余源照常显示并给出提示;全部源都失败时回退到上一次成功结果的磁盘缓存(`$DSH_HOME/wukong/market-cache`,读取时同样做 schema 校验,格式不对就当作没有缓存),再回退到随包精选(3 个 MCP 服务器 + 2 个技能模板),因此第一次打开市场、或整台机器离线时也有东西可装。
|
|
158
|
-
**Works offline**: an unreachable or rate-limited source only adds a warning while the others still answer; when every source fails the market falls back to the last successful result cached on disk (`$DSH_HOME/wukong/market-cache`, schema-checked on read, and a malformed file counts as no cache), and then to the bundled set (3 MCP servers + 2 skill templates), so there is something to install on a first run or on an offline machine.
|
|
159
|
-
- **MCP 安装写进插件自己的 MCP 行**:`POST /api/wukong/market/install` 生成 `serverName`(自动加短后缀避让重名)、`transport`、`command`/`args`/`env` 或 `url`/`headers`。需要环境变量的服务器**以禁用状态安装**并在响应里返回 `needsEnv`,不会在变量就绪之前启动子进程;环境变量在配置里写成 `${NAME}` 引用。
|
|
160
|
-
**MCP installs land in the plugin's own MCP rows**: `POST /api/wukong/market/install` produces `serverName` (with a short suffix to avoid a collision), `transport`, `command`/`args`/`env` or `url`/`headers`. A server that needs environment variables is installed **disabled** and the response lists `needsEnv`, so no child process starts before the variables exist; the variables are referenced as `${NAME}` in the config.
|
|
161
|
-
- **技能安装分两条路径**:单文件(随包模板)注册为**运行时技能**——面板立刻看得到、每个会话都能用、重启后仍在;带附加文件的仓库技能则写进 `$DSH_HOME/skills/<name>`,交给 harness 的文件系统技能提供者。
|
|
162
|
-
**Two skill install paths**: a single-file skill (a bundled template) is registered as a **managed runtime skill**, so the panel lists it immediately, every session can use it and it survives a restart; a repository skill that ships extra files is written to `$DSH_HOME/skills/<name>` for the harness filesystem skill provider.
|
|
163
|
-
- **面板里的市场浏览器**:技能与 MCP 两个页签都有可折叠的市场区块,支持关键词搜索(Enter 或按钮触发,不逐键请求)、刷新、来源与来源等级徽标、上游链接、权限与环境变量提示,以及一条一条的安装按钮;离线或使用了缓存时状态行会说清楚。
|
|
164
|
-
**A market browser in the panel**: both the Skills and the MCP tab get a collapsible market block with keyword search (Enter or button, never per keystroke), refresh, source and trust badges, a link to the upstream page, permission and environment-variable notes, and a per-item install button; the status line says when results are offline or served from cache.
|
|
165
|
-
- **24 项市场相关测试**:上游响应归一化(Registry / DSH 快照 / ClawHub / SkillsMP)、条目校验与拒绝、路径逃逸防护、去重、离线回退与磁盘缓存、`SKILL.md` 下载端点、以及"上游塞进畸形条目也不会被列出来"。
|
|
166
|
-
**24 new market tests**: upstream normalization (Registry / DSH snapshot / ClawHub / SkillsMP), item validation and rejection, path-escape defence, de-duplication, offline fallback and the disk cache, the `SKILL.md` download endpoint, and the case where a hostile upstream payload cannot inject an item.
|
|
167
|
-
|
|
168
|
-
### 安全 · Security
|
|
169
|
-
- 市场内容一律**先校验再使用**:条目 schema 校验(来源等级、权限数组、payload 形状)、技能相对路径禁止绝对路径 / `..` / 反斜杠 / 控制字符、单文件 1MB、单目录 8MB、归档 16MB、每源 10 秒超时、一个技能最多 64 个文件,GitHub 归档解压后还要过一遍包含性检查(不许符号链接、不许逃出目录)。安装动作只写插件的状态文档与技能根目录,不改 profile、不执行下载来的代码,上游被收录或带 `official` 标签都不等于安全背书。
|
|
170
|
-
**Market content is validated before use**: item schema validation (trust label, permission array, payload shape), skill-relative path rules that refuse absolute paths, `..`, backslashes and control characters, 1MB per file, 8MB per catalog, 16MB per archive, a 10-second timeout per source, at most 64 files per skill, and a containment pass over any extracted GitHub archive (no symbolic links, nothing outside the target). An install only writes the plugin's own state document and the user skill root: it does not modify the profile, does not run downloaded code, and neither upstream listing nor an `official` label is a security endorsement.
|
|
171
|
-
|
|
172
|
-
## [0.15.0] - 2026-10
|
|
173
|
-
|
|
174
|
-
### 变更 · Changed
|
|
175
|
-
- **拆成两个包:安装器 `dsh-plugin-wukong-cli` 与插件包 `dsh-plugin-wukong`**:npm 安装器改名为 `dsh-plugin-wukong-cli`(bin 仍是 `wukong` → `./cli.cjs`);它**不声明 `dsh` 字段、因此不是 bundle**,`files` 里只有 `cli.cjs` 与文档。插件包仍是 `dsh-plugin-wukong`(`packages/wukong/`),声明 `dsh.bundle.patch` 与 `dsh.client`(platform web),必须装进 profile。两个名字分开是有意的:`pnpm add dsh-plugin-wukong`(或在 harness 插件管理器里选 `dsh-plugin-wukong`)本来就是标准路径,安装器命令不该和 bundle 抢名字。
|
|
176
|
-
**Split into two packages: installer `dsh-plugin-wukong-cli` + plugin package `dsh-plugin-wukong`**: the npm installer is renamed to `dsh-plugin-wukong-cli` (bin still `wukong` → `./cli.cjs`); it declares **no `dsh` field, so it is not a bundle**, and its `files` list is `cli.cjs` plus the docs. The plugin package is still `dsh-plugin-wukong` (`packages/wukong/`), declares `dsh.bundle.patch` and `dsh.client` (platform web), and must be installed into a profile. The split is deliberate: `pnpm add dsh-plugin-wukong` (or picking `dsh-plugin-wukong` in the harness plugin manager) is already the standard path, so the installer command should not fight the bundle over one name.
|
|
177
|
-
- **CLI 新增 `-h/--help` 与 `-v/--version`**:两者在任何安装动作之前处理,只打印用法或版本后退出,不碰任何 profile。`--spec <spec>`、`--profile <name>` 与卸载行为不变。
|
|
178
|
-
**New CLI flags `-h/--help` and `-v/--version`**: both are handled before any install work, printing usage or the version and exiting without touching a profile. `--spec <spec>`, `--profile <name>` and uninstall behaviour are unchanged.
|
|
179
|
-
- **状态写入契约:`{state, ifRevision}` + `revision` + HTTP 409 `stale`**:`GET /api/wukong/state` 返回 `{ok, revision, state}`;`POST /api/wukong/state` 接受 `{state, ifRevision}`(扁平文档仍兼容),每次接受的写入都会归一化整份文档并让 `revision` 加一;`ifRevision` 与当前值不符时返回 HTTP 409 与 `{ok:false, error:'stale', revision, state}`,调用方应采用返回的文档。读取同样先归一化整份文档。
|
|
180
|
-
**State write contract: `{state, ifRevision}` + `revision` + HTTP 409 `stale`**: `GET /api/wukong/state` answers `{ok, revision, state}`; `POST /api/wukong/state` takes `{state, ifRevision}` (a bare flat document is still accepted), normalizes the whole document on every accepted write and increments `revision`; a mismatched `ifRevision` gets HTTP 409 with `{ok:false, error:'stale', revision, state}`, and the caller is expected to adopt the returned document. Reads normalize the whole document first too.
|
|
181
|
-
- **新增 `GET /api/wukong/skills`**:返回 `{ok, revision, skills, commands}`,即面板需要的技能 + 托管命令目录,浏览器不再从整份状态文档里重建它。
|
|
182
|
-
**New `GET /api/wukong/skills` route**: it returns `{ok, revision, skills, commands}` — the skill + managed-command catalog the panel needs — so the browser no longer reconstructs it from the whole state document.
|
|
183
|
-
- **对话与统计重做**:改走 harness 的 session-query 服务,不再手工解析 store 文件;项目目录编码与持久化后端一致;列表带标题与占用大小;缓存命中率与首字时间取自真实用量;导入经持久化服务流式写盘;删除会拒绝仍在运行的会话,`/update` 需要显式确认。
|
|
184
|
-
**Conversations and stats reworked**: they read through the harness session-query service instead of hand-parsing store files; the project-directory encoding matches the persistence backend; the list carries title and size columns; cache-hit rate and first-token time come from real usage data; import streams through the persistence service; delete refuses a session that is still live and `/update` requires explicit confirmation.
|
|
185
|
-
- **版本查询与一键更新改走安装器包**:`GET /api/wukong/version` 返回 `{ok, latest, current}`——`current` 在运行时从插件自己的 `package.json`(`lib/` 旁边)读取,面板里编译期常量只作回退;`latest` 先问 `dsh-plugin-wukong-cli` 再问 `dsh-plugin-wukong`,registry 不可达或尚未发布时返回空串。`POST /api/wukong/update` 现在执行 `npm exec --yes --package=dsh-plugin-wukong-cli -- wukong`(安装并运行安装器包),仍要求请求体带 `{"confirm":true}`,否则 HTTP 400 `confirmation-required`。此前它试图从 `dsh-plugin-wukong` 这个 bundle 里跑 `wukong` bin——而 bundle 没有 bin,这是包拆分引出的真实缺陷。
|
|
186
|
-
**Version lookup and one-click update now go through the installer package**: `GET /api/wukong/version` returns `{ok, latest, current}` — `current` is read at runtime from the plugin's own `package.json` beside `lib/` (the compiled-in constant in the panel is only a fallback), and `latest` is asked of `dsh-plugin-wukong-cli` first and `dsh-plugin-wukong` second, returning an empty string when the registry is unreachable or the package is unpublished. `POST /api/wukong/update` now runs `npm exec --yes --package=dsh-plugin-wukong-cli -- wukong` (installs and runs the installer package) and still requires `{"confirm":true}`, otherwise HTTP 400 `confirmation-required`. Previously it tried to run the `wukong` bin out of the `dsh-plugin-wukong` bundle — which has no bin — a real defect caused by the package split.
|
|
187
|
-
- **导出归档自动清理**:每次导出后都会清理 `$DSH_HOME/wukong/exports`,保留最新 10 个归档,并删除超过 7 天的文件,目录不会随使用无限增长。
|
|
188
|
-
**Export archives are pruned automatically**: after every export `$DSH_HOME/wukong/exports` is cleaned up — the 10 newest archives are kept and anything older than 7 days is removed — so the directory cannot grow without bound.
|
|
189
|
-
|
|
190
|
-
### 修复 · Fixed
|
|
191
|
-
- **同源围栏收紧**:外部来源与 opaque(`Origin: null`)来源、以及 `Sec-Fetch-Site: cross-site` 一律 HTTP 403;不带 `Origin` 的请求只在回环(loopback)主机上接受。
|
|
192
|
-
**Strict same-origin fence**: a foreign or opaque (`Origin: null`) origin, or `Sec-Fetch-Site: cross-site`, gets HTTP 403, and a request without an `Origin` is accepted only on a loopback host.
|
|
193
|
-
- **提示词正文不再插值**:正文以 `interpolate: false` 的 system-prompt section 注册,字面 `{{cwd}}`(或任何 `{{...}}`)原样送到模型。这修掉了一个真实 bug——插值开启时渲染器会在拼装系统提示词时抛错,让每个启用该提示词的会话的每一步模型调用都失败。
|
|
194
|
-
**Prompt bodies are no longer interpolated**: they register as system-prompt sections with `interpolate: false`, so a literal `{{cwd}}` (or any `{{...}}`) reaches the model verbatim. This fixes a real bug: with interpolation on, the renderer threw while assembling the system prompt and failed every model step of every session that had the prompt enabled.
|
|
195
|
-
- **zip 导入加封堵检查**:解压出的目录树在进入托管根之前先做包含性校验(zip slip 与符号链接一律拒绝);PowerShell 回退路径的引号写法也已修正。
|
|
196
|
-
**Zip imports are containment-checked**: an extracted tree is validated before it enters a managed root (zip slip and symlinks are refused), and the PowerShell fallback path now quotes correctly.
|
|
197
|
-
- **坏 zip 的报错更准确**:归档读不出来时区分「宿主没有解压工具」与「归档无法解压:没有任何工具接受该文件(它是不是合法 zip?)」,上传损坏文件时不再误导用户去装 unzip。
|
|
198
|
-
**A corrupt archive now gets an accurate error**: when a zip cannot be read, the host distinguishes "no unzip tool available" from "archive could not be extracted: no zip tool accepted the file (is it a valid zip?)", so a corrupt upload no longer tells the user to install unzip.
|
|
199
|
-
- **MCP 服务器状态不再假装成功**:新组合的 loader 条目在 10 秒宽限期内报 `starting`,发布出工具后报 `running`;10 秒内没有任何工具出现时带上 `lastError`,而不是静默显示「运行中、0 个工具」。
|
|
200
|
-
**MCP server status no longer pretends success**: a freshly composed loader entry reports `starting` during the 10-second grace window and `running` once it publishes a tool; when no tool appears within 10 seconds it carries a `lastError` instead of silently showing "running with 0 tools".
|
|
201
|
-
- **自定义斜杠命令没有进程内 handler 时明确报错**:从磁盘恢复的命令行拿不到进程内的闭包 handler,此时命令返回显式错误(说明它来自磁盘、本进程没有 handler),不再假装修好可用。
|
|
202
|
-
**A custom slash command with no process-local handler now reports an explicit error**: a command row restored from disk cannot carry its in-process closure, so it returns an explicit error saying exactly that instead of faking success.
|
|
203
|
-
- **面板侧修复**:壁纸读取改为有上限的重试(并正确 dispose,不再是无限重建循环);读取失败不再清空提示词列表;颜色改用主题 token 而不是硬编码色值;面板加了 error boundary,错误通知可手动关闭。
|
|
204
|
-
**Client-side fixes**: the wallpaper read is now a bounded retry with proper disposal (no more infinite rebuild loop); a failed read no longer blanks the prompt list; colors use theme tokens instead of hardcoded values; the panel gained an error boundary and dismissible error notices.
|
|
205
|
-
|
|
206
|
-
### 文档与工具 · Docs & tooling
|
|
207
|
-
- **新增测试套件与自检脚本**:`npm test` 用 `node --test` 跑 `test/`;`npm run verify` 先跑 `node scripts/verify-shipped.mjs`(包身份、结构、语法、构建可复现性)再跑测试;`npm run link:dev` 把本机已安装的 harness 包软链进仓库的 `node_modules/@deepseek-ai/`,供差分用例使用(不链时这些用例自行跳过,其余照常通过)。测试需要 Node 24 或更高版本(直接用类型擦除跑 TypeScript 源码)。
|
|
208
|
-
**New test suite and self-check scripts**: `npm test` runs `node --test` over `test/`; `npm run verify` runs `node scripts/verify-shipped.mjs` (package identity, structure, syntax, build reproducibility) and then the tests; `npm run link:dev` symlinks the installed harness packages into the repo's `node_modules/@deepseek-ai/` for the differential cases (without it they skip themselves and the rest still passes). Tests need Node 24 or newer (they run the TypeScript sources directly through type stripping).
|
|
209
|
-
- **`packages/wukong/tsconfig.json` 修成自包含配置**:不再有失效的 `extends` 或过期的 project references,供编辑器与 `tsc` 使用。
|
|
210
|
-
**`packages/wukong/tsconfig.json` is now a self-contained config**: no broken `extends` and no stale project references, usable by editors and `tsc`.
|
|
211
|
-
|
|
212
|
-
## [0.14.0] - 2026-10
|
|
213
|
-
|
|
214
|
-
### 变更 · Changed
|
|
215
|
-
- **项目更名为 Wukong,插件包改为 `dsh-plugin-wukong`**:仓库迁到 [`agassiz/dsh-plugin-wukong`](https://github.com/agassiz/dsh-plugin-wukong);npm 安装器包名 `prompt-skill-armory` → `dsh-plugin-wukong`,bin 从 `armory` / `prompt-skill-armory` 两个名字收敛为**单个 `wukong`**(不保留别名)。包目录 `packages/switchblade/` → `packages/wukong/`。
|
|
216
|
-
**Renamed to Wukong, plugin package is now `dsh-plugin-wukong`**: the repository moved to [`agassiz/dsh-plugin-wukong`](https://github.com/agassiz/dsh-plugin-wukong); the npm installer package `prompt-skill-armory` is now `dsh-plugin-wukong`, and its two bin names (`armory`, `prompt-skill-armory`) collapse into the single **`wukong`** (no aliases). The package directory moved from `packages/switchblade/` to `packages/wukong/`.
|
|
217
|
-
- **内部标识一次性全部更名**(本项目处于测试期,**不提供任何旧名兼容或迁移**):cordis service `switchblade` → `wukong`;源码 `src/switchblade.ts` → `src/wukong.ts`,类 `Switchblade` → `Wukong`(`SwitchbladeState`/`SwitchbladePatch`/`SwitchbladeSection` 等同理);面板 cordis 插件名 `ui-switchblade` → `ui-wukong`;设置项 id `switchblade` → `wukong`,语言命名空间 `settings.switchblade` → `settingswukong`;同源路由 `/api/armory/*` → `/api/wukong/*`,壁纸路由 `/api/switchblade-wallpaper/*` → `/api/wukong-wallpaper/*`;斜杠命令族 `/armory[-*]` → `/wukong[-*]`(**去掉了 `/sw-*` 别名**);状态文档 `$DSH_HOME/switchblade/state.json` → `$DSH_HOME/wukong/state.json`,壁纸与导出目录收敛到 `$DSH_HOME/wukong/{wallpapers,exports}`;面板显示名 Armory → Wukong;浏览器样式标识 `data-ar-*` / `--ar-*` → `data-wk-*` / `--wk-*`。
|
|
218
|
-
**Every internal identifier was renamed in one pass** (this project is in testing and ships **no compatibility or migration for the old name**): cordis service `switchblade` → `wukong`; `src/switchblade.ts` → `src/wukong.ts` with class `Switchblade` → `Wukong` (likewise `WukongState`/`WukongPatch`/`WukongSection`); the panel's cordis plugin `ui-switchblade` → `ui-wukong`; settings entry id `switchblade` → `wukong` and locale namespace `settings.switchblade` → `settingswukong`; same-origin routes `/api/armory/*` → `/api/wukong/*` and wallpapers `/api/switchblade-wallpaper/*` → `/api/wukong-wallpaper/*`; the slash-command family `/armory[-*]` → `/wukong[-*]` (**the `/sw-*` aliases are gone**); the state document moved to `$DSH_HOME/wukong/state.json` with wallpapers and exports consolidated under `$DSH_HOME/wukong/{wallpapers,exports}`; the panel display name is now Wukong; browser style hooks `data-ar-*` / `--ar-*` became `data-wk-*` / `--wk-*`.
|
|
219
|
-
- **安装器清理旧名安装与旧数据**:安装时除了 `dsh-plugin-wukong` 本身,还会移除旧 bundle/依赖名(`dsh-switchblade`、`@deepseek-ai/dsh-switchblade`)、`node_modules/@deepseek-ai/` 下两份旧拷贝、profile patch 里手写的 `ui-switchblade` 行,以及旧数据目录 `$DSH_HOME/switchblade`、`$DSH_HOME/wallpapers`、`$DSH_HOME/armory-exports`。`uninstall` 现在连同 `$DSH_HOME/wukong/`(状态文档 + 壁纸 + 导出)一起删除——**配置不再保留**;`$DSH_HOME/skills` 仍保留。
|
|
220
|
-
**The installer cleans up both the old-name install and its data**: besides installing `dsh-plugin-wukong`, it removes the old bundle/dependency names (`dsh-switchblade`, `@deepseek-ai/dsh-switchblade`), the two old copies under `node_modules/@deepseek-ai/`, the hand-written `ui-switchblade` row in the profile patch, the old data directories `$DSH_HOME/switchblade`, `$DSH_HOME/wallpapers`, `$DSH_HOME/armory-exports`. `uninstall` now also deletes `$DSH_HOME/wukong/` (state document + wallpapers + exports) — **configuration is not kept**; `$DSH_HOME/skills` still is.
|
|
221
|
-
- **移除 `plugin-src/` 遗留镜像**:那是 0.13.0 之前两个旧包的快照,既不构建也不发布,随更名一并删除(需要时可从 git 历史取回)。
|
|
222
|
-
**Removed the legacy `plugin-src/` mirror**: it was a snapshot of the two pre-0.13 packages, neither built nor published, and went away with the rename (recoverable from git history if ever needed).
|
|
223
|
-
|
|
224
|
-
## [0.13.1] - 2026-10
|
|
225
|
-
|
|
226
|
-
### 修复 · Fixed
|
|
227
|
-
- **输入框下方统计条的提示样式在 0.2.1 世代重新生效**:统计条容器在 2.0.9 之后已由 `[data-composer-stats]` 改为 `[data-composer-dock]`,每条统计是 `[data-composer-stat]`(文字标签仍是哈希 `_label` 类)。旧选择器在当前 frontend 里匹配不到任何元素,因此提示样式的「统计条」部分实际是失效的。现在一条规则同时匹配 `[data-composer-dock]`、`[data-composer-stat]` 与遗留的 `[data-composer-stats]`;`[data-composer-placeholder]` 与 `[data-composer-card]` 两个标记在当前世代仍然存在,未改动。
|
|
228
|
-
**The composer stats-strip hint style works again on the 0.2.1 generation**: after 2.0.9 the harness renders the strip as `[data-composer-dock]` with one `[data-composer-stat]` pill per stat (labels keep a hashed `_label` class), so the old `[data-composer-stats]` selector matched nothing and that part of the hint style was dead. One rule now matches `[data-composer-dock]`, `[data-composer-stat]` and the legacy `[data-composer-stats]`; `[data-composer-placeholder]` and `[data-composer-card]` still exist in this generation and are unchanged.
|
|
229
|
-
|
|
230
|
-
## [0.13.0] - 2026-10
|
|
231
|
-
|
|
232
|
-
### 变更 · Changed
|
|
233
|
-
- **打包合并为单个插件包 `dsh-switchblade`**:原来的 `@deepseek-ai/dsh-switchblade`(Host)+ `@deepseek-ai/dsh-client-ui-switchblade`(面板)合并成一个可发布的包,位于 `packages/switchblade/`(不带 scope)。面板源码移到 `packages/switchblade/src/client/**`,浏览器产物改为 `packages/switchblade/client/client.js`。包内同时声明两面:`dsh.bundle.patch = ./cordis.patch.yml`(唯一的 Host 行 `id: switchblade`、`name: dsh-switchblade`)与 `dsh.client = { platform: 'web', inject: [...] }`(`exports["./client"]`)——与社区插件 `dsh-plugin` 同形。因此**不再需要第二个包、也不再需要第二条 loader 行**。
|
|
234
|
-
**Repackaged as one plugin package, `dsh-switchblade`**: the former `@deepseek-ai/dsh-switchblade` (host) + `@deepseek-ai/dsh-client-ui-switchblade` (panel) are now a single publishable, unscoped package under `packages/switchblade/`. Panel sources moved to `packages/switchblade/src/client/**` and the browser artifact is now `packages/switchblade/client/client.js`. The package declares both faces — `dsh.bundle.patch = ./cordis.patch.yml` (the single host row `id: switchblade`, `name: dsh-switchblade`) and `dsh.client = { platform: 'web', inject: [...] }` via `exports["./client"]` — the same shape the community `dsh-plugin` uses. **No second package and no second loader row are needed.**
|
|
235
|
-
- **安装器改走标准安装路径**:`cli.cjs` 在 profile 目录里执行 `pnpm add <spec>`,再把 `dsh-switchblade` 追加进 profile 的 `dsh.profile.bundles`,最后清理 0.13 之前拷贝式安装的遗留物:`node_modules/@deepseek-ai/dsh-switchblade` 与 `@deepseek-ai/dsh-client-ui-switchblade` 两份拷贝、旧 bundle 名 `@deepseek-ai/dsh-switchblade`,以及 profile `cordis.patch.yml` 里手写的 `ui-switchblade` 行(**只删这一条**,其余行逐字节保留,因为那份文件 DSH.app 也在写)。
|
|
236
|
-
**The installer now takes the standard install path**: `cli.cjs` runs `pnpm add <spec>` inside the profile, appends `dsh-switchblade` to the profile's `dsh.profile.bundles`, then cleans up the pre-0.13 copy-style install — the two copies under `node_modules/@deepseek-ai/`, the legacy bundle name `@deepseek-ai/dsh-switchblade`, and the hand-written `ui-switchblade` row in the profile's `cordis.patch.yml` (that entry only; every other line stays byte-identical because DSH.app writes that file too).
|
|
237
|
-
- **新增 `--spec`**:`--spec <npm 包名|本地路径|tarball|git 地址>` 可从任意来源安装。`--profile/-p` 行为不变(可重复 / 逗号分隔),`--postinstall` 不变。`uninstall` 改为 `pnpm remove dsh-switchblade` + 取消 bundle 选择 + 同样的遗留清理;状态文档与 `$DSH_HOME/skills` 照旧保留。
|
|
238
|
-
**New `--spec` flag**: `--spec <namespace|tarball|git url>` installs from any source. `--profile/-p` is unchanged (repeatable / comma lists), as is `--postinstall`. `uninstall` now runs `pnpm remove dsh-switchblade` + drops the bundle selection + the same legacy cleanup; the state document and `$DSH_HOME/skills` are still kept.
|
|
239
|
-
- **构建产物随打包变化**:`scripts/build-lib.mjs` 现在只产出 `packages/switchblade/lib/index.js`、`lib/invariant.js` 与 `packages/switchblade/client/client.js`。`scripts/build-shipped.mjs` 变成**可选**的上游同步:只拷 `<harness>/packages/switchblade/switchblade/src` → `packages/switchblade/src`、`<harness>/packages/client/ui-switchblade/src/client` → `packages/switchblade/src/client`、`lib/{index,invariant}.js`,并且**不会覆盖**仓库自己的 `package.json`、`cordis.patch.yml`、`client/client.js`;同步完仍需跑 `node scripts/build-lib.mjs`。
|
|
240
|
-
**Build outputs follow the repackaging**: `scripts/build-lib.mjs` now emits only `packages/switchblade/lib/index.js`, `lib/invariant.js` and `packages/switchblade/client/client.js`. `scripts/build-shipped.mjs` became an **optional** upstream sync: it copies only `<harness>/packages/switchblade/switchblade/src` → `packages/switchblade/src`, `<harness>/packages/client/ui-switchblade/src/client` → `packages/switchblade/src/client` and `lib/{index,invariant}.js`, and deliberately **never overwrites** this repo's `package.json`, `cordis.patch.yml` or `client/client.js`; you still run `node scripts/build-lib.mjs` afterwards.
|
|
241
|
-
|
|
242
|
-
### 修复 · Fixed
|
|
243
|
-
- **`pnpm add` 不再因 `@deepseek-ai/*` 抓不到而 404 失败**:所有 `@deepseek-ai/*` 运行时包与 `react`/`react-dom` 都改在 `peerDependenciesMeta` 里标为 `optional`,运行时 `dependencies` 为空。这些包不在公共 npm 源上,写成必选 peer 会让 pnpm 直接 `ERR_PNPM_FETCH_404`;标成可选后 pnpm 能顺利装上插件,而模块仍由 harness 宿主在运行时提供。
|
|
244
|
-
**`pnpm add` no longer fails on `@deepseek-ai/*` fetch 404s**: every `@deepseek-ai/*` runtime package plus `react`/`react-dom` is now `optional` in `peerDependenciesMeta`, and runtime `dependencies` are empty. Those packages are not on the public npm registry, so required peers made pnpm abort with `ERR_PNPM_FETCH_404`; optional peers let pnpm install the plugin while the harness host supplies those modules at runtime.
|
|
245
|
-
- **插件现在会出现在 harness 的插件界面里**:它是带 bundle patch 的真实 pnpm profile 依赖,所以侧栏**插件**页与**设置 → 插件**的「已安装」列表都会列出并允许开关(旧的拷贝式安装没有依赖记录,因此从不出现)。面板本身仍在**设置 → Prompt-SkillArmory**(书图标)。
|
|
246
|
-
**The plugin now appears in the harness plugin surfaces**: being a real pnpm profile dependency with a bundle patch, it is listed and toggleable on the sidebar **Plugins** page and under **Settings → Plugins** → "Installed" (the old copy-style install left no dependency record, so it never showed up). The panel itself stays at **Settings → Prompt-SkillArmory** (book icon).
|
|
247
|
-
|
|
248
|
-
### 移除 · Removed
|
|
249
|
-
- **`packages/client-ui-switchblade/` 目录**:面板已并入 `packages/switchblade/`(源码 `src/client/**`,产物 `client/client.js`)。
|
|
250
|
-
**The `packages/client-ui-switchblade/` directory**: the panel is now part of `packages/switchblade/` (sources `src/client/**`, artifact `client/client.js`).
|
|
251
|
-
- **`plugin-src/` 明确为遗留物**:它保存的是 0.13 之前的镜像(旧 `@deepseek-ai/...` 包名和第二个包),既不发布也不构建,可安全忽略。
|
|
252
|
-
**`plugin-src/` is now explicitly legacy**: it holds a pre-0.13 mirror (old `@deepseek-ai/...` names and the second package); it is neither shipped nor built and is safe to ignore.
|
|
253
|
-
|
|
254
|
-
## [0.12.0] - 2026-10
|
|
255
|
-
|
|
256
|
-
### 变更 · Changed
|
|
257
|
-
- **移植到 DSH 0.2.0-rc.2 接口世代**:harness 的 settings 服务改成了「每个 loader 条目一个命名空间」(`SettingsForms`),旧的 `settingsNamespace` / `settingsScope` 接口在该世代**已不存在**。0.12.0 按当前世代重写宿主与面板;**面向旧 2.0.9 世代的构建(0.11.x 及更早)不再受支持**,并且**有意不提供向后兼容**——两代接口只能二选一。
|
|
258
|
-
**Ported to the DSH 0.2.0-rc.2 internal-API generation**: the harness settings service became "one namespace per loader entry" (`SettingsForms`) and the old `settingsNamespace` / `settingsScope` interfaces are gone from that generation. 0.12.0 rewrites both halves against it; builds targeting the older 2.0.9-era generation (0.11.x and earlier) are no longer supported, with no backward compatibility on purpose.
|
|
259
|
-
- **持久化改为一个私有状态文档**:提示词 / 托管技能 / 自定义命令 / MCP 服务器 / 壁纸与特效设置全部写进 `$DSH_HOME/switchblade/state.json`(默认 `~/.dsh/switchblade/state.json`),**原子写入**(临时文件 + rename),不再占用 harness 的 settings 命名空间;壁纸字节在 `$DSH_HOME/wallpapers/`,zip/目录安装的技能落在 `$DSH_HOME/skills/`(官方 filesystem 技能 provider 扫描并监听该根目录),对话导出在 `$DSH_HOME/armory-exports/`。
|
|
260
|
-
**Persistence is now one private state document**: prompts, managed skills, custom commands, MCP servers and wallpaper/effect settings all live in `$DSH_HOME/switchblade/state.json` (default `~/.dsh/switchblade/state.json`), written **atomically** (temp file + rename); wallpaper bytes go to `$DSH_HOME/wallpapers/`, zip/directory-installed skills land in `$DSH_HOME/skills/` (the root the official filesystem skill provider scans and watches), and conversation exports go to `$DSH_HOME/armory-exports/`.
|
|
261
|
-
- **面板 ↔ Host 改走插件自有的同源路由**:`GET/POST /api/armory/state`、`POST /api/armory/mcp/test`、`POST /api/armory/skills/zip`、`POST /api/switchblade-wallpaper/upload`、`GET /api/switchblade-wallpaper/image/<id>`,加上原有的 `/api/armory/*` 对话/统计路由。旧的 `api.settings.mutate/describe` 与 `ctx.settingsScope` 路径全部移除;技能目录仍通过 remote RPC `api.skills.list` 读取。
|
|
262
|
-
**Panel ↔ Host now uses the plugin's own same-origin routes**: `GET/POST /api/armory/state`, `POST /api/armory/mcp/test`, `POST /api/armory/skills/zip`, `POST /api/switchblade-wallpaper/upload`, `GET /api/switchblade-wallpaper/image/<id>`, plus the existing `/api/armory/*` conversation/stats routes. The old `api.settings.mutate/describe` and `ctx.settingsScope` paths are gone; the skill catalog still comes over remote RPC (`api.skills.list`).
|
|
263
|
-
- **提示词细粒度作用域**:全局(默认)/ 仅指定项目(按会话工作区目录名匹配)/ 仅指定会话 / 除指定项目外 / 除指定会话外。只有作用域匹配的提示词才返回正文,不匹配的 section 返回空串并被渲染阶段丢弃——不会泄漏到其他项目或会话。
|
|
264
|
-
**Fine-grained prompt scoping**: global (default) / only-project (matched by the session workspace directory name) / only-session / all-except-project / all-except-session. A scoped prompt returns its body only for matching agents; non-matching sections resolve to an empty string that the render step drops, so nothing leaks into other projects or sessions.
|
|
265
|
-
- **构建改为 esbuild**:`node scripts/build-lib.mjs` 直接产出发布包,**不需要 deepseek-harness checkout**(打包只用 esbuild)。产物为 `packages/switchblade/lib/{index,invariant}.js` 与 `packages/client-ui-switchblade/lib/{index,invariant,client}.js`;浏览器面板打成 harness module-loader bundle(`window.__ModuleLoader__.load({ id, factory })`)。`scripts/build-shipped.mjs <harness-checkout>` 仍在,但职责缩小为「从 monorepo checkout 拷出源码/产物」。
|
|
266
|
-
**Build is now esbuild**: `node scripts/build-lib.mjs` produces the shipped artifacts with **no deepseek-harness checkout needed** (esbuild alone does the bundling). Outputs: `packages/switchblade/lib/{index,invariant}.js` and `packages/client-ui-switchblade/lib/{index,invariant,client}.js`; the browser panel is emitted as a harness module-loader bundle (`window.__ModuleLoader__.load({ id, factory })`). `scripts/build-shipped.mjs <harness-checkout>` still exists but is now only "copy sources/artifacts out of a monorepo checkout".
|
|
267
|
-
- **安装器支持只装指定 profile**:`npx prompt-skill-armory --profile web`(可重复、可逗号分隔,`-p` 为简写),`uninstall --profile web` 只从该 profile 卸载;不带该参数时行为不变(装到全部 profile)。名字写错会直接报错并列出当前可用的 profile。
|
|
268
|
-
**Installer can target specific profiles**: `npx prompt-skill-armory --profile web` (repeatable, comma lists accepted, `-p` is the short form), and `uninstall --profile web` removes it from that profile only; without the flag the behaviour is unchanged (every profile). A misspelled name fails immediately with the list of available profiles.
|
|
269
|
-
|
|
270
|
-
### 修复 · Fixed
|
|
271
|
-
- **跨平台归档**:会话导出/导入依次尝试 `zip`/`unzip` → bsdtar(`tar`)→ PowerShell,不再是 Windows 专用的 `powershell.exe`。
|
|
272
|
-
**Cross-platform archives**: conversation export/import now tries `zip`/`unzip`, then bsdtar (`tar`), then PowerShell — no more Windows-only `powershell.exe`.
|
|
273
|
-
- **跨平台一键更新**:POSIX 上调 `npm`,仅在 Windows 上用 `npm.cmd`。
|
|
274
|
-
**Cross-platform one-click update**: calls `npm` on POSIX and `npm.cmd` only on Windows.
|
|
275
|
-
- **`dsh.client.inject` 列出真实存在的包**:`@deepseek-ai/dsh-api-remotes`、`@deepseek-ai/dsh-api-session-controller`、`@deepseek-ai/dsh-client-locale`、`@deepseek-ai/dsh-client-ui-settings`;面板的 cordis service inject 为 `['slots','locale','remote','remote.skills','sessions']`。
|
|
276
|
-
**`dsh.client.inject` now lists packages that actually exist**: `@deepseek-ai/dsh-api-remotes`, `@deepseek-ai/dsh-api-session-controller`, `@deepseek-ai/dsh-client-locale`, `@deepseek-ai/dsh-client-ui-settings`; the panel's cordis service inject is `['slots','locale','remote','remote.skills','sessions']`.
|
|
277
|
-
|
|
278
|
-
### 移除 · Removed
|
|
279
|
-
- **Agent 预设 / prompt profile 管理**:`@deepseek-ai/dsh-agent-presets` 包在该世代已不存在,`/armory-profile` 命令一并移除(面板自 0.11.0 起就没有该 tab)。
|
|
280
|
-
**Agent-preset / prompt-profile management**: the `@deepseek-ai/dsh-agent-presets` package does not exist in this generation, so `/armory-profile` is gone too (the panel had no such tab since 0.11.0).
|
|
281
|
-
- **旧类型镜像与 `plugin-src/` 的定位**:`plugin-src/` 明确标记为**遗留镜像,不是发布真相**——以 `packages/`(`lib/` + `src/`)为准。
|
|
282
|
-
**Legacy type mirrors and the role of `plugin-src/`**: `plugin-src/` is now clearly marked as a **legacy mirror, not the shipped truth** — `packages/` (`lib/` + `src/`) is authoritative.
|
|
283
|
-
|
|
284
|
-
### 命令 · Commands
|
|
285
|
-
- `/armory`、`/armory-enable`、`/armory-disable`、`/armory-install`、`/armory-uninstall`、`/armory-export`、`/armory-import`、`/armory-skill-dir`、`/armory-install-zip`、`/armory-state` —— 每个都保留 `/sw*` 旧别名。
|
|
286
|
-
`/armory`, `/armory-enable`, `/armory-disable`, `/armory-install`, `/armory-uninstall`, `/armory-export`, `/armory-import`, `/armory-skill-dir`, `/armory-install-zip`, `/armory-state` — each keeps a `/sw*` legacy alias.
|
|
287
|
-
|
|
288
|
-
### 验证 · Verified
|
|
289
|
-
- 在隔离的 `DSH_HOME=/tmp/armory-test` 上端到端验证(`dsh web --no-open --port 3099`):`/api/armory/state` 的 GET/POST 正常、`state.json` 落盘、壁纸上传+回读字节一致、zip 技能解压进 `$DSH_HOME/skills`、MCP 启动/停止会组合出 `@deepseek-ai/dsh-mcp-client` loader 条目、面板 bundle 出现在 boot manifest 中并能驱动状态路由(新增提示词/开关、技能启用/卸载),五种作用域的匹配逐项断言。
|
|
290
|
-
**Verified end-to-end** on an isolated `DSH_HOME=/tmp/armory-test` (`dsh web --no-open --port 3099`): `/api/armory/state` GET/POST, `state.json` written, wallpaper upload + read-back byte-identical, zip skill install extracted into `$DSH_HOME/skills`, MCP start/stop composing a `@deepseek-ai/dsh-mcp-client` loader entry, the panel bundle discovered in the boot manifest and driving the state routes (prompt add/toggle, skill enable/uninstall), and scope matching asserted for all five scope types.
|
|
291
|
-
|
|
292
|
-
## [0.11.0] - 2026-09
|
|
293
|
-
|
|
294
|
-
### 变更 · Changed
|
|
295
|
-
- **提示词作用域更易用(下拉选择 + 排除模式)**:
|
|
296
|
-
- 作用域改为 5 选项下拉:全局 / 仅指定项目 / 仅指定会话 / **除指定项目外** / **除指定会话外**。
|
|
297
|
-
- 目标不再手填:项目从真实工作区(cwd 目录名)下拉,会话从真实会话列表下拉(显示「标题 · 项目 · 短 id」),无需记 session id。
|
|
298
|
-
- 新增**排除模式**——覆盖「全局生效、只有某个项目/会话不要」这一最常见诉求,一个开关搞定,不必逐个勾选。
|
|
299
|
-
- 列表徽章同步显示:`仅项目:qc` / `除会话 abc12345 外`。
|
|
300
|
-
**Prompt scoping is now easier (dropdowns + exclude modes)**: a 5-option scope dropdown (global / only-project / only-session / all-except-project / all-except-session); project and session targets are picked from real data (workspace cwd names, session titles) instead of typing ids; exclude modes cover the common "global but not here" case in one step; list badges reflect it.
|
|
301
|
-
|
|
302
|
-
## [0.10.5] - 2026-09
|
|
303
|
-
|
|
304
|
-
### 修复 · Fixed
|
|
305
|
-
- **输入框下方提示样式停用/启用异常**:此前的实现用 JS 直接改写元素 inline style——停用时只删样式标签、残留的 inline 样式没有还原(所以「关不掉」),启用时又给统计条容器加了字号与 `display:inline-block`(所以布局被撑动)。改为**单一 CSS 样式标签驱动**:停用即删除标签,DOM 零残留、完全还原;样式只作用于统计条 label 文本(font/color),不再触碰 flex 容器布局。
|
|
306
|
-
**Composer stats-strip style toggle was broken**: the old implementation wrote inline styles via JS — disabling removed only the style tag, leaving inline styles behind (so it never reverted), and enabling added font-size / `display:inline-block` to the strip container (so the layout shifted). Now driven by a single CSS tag: disabling deletes the tag with zero DOM residue (fully restores), and styles apply only to the strip label text (font/color), never touching the flex container layout.
|
|
307
|
-
|
|
308
|
-
## [0.10.4] - 2026-09
|
|
309
|
-
|
|
310
|
-
### 修复 · Fixed
|
|
311
|
-
- **输入框下方提示样式真正生效**:该样式针对的是输入框下方的**会话统计 + token 用量条**(2.0.9 渲染为 `[data-composer-stats]` 容器,内含 TimePill/UsagePill,分隔符为 `·`)。CSS 锚定 `[data-composer-stats]` 及其 `_label`/`_pill`(哈希类名用属性选择器匹配),JS 分隔符匹配从旧版 `|` 扩展为 `·`/ `|`。
|
|
312
|
-
**Composer stats-strip hint style now works**: this style targets the session-stats + token-usage strip below the composer, which 2.0.9 renders as `[data-composer-stats]` (TimePill/UsagePill, `·` separators). CSS anchors on `[data-composer-stats]` and its `_label`/`_pill` hashed classes via attribute selectors; JS separator matching now covers `·` and `|`.
|
|
313
|
-
|
|
314
|
-
## [0.10.3] - 2026-09
|
|
315
|
-
|
|
316
|
-
### 修复 · Fixed
|
|
317
|
-
- **输入框提示样式精准适配**:2.0.9 的提示/占位文本渲染为 `[data-composer-placeholder]` 独立 div(不是 `input::placeholder`)。提示样式直接作用于该元素,渐变色补 `display:inline-block` 确保 `background-clip:text` 生效。另确认 2.0.9 已移除旧 dock StatsLine(`span[aria-hidden="|"]`)。
|
|
318
|
-
**Hint style precisely retargeted**: 2.0.9 renders the composer hint/placeholder as a `[data-composer-placeholder]` div (not `input::placeholder`). The style now targets that element, with `display:inline-block` so gradient `background-clip:text` renders. Also confirmed the old StatsLine dock (`span[aria-hidden="|"]`) is gone in 2.0.9.
|
|
319
|
-
|
|
320
|
-
## [0.10.2] - 2026-09
|
|
321
|
-
|
|
322
|
-
### 修复 · Fixed
|
|
323
|
-
- **面板报错 `cannot get property "remote.skills" without inject`**:2.0.9 的 cordis 要求 client 插件在 `inject` 里显式声明 `remote.skills` 子命名空间(与官方 ui-skill 一致),且 `skills.list` 的签名是 `({ sessionId }, signal)` 而非旧的 `{ request: ... }`。补齐 inject + 修正调用后,面板正常加载,之前保存的提示词/技能/MCP 数据全部恢复显示(数据一直在 settings.yaml,从未丢失)。
|
|
324
|
-
**Panel error `cannot get property "remote.skills" without inject`**: 2.0.9's cordis requires the client plugin to declare the `remote.skills` sub-namespace in `inject` (matching official ui-skill), and `skills.list` takes `({ sessionId }, signal)` not the old `{ request: ... }`. With the inject added and the call fixed, the panel loads and previously saved prompts/skills/MCP data is restored (it was always in settings.yaml).
|
|
325
|
-
- **输入框提示样式适配 2.0.9**:2.0.9 移除了旧的 `[data-decoration="hint"]` 行,提示改在输入框内(placeholder + claim hint)。提示样式选择器改到稳定的 `[data-composer-card]`(placeholder 与内嵌提示文本),颜色/字号/渐变照常生效。
|
|
326
|
-
**Hint style adapted to 2.0.9**: the old `[data-decoration="hint"]` row is gone in 2.0.9; hints now live inside the composer card (placeholder + inline claim hint). The style now targets `[data-composer-card]` placeholder and hint text, keeping color/size/gradient working.
|
|
327
|
-
|
|
328
|
-
## [0.10.1] - 2026-09
|
|
329
|
-
|
|
330
|
-
### 修复 · Fixed
|
|
331
|
-
- **面板加载报错 `Cannot read properties of undefined (reading 'settings')`**:DSH 2.0.9 把 client 端 settings 访问从 `connection.api.settings` 改成 `ctx.settingsScope`(命名空间绑定)+ `ctx.remote`(RPC)——插件还走旧的 `api.settings`,api 为 undefined 直接抛错,导致提示词/技能/MCP/壁纸面板全部加载失败。已迁移:读走 `settingsScope.getSnapshot()`,写走 `scope.mutate(ops)`,技能走 `remote.skills.list({request})`。面板恢复后,之前安装的提示词/技能/MCP 数据依然在(settings.yaml 从未丢失)。
|
|
332
|
-
**Panel load error `Cannot read properties of undefined (reading 'settings')`**: DSH 2.0.9 moved client settings access from `connection.api.settings` to `ctx.settingsScope` (namespace-bound) + `ctx.remote` (RPC); the plugin still used the old `api.settings`, so api was undefined and the whole panel failed. Migrated: reads via `settingsScope.getSnapshot()`, writes via `scope.mutate(ops)`, skills via `remote.skills.list({request})`. Installed prompts/skills/MCP data was never lost (still in settings.yaml).
|
|
333
|
-
- **壁纸只覆盖对话区**:DSH 2.0.9 桌面端是 `.dshDesktopFrame` 三栏 grid(sidebar/conversation/rightbar),背景层挂在 body 下 z-index 为负被 surface 实色背景挡住,且 `data-dsh-desktop-material="off"` 的侧边栏用 `--dsw-alias-bg-layer-1` 实色。现在背景层 z-index 提到 0、`#root` 抬到 z-index 1、所有桌面 surface 背景强制透明(含 `--dsw-alias-bg-layer-1`),壁纸覆盖整个窗口。
|
|
334
|
-
**Wallpaper only covered the chat area**: 2.0.9 desktop renders a `.dshDesktopFrame` three-column grid; the negative-z body backdrop was hidden behind opaque surface fills (sidebar uses `--dsw-alias-bg-layer-1` at material=off). Backdrop is now z-index 0 with `#root` lifted above it and every desktop surface forced transparent, so the wallpaper covers the whole window.
|
|
335
|
-
|
|
336
|
-
## [0.10.0] - 2026-09
|
|
337
|
-
|
|
338
|
-
### 修复 · Fixed
|
|
339
|
-
- **DSH Desktop 2.0.9 恢复模式(第二次根治)**:修复 cordis 属性访问后,客户端面板仍报 `client-modules: require("@deepseek-ai/dsh-client-runtime/client") missed the module table`——2.0.9 的浏览器模块表不再把 `dsh-client-runtime/client` 作为可用种子,而插件的 snapshot store 从它导入 `createSnapshotStore`,构建产物残留运行时 require 导致加载失败。改为**内联本地 snapshot store** 并移除对 runtime 的运行时依赖(`ClientContext`/会话列表改用本地接口),2.0.9 下实测完整启动。
|
|
340
|
-
**DSH Desktop 2.0.9 recovery mode (second root cause)**: after the cordis fix, the panel still failed with `client-modules: require("@deepseek-ai/dsh-client-runtime/client") missed the module table` — 2.0.9's browser module table no longer seeds `dsh-client-runtime/client`, but the plugin imported `createSnapshotStore` from it, leaving a runtime require in the bundle. Now inlines a local snapshot store and drops the runtime dependency (local `ClientContext`/session interfaces); verified a full boot on 2.0.9.
|
|
341
|
-
- **提示词作用域(精细化差分)**:每个提示词可选 全局 / 指定项目(cwd 目录名)/ 指定会话(session id),Host 按 agent 的 cwd/sessionId 匹配注入,零全局污染。
|
|
342
|
-
**Prompt scoping**: each prompt can target global / a project / a session with zero leakage.
|
|
343
|
-
|
|
344
|
-
## [0.9.9] - 2026-09
|
|
345
|
-
|
|
346
|
-
### 修复 · Fixed
|
|
347
|
-
- **DSH Desktop 2.0.9 恢复模式(根治)**:2.0.9 的 cordis 禁止对未注入的服务做属性访问。插件里 `fiber.ctx.switchblade` 属性访问在加载时抛 `cannot get property "switchblade" without inject`,导致整个客户端启动失败进恢复模式。改为 `ctx.get('switchblade')` 惰性解析,并在 Switchblade 服务的 `static inject` 补上 `commands`;配合上一版对 `cordis.patch.yml` 的块级去重,2.0.9 下已通过 `dsh --profile desktop` 实测完整启动。
|
|
348
|
-
**DSH Desktop 2.0.9 recovery mode (root cause)**: 2.0.9's cordis forbids property access to non-injected services. The plugin's `fiber.ctx.switchblade` property access threw `cannot get property "switchblade" without inject` at load, failing startup into recovery mode. Switched to lazy `ctx.get('switchblade')` and added `commands` to `static inject`; verified a full boot via `dsh --profile desktop` on 2.0.9.
|
|
349
|
-
- **提示词作用域(精细化差分)**:每个提示词可选 全局 / 指定项目(cwd 目录名)/ 指定会话(session id)。Host 通过 systemPrompt section 的 text 函数按当前 agent 的 cwd/sessionId 匹配,不匹配返回空串(渲染时自动过滤)——零全局污染。
|
|
350
|
-
**Prompt scoping (fine-grained diff)**: each prompt can target global / a project (cwd basename) / a session (id); non-matching agents get an empty section that render filters out.
|
|
351
|
-
|
|
352
|
-
## [0.9.8] - 2026-08
|
|
353
|
-
|
|
354
|
-
### 修复 · Fixed
|
|
355
|
-
- **DSH Desktop 2.0.9 恢复模式**:安装器对 `cordis.patch.yml` 的行级去重会把注释行和裸 `- insert:` 当用户条目保留,每次安装/更新都叠加一段残缺 insert 块;2.0.9 的 patch 解析器拒绝无 body 的 insert 导致启动崩溃。改为**块级去重**(命中任一 Armory 管理行即整块清理),并重置已有 profile 的 patch 文件。
|
|
356
|
-
**DSH Desktop 2.0.9 recovery mode**: the installer's line-based dedup kept the comment/header and bare `- insert:` lines as "user entries", appending a truncated insert block on every install/update; 2.0.9's patch parser rejects body-less inserts and crashed at boot. Now block-level (any Armory-managed line clears the whole block), and existing profile patch files are reset.
|
|
357
|
-
- **技能名含点号无法注册**:DSH 技能名必须是 kebab-case(`gpt-5.6-sol` 被拒)。安装/注册时自动规范化名字(点号转连字符)。
|
|
358
|
-
Skills with dots failed to register: DSH requires kebab-case names. Names are now normalized on install/register.
|
|
359
|
-
|
|
360
|
-
### 新增 · Added
|
|
361
|
-
- **提示词作用域(精细化差分)**:每个提示词可选 全局 / 指定项目(按 cwd 目录名)/ 指定会话(session id)。Host 通过 systemPrompt section 的 text 函数按当前 agent 的 cwd/sessionId 匹配,不匹配返回空串(渲染时自动过滤)——零全局污染,其他项目/会话完全不受影响。
|
|
362
|
-
**Prompt scoping (fine-grained diff)**: each prompt can target global / a specific project (cwd basename) / a specific session (id). The Host matches via a text provider against the assembling agent's cwd/sessionId and returns '' otherwise (filtered at render) — no global leakage.
|
|
363
|
-
|
|
364
|
-
## [0.9.7] - 2026-08
|
|
365
|
-
|
|
366
|
-
### 修复 · Fixed
|
|
367
|
-
- 对话删除与工作区下拉「没反应」:导出/导入/删除的异步处理缺少 try/finally,一旦下载抛错 `chatBusy` 卡死为 true,整个工具栏被禁用。现在所有处理统一 try/finally 复位,并逐会话容错删除、同步清理 `workspace.json` 里的 sessionId 引用(防止幽灵会话复活)。
|
|
368
|
-
Delete and the workspace selector appeared dead: the async handlers lacked try/finally, so a failed download left `chatBusy` stuck true and disabled the whole toolbar. Handlers now always reset via finally; deletion is per-session resilient and scrubs sessionIds from `workspace.json` (no ghost-session resurrection).
|
|
369
|
-
- 工作区名过长溢出面板:会话列表徽章加最大宽度 + 省略号,整体导出下拉限宽 220px。
|
|
370
|
-
Long workspace names no longer overflow: the session badge gets max-width + ellipsis and the export selector is capped at 220px.
|
|
371
|
-
- 折线图 Token 轴改为对数刻度:输入 Token 通常比输出大一个数量级,线性轴会把输出线压成贴地;对数轴让输入/输出/缓存的形状都清晰可读(步骤轴保持线性)。
|
|
372
|
-
The chart token axis now uses a log scale: input tokens are typically an order of magnitude above output, so a linear axis flattened the output line into the baseline; log scale keeps every series readable (the steps axis stays linear).
|
|
373
|
-
|
|
374
|
-
## [0.9.6] - 2026-08
|
|
375
|
-
|
|
376
|
-
### 修复 · Fixed
|
|
377
|
-
- 折线图输入 Token 线不可见:右轴此前只用输出 Token 缩放,输入 Token 通常大一个数量级,Y 坐标算出负值被画出视口顶部。现在输入/输出/缓存读/缓存写全部参与右轴缩放,并补上输入 Token 的数据点、数值标签与圆整刻度。
|
|
378
|
-
The input-token line was invisible: the right axis was scaled on output tokens alone, and input tokens (typically an order of magnitude larger) produced negative Y coordinates above the viewport. All token series now share the axis scale, and input-token dots, value labels and rounded ticks are rendered.
|
|
379
|
-
|
|
380
|
-
## [0.9.5] - 2026-08
|
|
381
|
-
|
|
382
|
-
### 新增 · Added
|
|
383
|
-
- 使用统计折线图实时刷新:统计标签页打开时每 30 秒自动轮询当前范围(今天 / 7天 / 30天 / 全部),并在标题旁显示「上次更新」时间;切换范围立即拉取最新数据。
|
|
384
|
-
Usage-stats chart now live-refreshes: while the stats tab is open it polls the active range (today / 7d / 30d / all) every 30 seconds, shows the last-updated time next to the title, and fetches instantly when switching ranges.
|
|
385
|
-
- 所有范围的按日折线都补全到今天(缺的日期补 0),7 天 / 30 天 / 全部的趋势线尾巴始终顶到最新使用状态;Host 端加 4 秒 TTL 缓存避免轮询反复读盘。
|
|
386
|
-
Daily trend lines for every range are now padded through today (missing days filled with 0), so the 7d / 30d / all lines always reach the latest usage; the Host adds a 4s TTL cache so polling does not re-read the projcache every tick.
|
|
387
|
-
|
|
388
|
-
## [0.9.4] - 2026-08
|
|
389
|
-
|
|
390
|
-
### 修复 · Fixed
|
|
391
|
-
- 「今天」统计改用会话的**最后活动时间**(`lastPromptAt`,回退到创建时间)做过滤与按小时分桶:此前按创建时间过滤会把「前几天创建、今天仍在使用」的会话整个跳过,导致今天折线图空白。同时按日统计改为本地时区日期(不再用 UTC `toISOString` 产生跨日错位)。
|
|
392
|
-
The "today" stats now use each session's **last activity time** (`lastPromptAt`, falling back to creation time) for filtering and hourly bucketing: previously sessions created earlier but still used today were skipped entirely, leaving the today chart blank. Daily bucketing also switched to local-timezone dates (no more UTC shift).
|
|
393
|
-
|
|
394
|
-
## [0.9.3] - 2026-08
|
|
395
|
-
|
|
396
|
-
### 新增 · Added
|
|
397
|
-
- 对话导出支持「整个项目工作区」:下拉选择项目后一键导出该项目下的全部对话。
|
|
398
|
-
Conversation export now supports whole-project workspaces: pick a project and export every conversation under it in one click.
|
|
399
|
-
- 导出包携带工作区注册表(title/path)与每个会话的 identity(createdAt/cwd/title),导入后合并写回 `workspace.json` 与 `session_projcache.json`,项目工作区名不再变成「未命名」,尽量与导出端一致。
|
|
400
|
-
The export zip now carries the workspace registry (title/path) plus per-session identity (createdAt/cwd/title); import merges them back into `workspace.json` and `session_projcache.json`, so project workspace names survive the move instead of falling back to "unnamed".
|
|
401
|
-
|
|
402
|
-
## [0.9.2] - 2026-08
|
|
403
|
-
|
|
404
|
-
### 修复 · Fixed
|
|
405
|
-
- 对话导出仅包含勾选的会话(不再打包全局附件/工作区,避免泄露其他内容)。
|
|
406
|
-
Conversation export now includes only the selected sessions (global attachments/workspace are no longer bundled, preventing leakage).
|
|
407
|
-
- 更新提示并入标题版本号旁(移除独立横幅)。
|
|
408
|
-
The update prompt now sits next to the version badge in the header (standalone banner removed).
|
|
409
|
-
|
|
410
|
-
## [0.9.1] - 2026-08
|
|
411
|
-
|
|
412
|
-
### 修复 · Fixed
|
|
413
|
-
- 一键更新失败:npm 包 bin 名实际为 `armory`,旧命令 `npx prompt-skill-armory` 找不到同名命令。新增 `prompt-skill-armory` bin 别名,Host 更新改用 `npm exec --package=prompt-skill-armory -- armory`(shell 模式 + 更长超时),并把具体错误信息回显到面板。
|
|
414
|
-
Fixed one-click update: the npm bin is `armory`, so `npx prompt-skill-armory` failed. Added a `prompt-skill-armory` bin alias, switched the Host update to `npm exec --package=prompt-skill-armory -- armory` (shell mode + longer timeout), and surface the real error in the panel.
|
|
415
|
-
|
|
416
|
-
## [0.9.0] - 2026-08
|
|
417
|
-
|
|
418
|
-
### 变更 · Changed
|
|
419
|
-
- **移除 Agent 预设 tab** 及相关 UI/状态/注入。
|
|
420
|
-
Removed the Agent Presets tab and related UI/state/injection.
|
|
421
|
-
- **使用统计全面升级**(对齐 cc-switch):时间范围筛选(全部/30天/7天/今天)、输入/输出/缓存读/缓存写 Token、缓存命中率、成本估算、请求日志(时间/项目/模型/输入输出/缓存/成本/用时/首字/状态)、Provider(项目)统计、模型统计、SVG 双轴趋势图,今天按 24 小时分段。
|
|
422
|
-
Usage stats overhaul (cc-switch style): range filter, input/output/cache tokens, cache-hit rate, cost estimate, request log, provider/project stats, model stats, SVG dual-axis trend chart (24h split for today).
|
|
423
|
-
|
|
424
|
-
## [0.8.3] - 2026-08
|
|
425
|
-
|
|
426
|
-
### 新增 · Added
|
|
427
|
-
- **一键更新**:面板自动检测 npm 最新版本,发现新版本时顶部横幅提示并可一键更新(Host 端运行官方安装器原地重装)。
|
|
428
|
-
**One-click update**: the panel auto-checks the npm registry; when a newer version exists it shows a banner with a one-click update (the Host re-runs the official installer in place).
|
|
429
|
-
- 删除/导入对话后同步刷新 DSH 官方会话列表。
|
|
430
|
-
The official DSH conversation list now refreshes after delete/import.
|
|
431
|
-
|
|
432
|
-
## [0.8.2] - 2026-08
|
|
433
|
-
|
|
434
|
-
### 新增 · Added
|
|
435
|
-
- **真实删除对话**:对话 tab 新增「删除选中」(带确认),删除会话目录并从 DSH 会话索引移除。
|
|
436
|
-
**Real conversation delete**: a "delete selected" action (with confirm) in the Chat tab that removes the session directory and its index entry.
|
|
437
|
-
|
|
438
|
-
## [0.8.1] - 2026-08
|
|
439
|
-
|
|
440
|
-
### 新增 · Added
|
|
441
|
-
- **卸载命令**:`npx prompt-skill-armory uninstall` 移除插件(包、bundle、面板挂载)并清理壁纸/导出目录。
|
|
442
|
-
**Uninstall command**: `npx prompt-skill-armory uninstall` removes the plugin (packages, bundle, panel mount) and cleans up wallpaper/export dirs.
|
|
443
|
-
- README 增加 LINUX DO 友情链接。
|
|
444
|
-
Added a LINUX DO friend link to the README.
|
|
445
|
-
|
|
446
|
-
## [0.8.0] - 2026-08
|
|
447
|
-
|
|
448
|
-
### 新增 · Added
|
|
449
|
-
- **对话导入 / 导出**:勾选多个会话导出为 zip(含附件与工作区),另一台机器导入即可还原;新增「对话」tab,显示对话标题、项目与时间。
|
|
450
|
-
**Conversation import/export**: export selected sessions as a zip (with attachments & workspace) and restore them on another machine; new "Chat" tab showing title, project and time.
|
|
451
|
-
- 会话标题回退:读取 DSH 会话缓存标题,缺失时从会话日志取第一条用户消息(与官方默认标题一致)。
|
|
452
|
-
Title fallback: use the DSH session-cache title, falling back to the first user message from the log (matching the official default-title rule).
|
|
453
|
-
|
|
454
|
-
## [0.7.2] - 2026-08
|
|
455
|
-
|
|
456
|
-
### 变更 · Changed
|
|
457
|
-
- 插件展示名更名 **Armory**(面板标题、设置导航、README 定位为 DeepSeek Harness 社区插件/管理中枢,覆盖提示词/技能/MCP/壁纸/预设);npm 与仓库名保持 `prompt-skill-armory`。
|
|
458
|
-
Renamed the display name to **Armory** (panel title, nav, README) and positioned it as a DeepSeek Harness community plugin / control center (prompts, skills, MCP, wallpaper, presets); npm & repo stay `prompt-skill-armory`.
|
|
459
|
-
|
|
460
|
-
## [0.7.1] - 2026-08
|
|
461
|
-
|
|
462
|
-
### 修复 · Fixed
|
|
463
|
-
- 渐变色方案:正确解析渐变 id → CSS(修复除「纯色」外渐变文字未生效)。
|
|
464
|
-
Gradient presets now resolve the preset id to its CSS (fixes gradient text not applying).
|
|
465
|
-
|
|
466
|
-
## [0.7.0] - 2026-08
|
|
467
|
-
|
|
468
|
-
### 新增 · Added
|
|
469
|
-
- 可配置全局壁纸:本地上传图片/视频(字节存盘 `~/.dsh/wallpapers`,settings 只存 id,不撑爆配置文档)或图片 URL;透明度 / 遮罩 / 玻璃透明度 / 玻璃模糊 / 壁纸模糊 / 铺法可调。
|
|
470
|
-
Configurable global wallpaper: local image/video upload (bytes on disk, id-only in settings) or an image URL; adjustable opacity / scrim / glass / blur / fit.
|
|
471
|
-
- 桌面客户端与网页端分别设置壁纸与样式(`backgroundDesktop` / `backgroundWeb` 分字段)。
|
|
472
|
-
Per-surface wallpaper & styling for desktop vs web.
|
|
473
|
-
- 输入栏下方提示行(含 dock 统计行)样式:启用 / 颜色 / 字号 / 渐变色预设(极光/火焰/晴空/霓虹/海洋/晚霞)。
|
|
474
|
-
Composer hint-line (incl. dock stats row) styling: enable / color / size / gradient presets.
|
|
475
|
-
- Wallpaper tab 移至第四列并更名 Wallpaper;启用改为醒目滑动开关。
|
|
476
|
-
Wallpaper tab moved to 4th column and renamed Wallpaper; a prominent enable switch.
|
|
477
|
-
|
|
478
|
-
## [0.5.6] - 2026-08
|
|
479
|
-
|
|
480
|
-
### 变更 · Changed
|
|
481
|
-
- 三个 tab 改为上下布局(操作区在上、列表在下、列表 flex 自适应),三个 tab 高度一致,消除底部留白与溢出。
|
|
482
|
-
Tabs switched to a vertical layout (form on top, list below, list flex-adaptive) so all three tabs share one height — no bottom whitespace or overflow.
|
|
483
|
-
- 版本徽章同步到 0.5.6。Version badge bumped to 0.5.6.
|
|
484
|
-
|
|
485
|
-
## [0.5.5] - 2026-08
|
|
486
|
-
|
|
487
|
-
### 修复
|
|
488
|
-
- 重新构建 client bundle,让发布的 `lib/client.js` 携带当前版本徽章(`v0.5.5`)——之前只改源码版本号导致已发布 bundle 过期。
|
|
489
|
-
|
|
490
|
-
## [0.5.4] - 2026-08
|
|
491
|
-
|
|
492
|
-
### 修复
|
|
493
|
-
- Profile 的 `cordis.patch.yml` 现在是纯顶层 `- insert:` 列表(之前的 `[]` + insert 形式是非法 YAML——“document separator expected”,会让 desktop 客户端进入恢复模式)。
|
|
494
|
-
|
|
495
|
-
## [0.5.3] - 2026-08
|
|
496
|
-
|
|
497
|
-
### 修复
|
|
498
|
-
- 安装器幂等地重写格式错误的 `cordis.patch.yml`(旧安装器产物)为干净格式。
|
|
499
|
-
|
|
500
|
-
## [0.5.2] - 2026-08
|
|
501
|
-
|
|
502
|
-
### 修复
|
|
503
|
-
- 安装器现在**始终确保 desktop profile 存在**(客户端默认用 `desktop` profile)并装好插件——新机器之前只有 `web` profile,客户端没有面板。
|
|
504
|
-
|
|
505
|
-
## [0.5.1] - 2026-08
|
|
506
|
-
|
|
507
|
-
### 修复
|
|
508
|
-
- 安装器在新机器上同时创建 `web` 和 `desktop` 两个 profile。
|
|
509
|
-
|
|
510
|
-
## [0.5.0] - 2026-08
|
|
511
|
-
|
|
512
|
-
### 新增
|
|
513
|
-
- **DSH Desktop 客户端支持**:面板同时出现在官方 `dsh web` 和 DSH Desktop 客户端。安装器把 `ui-switchblade` 挂进每个 profile 的 `cordis.patch.yml`(已验证的正确位置——不是 web-app patch,那会重复挂载崩溃),并把两个插件包装进所有 profile。
|
|
514
|
-
|
|
515
|
-
### 修复
|
|
516
|
-
- Profile 的 `cordis.patch.yml` 以合法 YAML 写入(`[]`,绝不是带引号的 `"[]"`——那会破坏 desktop 客户端的恢复模式)。
|
|
517
|
-
- 安装器每个 profile 只挂一次客户端面板(去重)。
|
|
518
|
-
|
|
519
|
-
## [0.4.7] - 2026-08
|
|
520
|
-
|
|
521
|
-
### 修复
|
|
522
|
-
- 重新构建 client bundle,让发布的 `lib/client.js` 携带 Prompt•Skill-Armory 名称和当前版本徽章(只改源码导致已发布 bundle 过期)。
|
|
523
|
-
|
|
524
|
-
## [0.4.6] - 2026-08
|
|
525
|
-
|
|
526
|
-
### 变更
|
|
527
|
-
- 面板 + 侧边栏名称 **Prompt•Skill-Armory**(圆点分隔符),Prompt 与 Skill 共享同一强调色。版本徽章跟随发布版本。
|
|
528
|
-
|
|
529
|
-
## [0.4.5] - 2026-08
|
|
530
|
-
|
|
531
|
-
### 变更
|
|
532
|
-
- 面板和侧边栏名称现为 **Prompt•Skill-Armory**;Prompt 与 Skill 共享强调色。
|
|
533
|
-
- 安装器自动挂载客户端面板(cordis.patch.yml 的 ui-switchblade 行),面向 desktop / web profile。
|
|
534
|
-
- 安装器体检:settings.yaml 超过客户端 4MB 上限时告警(陈旧的 pendingZip 残留)。
|
|
535
|
-
|
|
536
|
-
## [0.4.4] - 2026-08
|
|
537
|
-
|
|
538
|
-
### 修复
|
|
539
|
-
- 安装器覆盖过期的符号链接/junction(先 rmSync 再复制),并安装进每个 profile(web + desktop)。
|
|
540
|
-
- settings 膨胀(5MB 陈旧的 zip base64)不再卡死 desktop 客户端。
|
|
541
|
-
|
|
542
|
-
## [0.4.1] - 2026-08
|
|
543
|
-
|
|
544
|
-
### 变更
|
|
545
|
-
- 统一命名为 **Prompt-SkillArmory**:CLI 命令现在是 `/armory-*`(`/armory`、`/armory-enable`、`/armory-skill-dir`、`/armory-install-zip`…),保留旧 `/sw-*` 别名以兼容。
|
|
546
|
-
|
|
547
|
-
## [0.4.0] - 2026-08
|
|
548
|
-
|
|
549
|
-
### 变更
|
|
550
|
-
- 技能 tab 现在是所有技能的唯一入口:面板安装的(managed)和本地扫描的合并进一个列表,每张卡片带调用提示(`/name`)和完整管理(增/改/开关/卸载/收养)。
|
|
551
|
-
- 移除单独的 "Local skills" tab 和 web zip 上传按钮(CLI 的 `/sw-install-zip` / `/sw-skill-dir` 命令仍是 zip/dir 安装路径)。
|
|
552
|
-
- 技能 tab 增加了 CLI 命令参考框。
|
|
553
|
-
- 面板头部版本徽章更清晰。
|
|
554
|
-
|
|
555
|
-
## [0.3.1] - 2026-08
|
|
556
|
-
|
|
557
|
-
### 修复
|
|
558
|
-
- 移除 web 面板的 zip-queue 路径(`pendingZip` settings 字段 + `handlePendingZip`),它死锁了 settings/api 通道、让整个 UI 空白。稳定的提示词 + 技能流程恢复;zip 技能经 `/sw-install-zip` CLI 命令安装(直接 Host 调用,不走 settings 往返)。
|
|
559
|
-
|
|
560
|
-
## [0.3.0] - 2026-08
|
|
561
|
-
|
|
562
|
-
### 修复
|
|
563
|
-
- **提示词现在真正生效。** 根因链:包 `main` 指向 `lib/types/index.js`(tsc 原始产物),loader 无法识别为插件——插件从未挂载。把 `main` 恢复为 `lib/index.js`(tsdown bundle),并在 `static inject` 声明 `skills` / `systemPrompt`,服务才能解析它们(`/sw` 之前报 "cannot get property skills without inject")。提示词经 `ctx.systemPrompt.section` 全局注入;技能经 `ctx.skills.register` 注册。
|
|
564
|
-
|
|
565
|
-
## [0.2.0] - 2026-08
|
|
566
|
-
|
|
567
|
-
### 新增
|
|
568
|
-
- 提示词编辑:改已存提示词的名称/描述/内容。
|
|
569
|
-
- 技能编辑:改已装技能的名称/描述/内容。
|
|
570
|
-
- 本地技能扫描:第 4 个 tab 列出本地扫描的技能,带"收养"操作。
|
|
571
|
-
- 设置侧边栏 Prompt-SkillArmory 导航的书图标。
|
|
572
|
-
- Tab 计数加载中显示 `…`(不再误导性显示 `0`)。
|
|
573
|
-
|
|
574
|
-
### 变更
|
|
575
|
-
- 面板改名为 **Prompt-SkillArmory**,配打开的书形图标。
|
|
576
|
-
- 布局改为设置对话框固定宽度内的 4 个 tab:提示词 / 技能 / Agent 预设 / 本地技能。
|
|
577
|
-
- 技能 tab 只管理面板安装的技能;本地技能 tab 只列本地扫描的。
|
|
578
|
-
- Tab 和头部标签不再强制大写。
|
|
579
|
-
- Host 端提示词/技能对账全程受保护(settings 提交路径无死锁;修好 `signal timed out`)。
|
|
580
|
-
|
|
581
|
-
## [0.1.0] - 2026-08
|
|
582
|
-
|
|
583
|
-
### 新增
|
|
584
|
-
- 首个发布:CCswitch 风格的提示词、技能、预设管理器。
|
|
585
|
-
- 提示词:增 / 启用 / 停用 / 设默认 / 删除;全局注入系统提示词。
|
|
586
|
-
- 技能:从本地 `.md` 或手动输入安装;启用 / 停用 / 卸载。
|
|
587
|
-
- 预设:浏览 agent-preset 名册,设默认。
|
|
588
|
-
- 中英双语 UI。
|
|
589
|
-
- 每个 tab 内搜索 + 滚动。
|