dsh-armory 2.4.1 → 2.4.3
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 +25 -5
- package/README.md +28 -9
- package/lib/expert-market.js +121 -6
- package/lib/whats-new-en.js +28 -0
- package/lib/whats-new.js +34 -0
- package/package.json +1 -1
package/README.en.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **The all-in-one control board for DeepSeek Harness**: MCP servers · skills · experts · plugins · tool-usage ledger · four markets — browse, search, install and summon in one place.
|
|
6
6
|
> Forked from [Imzl-zl/dsh-mcp-manager-ui](https://github.com/Imzl-zl/dsh-mcp-manager-ui) (MIT) and extended into a full armory.
|
|
7
7
|
>
|
|
8
|
-
> **New in v2.4.
|
|
8
|
+
> **New in v2.4.2**: documentation release — the README (both languages) now matches what actually ships: the three entry seats with six modes, how to hide the floating button, and the v2.4.1 SkillHub detail fixes. The runtime code is byte-identical to v2.4.1. See the [changelog](.github/release-notes/v2.4.2.md).
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
11
|
<a href="https://github.com/2026heshao/dsh-armory/stargazers"><img src="https://img.shields.io/github/stars/2026heshao/dsh-armory?style=social" alt="stars"></a>
|
|
@@ -26,7 +26,7 @@ dsh plugin --profile web add dsh-armory
|
|
|
26
26
|
dsh plugin --profile web add github:2026heshao/dsh-armory
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
Restart DSH, then open **
|
|
29
|
+
Restart DSH, then open **Big Fish Armory** from the global panel list at the top of the sidebar (next to "Plugins") — or use the floating button bottom-right, or the sidebar bottom entry. Desktop users on the `desktop` profile: swap `--profile web` for `--profile desktop`.
|
|
30
30
|
|
|
31
31
|
## What it solves
|
|
32
32
|
|
|
@@ -35,6 +35,9 @@ Restart DSH, then open **Skills · MCP · Experts** from the global panel list a
|
|
|
35
35
|
| MCP config means hand-editing YAML with no feedback on whether it connects | Visual panel: status, tool schemas, enable/disable, reconnect — global & per-project scopes, project changes apply to live sessions instantly |
|
|
36
36
|
| Installing skills means hunting for `SKILL.md` repos everywhere | **Direct markets**: SkillHub (190k+ skills), WorkBuddy connectors (316) — search, filter, one-click install with per-file sha256 verification |
|
|
37
37
|
| You install a skill from the market, then cannot find it on the board or tell which one is new | **Recognisable installs**: cards show "installed …" with a 7-day highlight and relative time; the filter bar lays skills out newest-first as a "recently installed" timeline; when the board name differs from the market name, the original is shown |
|
|
38
|
+
| The list card shows a summary, but opening the detail makes it blank and the title falls back to the slug | **Details read the right fields**: SkillHub puts the name and summary under the response's `skill` object (`displayName` / `summary_zh`); empty values from the detail endpoint never overwrite what is already on screen, and the list summary shows while loading |
|
|
39
|
+
| The detail's "homepage" opens `api.skillhub.cn` — a JSON endpoint a browser cannot render (405) | **Links go where browsers can go**: API URLs are rewritten to the public page `https://skillhub.cn/<namespace>/<slug>`, and the button is not rendered at all when there is no browsable page |
|
|
40
|
+
| The floating button sits on top of board content and offers no way to close it | **You own the entries**: right-click or long-press the button to hide it (with a hint on how to reopen), it steps aside while the board occupies the centre column, and the six entry modes guarantee you are never left with no way in |
|
|
38
41
|
| Every MCP's tool descriptions eat context tokens; zero-use tools sit there for free | **Tool Tailor**: scans local session logs for per-tool call counts / errors / latency, plus a skill-level usage ledger; prune dead tools with one click |
|
|
39
42
|
| Migrating from Claude/Cursor/VS Code means copying config by hand | Detects local configs from 11 clients and imports them with a preview |
|
|
40
43
|
| OAuth-protected or key-protected servers and plugins just fail, with no hint why | **Plugin market** (the DSH community list) with per-entry installability, **one-click MCP OAuth** (RFC 9728 → 8414 → 7591 → 7636 PKCE → 8707, three callback fallbacks ending at "paste a token"), and a **credential prompt before install** that fills `${...}` placeholders so the server works on first connect |
|
|
@@ -105,13 +108,14 @@ Experts (WorkBuddy expert center, 429 experts / 15 industries; category filter +
|
|
|
105
108
|
- Filter by transport (HTTP/stdio) and status, search by name/command/URL
|
|
106
109
|
- Enable, disable, reconnect, add, edit, remove; reveal masked credentials temporarily with the eye button and copy with one click
|
|
107
110
|
- **Global + project scopes**: global servers live in the Web profile and are available to every project; project servers live in that project's `.dsh/mcp.json` and are visible only to its sessions. A project can also hide any global MCP
|
|
108
|
-
- **
|
|
111
|
+
- **Three entry seats, six modes**: the **Big Fish Armory** row in the global panel list at the top of the sidebar (the host's own mechanism, next to "Plugins"), the draggable floating button (position remembered) and the sidebar bottom entry all open the same panel. The "Entries" menu in the panel header switches between six combinations (two / one / three seats); **all three can never be off**, and the floating button cannot be hidden while it is your only entry (since 2.4.1 you can also right-click or long-press the button itself to hide it)
|
|
109
112
|
- **WB Market (direct installs)**: a third board tab with two markets in one place —
|
|
110
113
|
- **Connectors (MCP)**: reads the official WorkBuddy distribution ZIP (`static.workbuddy.cn`, the same source the WorkBuddy desktop app uses) on demand — 316 connectors, 242 installable (mostly streamable-http), while 74 CLI-based or WorkBuddy-token-dependent ones are honestly labeled "view only" with the reason. Installing = merging the connector's `mcpServers` into your MCP config through the same pipeline as "Import JSON" (admission, duplicate skip, entry-id reservation), in either global or project scope. The ZIP is ETag-cached under `~/.dsh/wb-market/` and decompressed with Node's built-in zlib — **zero new runtime dependencies**
|
|
111
114
|
- **Skills (SkillHub)**: reads the public SkillHub API (`api.skillhub.cn`, 190k+ skills) with keyword search, four sort orders, and pagination; details include publisher verification and security-scan status. Installing = downloading file-by-file, verifying each against the manifest's sha256, and writing into `~/.agents/skills/` (the same discovery scope as the official skill subsystem) — effective immediately. Installed skills show an "installed" badge, support one-click uninstall, and reinstalling updates them. After an install or uninstall the **Skill** tab's count badge and board list realign with the new set immediately — no tab switch or panel reopen needed. Downloads sorting is now done **within the current page** (the upstream `sortBy=downloads` hangs), while the other sorts still go remote; each request gives up after 15s and reports a localized error
|
|
112
115
|
- Skills belong to their respective authors. Both upstreams are third-party interfaces whose fields may change; the panel carries a persistent note saying so
|
|
113
116
|
- **Experts (direct, 1.9.0)** — a dedicated board tab (the sidebar entry is renamed **Skills · MCP · Experts**):
|
|
114
117
|
- **Directory**: reads the official WorkBuddy expert center distribution (`expert_center.json`, 429 experts / 15 industries, ETag-cached under `~/.dsh/wb-market/experts/`) with category filter, keyword search, and a detail dialog (persona, bundled skills, sample prompts) before you summon
|
|
118
|
+
- **Where the persona comes from (2.4.3)**: detail and summon resolve the persona in this order — local override, local WorkBuddy cache (`~/.workbuddy/plugins/cache/experts/<plugin>/<version>/agents/`), public distribution URL, then a stand-in. Roughly four in ten experts listed upstream (185 of 429, e.g. "Skill Smith" / skill-smith) have no publicly distributed persona file at all; if your WorkBuddy has used one, its cache is read directly, and when all three proper sources are empty a **stand-in persona** is built from the public description, tags and sample prompts of the expert center, with its first paragraph stating that it is not the original text. Every expert stays viewable and summonable (issue #5).
|
|
115
119
|
- **Summoning** = appending one independent **agent preset** row to the profile patch (a `@deepseek-ai/dsh-agent-preset` entry that mirrors the built-in `standard` preset, with only the persona prefix swapped for the expert's full persona). New sessions then offer **WorkBuddy Expert · …** and that expert takes over the session, while the standard tools / planning / compaction / delegation stay intact. Multiple experts coexist; writes go through the existing patch pipeline (file lock + version check + atomic write), preserving other rows, comments and `!!js` expressions
|
|
116
120
|
- **Bundled skills**: tick to install them too — a full local WorkBuddy cache (`~/.workbuddy/plugins/cache/experts/`) is copied wholesale into `~/.agents/skills/` (prefixed `wbexpert__`, discovered by the skill registry immediately); without a cache it falls back to the CDN's single `SKILL.md` and labels the source honestly
|
|
117
121
|
- **Team experts (summonable since 1.9.4)**: WorkBuddy's 53 "expert teams" assume `TeamCreate` and `Agent(name=…)`, neither of which DSH has. Summoning now also writes one file per member persona under `~/.dsh/wb-market/experts/teams/<expert>/`, and appends a **runtime adaptation** block to the lead's persona: creating the team becomes a no-op (the roster is fixed at summon time); dispatching a member becomes `subagent` (after `read`-ing that member's persona into the prompt), with sequential SOPs passing `run_in_background: false` so the lead waits for the result; follow-ups use `send_message`. The original rules — never ghost-write a member's output, never connect members directly, everything relayed through the lead — are preserved verbatim. Member personas stay **out of the system prompt** (otherwise every turn would pay for all five), and are read only when dispatching
|
|
@@ -136,6 +140,8 @@ Experts (WorkBuddy expert center, 429 experts / 15 industries; category filter +
|
|
|
136
140
|
- **Skill uninstall (new in 2.2.0)**: skills in user-level / project-level directories can be deleted from the detail pane (inline second confirmation, **permanent, no undo**), while skills shipped with DSH, registered at runtime, or living in custom directories stay read-only and say so. The host only exposes read endpoints, so removal is handled by this plugin's `removeSkill`: source allowlist → strict root containment → parent-directory realpath → symlinks unlinked without touching their targets → the folder must contain `SKILL.md` and stay under the root
|
|
137
141
|
- **Live skill-set refresh (new in 2.2.0)**: installing or uninstalling from the market, and uninstalling from the board, all broadcast on a module-level change bus. The top **Skill** badge and the board list subscribe to the same bus and re-read the truth, with a sequence guard on the badge fetch so rapid toggles cannot roll the number back. The new set is reflected immediately — no tab switch or panel reopen
|
|
138
142
|
- **Recognisable skill installs (new in 2.4.0)**: every Skill card / list row shows an "installed …" badge — green with relative time within 7 days ("installed 3 hours ago"), "N days ago" within 30 days, an absolute date beyond. The timestamp prefers the first-install time recorded in the install-state ledger, then the directory creation time, then its mtime; skills shipped with DSH or registered at runtime have no install event and show no badge. The filter bar adds a **recently installed** timeline (newest first), and when a board name (from `SKILL.md`'s `name:`) differs from the market name recorded in the ledger, the card carries a "from market: original name" badge and the detail pane adds an original-name row. Data comes from the new `skillInstallInfo` RPC (the host scans the standard skill roots and reads only the first 4KB of each `SKILL.md`); the host must be restarted once to register it, and the board says so explicitly instead of showing nothing
|
|
143
|
+
- **Skill details and market homepage fixed (new in 2.4.1)**: SkillHub's detail endpoint keeps the name and summary under the `skill` object (`displayName` / `summary_zh`), while the old mapping only read the root — so the detail dialog showed the slug as the title and an empty body. Values now fall back through `skill.displayName → root name → slug` and `skill.summary_zh → skill.summary → legacy fields`, icon / created date / category / source / publisher come from the same place, and merging the response into the list entry **never lets empty strings overwrite what is already shown** (`0` and `false` still win). The summary from the list is visible while the detail loads. A `homepage` pointing at `api.skillhub.cn` (a JSON API that returns 405 in a browser) is rewritten to `https://skillhub.cn/<namespace>/<slug>`, with a second guard at render time, and feedback links prefer the GitHub repository when one can be resolved (issue #4)
|
|
144
|
+
- **The floating button can be hidden, and it steps aside for the board (new in 2.4.1)**: right-click or long-press (about half a second, works with touch and stylus) opens a menu with **Hide floating button**, followed by a 6-second hint saying where to reopen it. When the board occupies the centre column the button collapses automatically instead of covering list and detail text, and returns when you leave the board — without changing your chosen mode. If the button is your only remaining entry the item is disabled and explains why: pick another mode in the "Entries" menu before hiding it, so you can never end up with an armory that cannot be opened
|
|
139
145
|
- **Custom suites (new in 2.2.0)**: bundle skills you use together. The **Suites** button in the Skill board toolbar opens a manager: pick skills on the left, arrange them on the right (click **+** or drag one in, drag to reorder, delete with an inline confirmation), and one save overwrites the whole set into `~/.dsh/armory/suites.json` (staging + atomic rename; invalid input is rejected without touching the file). The composer's Skills submenu shows a suite group at the top — one click expands the suite in member order into multiple `/name` tokens in the draft. Limits: 100 suites, 40 members each; members count individually toward "recently used" rather than the suite name
|
|
140
146
|
- **Marketplace registry (new in 2.0.0)**: market sources are no longer hard-coded — they live in `~/.dsh/armory/marketplaces.json` (`REGISTRY_VERSION = 1`), fall back to the built-in defaults when missing or corrupt, persist on first read, and can be added / edited / removed. Writes are staging + atomic rename
|
|
141
147
|
- **Instant community list (new in 2.0.0)**: the last successful slim list is mirrored into `localStorage` (7 days / 4MB cap, older snapshot kept on quota errors), so the first paint renders the snapshot before the real result silently replaces it (zero network, zero IPC). When no source is reachable it says "showing the local cache" instead of an empty list
|
|
@@ -188,13 +194,21 @@ Details, local development installs, and troubleshooting: [docs/installation.md]
|
|
|
188
194
|
|
|
189
195
|
### Opening the panel
|
|
190
196
|
|
|
191
|
-
|
|
197
|
+
Three entry seats, one panel:
|
|
192
198
|
|
|
199
|
+
- **The "Big Fish Armory" row in the global panel list** (top of the sidebar): the host's official panel list, right next to "Plugins" — the primary entry;
|
|
193
200
|
- **Floating button (bottom-right)**: draggable, position remembered;
|
|
194
|
-
- **Sidebar entry
|
|
201
|
+
- **Sidebar bottom entry**: a 42px row (icon + label) when the sidebar is expanded, an icon button once it collapses into the rail.
|
|
195
202
|
|
|
196
203
|
The panel floats above the session; closing it ("Close" or Esc) does not affect the conversation.
|
|
197
204
|
|
|
205
|
+
Which seats stay is chosen in the panel header's **Entries** menu, six modes: `Global panel + floating button (recommended)` (default) / `Global panel only (top-left, next to "Plugins")` / `Global panel + sidebar bottom entry (no floating button)` / `Floating button only` / `Sidebar bottom entry only` / `All three entries`. **All three can never be off** — the panel opens only from those seats, so the menu is a "keep at least one" combination rather than three independent switches. The choice lives in `localStorage`, so a different browser or cleared storage means picking again.
|
|
206
|
+
|
|
207
|
+
Two self-service rules for the floating button (since 2.4.1):
|
|
208
|
+
|
|
209
|
+
- **Right-click or long-press it** (about half a second) for a menu with **Hide floating button** — no hunt for the Entries menu. A 6-second hint then says where to reopen it. If the button is the only entry left, that item is greyed out and points you to the Entries menu: keep another seat before losing this one.
|
|
210
|
+
- **It auto-collapses while the board occupies the centre column**: the button is an overlay and would sit on the list and detail text; it comes back as soon as you leave the board, and your mode is untouched.
|
|
211
|
+
|
|
198
212
|
### Global vs project
|
|
199
213
|
|
|
200
214
|
Tabs switch between "Global" and each project:
|
|
@@ -222,6 +236,12 @@ The detail pane lists the tools a server currently registers; expand one for its
|
|
|
222
236
|
**The panel says a server is "disabled", but the model reports `unknown tool "mcp__xxx__..."`.**
|
|
223
237
|
That server is disabled, so it registers no tools. Enable it in the panel.
|
|
224
238
|
|
|
239
|
+
**I upgraded but the skill detail is still blank, or the floating button behaves as before.**
|
|
240
|
+
Check two things. First, that the new package actually landed: after `dsh plugin --profile web update dsh-armory`, the first panel you open shows a **"vX.Y.Z update"** card whose title is the version currently installed — or read the `version` field of `~/.dsh/profiles/<profile>/node_modules/dsh-armory/package.json`. Second, **quit DSH completely and start it again** — the market field mapping lives in host-side modules (`lib/wb-market.js`, `lib/index.js`) that are loaded once at process start, so reloading the panel only refetches the UI bundle. If one specific skill still has no summary, post its slug in an issue and that response gets checked on its own.
|
|
241
|
+
|
|
242
|
+
**Opening an expert, the detail says this persona is not the original text?**
|
|
243
|
+
That is the stand-in, not an error. About four in ten experts in the upstream expert center (185 of 429, "Skill Smith" among them) only have a directory entry — there is no persona file at the public distribution URL — and when the local WorkBuddy cache does not have it either, the Armory builds a stand-in from the public description, tags and sample prompts, so the expert **stays viewable and summonable**; it only reproduces "who this roughly is and what they own", not the original working method. To use the original, save it as `~/.dsh/wb-market/experts/overrides/<plugin>.md` (e.g. `skill-smith.md`); the next detail view uses it automatically and labels the source "local override" — delete the file to fall back to cache, distribution or the stand-in. The first paragraph of the stand-in also gives the exact path on this machine.
|
|
244
|
+
|
|
225
245
|
**How do I upgrade? Why did the panel not notify me?**
|
|
226
246
|
GitHub tag-pinned installs never cross versions — re-add with the new tag (`github:2026heshao/dsh-armory#v1.9.0`). The banner only queries this repo's GitHub Releases, at most once a day, is dismissible, and never acts on its own.
|
|
227
247
|
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
> **DeepSeek Harness 的一体化管理看板**:MCP · 技能 · 专家 · 插件 · 工具账本 · 四大市场,浏览、搜索、一键安装、一键召唤。
|
|
6
6
|
> fork 自 [Imzl-zl/dsh-mcp-manager-ui](https://github.com/Imzl-zl/dsh-mcp-manager-ui)(MIT),现已扩展为完整军械库。
|
|
7
7
|
>
|
|
8
|
-
> **最新 v2.4.
|
|
8
|
+
> **最新 v2.4.2**:文档版——README(中 / 英)与实机功能对齐:三个入口席位与六种档位、悬浮按钮怎么隐藏、看板打开时它如何自动让位,以及 v2.4.1 的 SkillHub 详情修正都写进来了;运行代码与 v2.4.1 完全相同。详见 [更新日志](.github/release-notes/v2.4.2.md)。
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
11
|
<a href="https://github.com/2026heshao/dsh-armory/stargazers"><img src="https://img.shields.io/github/stars/2026heshao/dsh-armory?style=social" alt="stars"></a>
|
|
@@ -26,7 +26,7 @@ dsh plugin --profile web add dsh-armory
|
|
|
26
26
|
dsh plugin --profile web add github:2026heshao/dsh-armory
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
装完**重启 DSH**,侧栏顶部「全局面板」里点
|
|
29
|
+
装完**重启 DSH**,侧栏顶部「全局面板」里点 **大肥鱼军械库**(或在右下角悬浮按钮、左侧栏底部入口,三个席位见下文)。桌面端装在 `desktop` profile 时把 `--profile web` 换成 `--profile desktop`。
|
|
30
30
|
|
|
31
31
|
## 它解决什么
|
|
32
32
|
|
|
@@ -35,6 +35,9 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
|
|
|
35
35
|
| MCP 配置要手改 YAML,改完不知道连没连上 | 可视化面板:状态、工具 Schema、启停、重连,全局与项目双作用域,项目级改完即对存活会话生效 |
|
|
36
36
|
| 装技能要去各处翻 `SKILL.md` 仓库 | **市场直连**:SkillHub 19 万+ 技能、WorkBuddy 316 个连接器,搜索/筛选/一键安装,逐文件 sha256 校验 |
|
|
37
37
|
| 在市场装了技能,回看板却找不到,也分不清哪个是刚装的 | **技能安装可辨识**:卡片标「装于 …」,7 天内高亮并给相对时间;筛选条按安装时间倒序成「最近安装」;看板名与市场原名不一致时标出「来自市场 原名」 |
|
|
38
|
+
| 技能列表有两行摘要,点进详情反而整块空白,标题还退化成 slug | **详情读得到**:SkillHub 把名称与介绍放在接口的 `skill` 子对象(`displayName` / `summary_zh`),映射按此取值;详情回包里的空串不会覆盖已显示的内容,加载中也先给摘要 |
|
|
39
|
+
| 详情里的「来源主页」跳过去是 `api.skillhub.cn`,浏览器只会拿到 405 | **链接点得开**:接口域名统一改写成 `https://skillhub.cn/<namespace>/<slug>` 公开页,渲染层再拦一道,拿不到可浏览主页就不渲染这个按钮 |
|
|
40
|
+
| 右下角悬浮球盖住看板内容,又找不到关闭的地方 | **入口自己管**:右键 / 长按悬浮按钮即可隐藏(并提示从哪重开),看板占据中栏时自动让位;三个入口席位六档可切,不会出现「全关了自己开不了」 |
|
|
38
41
|
| 每个 MCP 的工具描述都在吃上下文 token,零调用的工具白白占位 | **工具裁缝**:扫描本机会话日志统计每个工具的调用/错误/延迟,并给出技能维度的使用账本;死工具清单一键禁用 |
|
|
39
42
|
| 从 Claude/Cursor/VS Code 迁移要逐条抄配置 | 自动检出 11 种客户端的本机配置,预览后一键导入 |
|
|
40
43
|
| 插件散在宿主自带与社区清单两处,格式与可装性各不相同 | **插件页**:把 DSH 社区清单一并呈现并标明可装性(宿主自带组件单独标注),安装统一走宿主 `pluginManager`,装完明确提示需重启 |
|
|
@@ -91,7 +94,7 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
|
|
|
91
94
|
- 按传输方式(HTTP/stdio)与状态筛选,按名称/命令/URL 搜索
|
|
92
95
|
- 启用、禁用、重连、添加、编辑、移除;需要时用眼睛临时揭示被掩码的凭据并一键复制
|
|
93
96
|
- **全局 + 项目双作用域**:全局写 Web profile,一次注册所有项目可用;项目写该项目 `.dsh/mcp.json`,只该项目会话可见;项目里还能「屏蔽」某个全局 MCP
|
|
94
|
-
-
|
|
97
|
+
- **三个入口席位,六档可切**:左上角「全局面板」里的**大肥鱼军械库**一行(宿主官方机制,与「插件」同一套)、右下角悬浮按钮(可拖拽、记忆位置)、左侧栏底部入口(展开态 42px 行、收起成轨道时是圆钮)共用同一个面板;面板右上角「入口」菜单在六档之间切换(两个 / 一个 / 三个席位),**不能三个都关**,悬浮按钮若是唯一入口则不可单独隐藏(2.4.1 起还能右键 / 长按悬浮按钮直接隐藏它)
|
|
95
98
|
- 导入本机其他客户端的 MCP 配置:自动检测 Claude Code、Codex(`config.toml`)、OpenCode(含 `.jsonc`)、pi、Claude Desktop、Cursor、Windsurf、VS Code、Gemini CLI、Roo Code 与跨工具的共享配置,逐个列出,点一条即导入;也能粘贴 Claude/Cursor/Cline/Roo 的 `mcpServers` 或 VS Code 的 `servers` JSON。写入前预览,支持「合并(同名更新)」与「替换」
|
|
96
99
|
- 跟随 DSH 深色/浅色主题,适配窄屏与移动宽度
|
|
97
100
|
- 更新提示与**一键升级**:有新版时在面板顶部显示可关闭的提示条(每天最多查一次,可用 `DSH_ARMORY_DISABLE_UPDATE_CHECK` 关闭)。点了「升级」才动,**不会自动升级**;升级由 DSH 官方的 pluginManager 执行,装完提示重启宿主生效。用 `link:` / `file:` / `github:` 装的本地开发副本不给按钮(那会把链接换成 npm 包)
|
|
@@ -103,6 +106,7 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
|
|
|
103
106
|
- 技能版权归原作者所有;两个均为第三方接口,字段可能随上游改版变化(面板顶部有常驻说明)
|
|
104
107
|
- **专家直连(1.9.0 新增,体验对齐 WorkBuddy 专家中心)**:看板独立分类「专家」(侧栏入口同步更名「技能 · MCP · 专家」)——
|
|
105
108
|
- **目录**:直读 WorkBuddy 专家中心官方分发(`expert_center.json`,429 位专家 / 15 个行业分类,ETag 缓存在 `~/.dsh/wb-market/experts/`),分类筛选 + 关键词搜索 + 详情弹层(召唤前看人设正文、捆绑技能、试试这样问)
|
|
109
|
+
- **人设来源(2.4.3)**:详情与召唤按「本机覆盖 → 本机 WorkBuddy 缓存(`~/.workbuddy/plugins/cache/experts/<包>/<版本>/agents/`)→ 公开分发地址 → 兜底人设」取数。上游目录里约四成专家(429 位中的 185 位,例如「技能匠人」skill-smith)其实没有公开分发人设文件;本机 WorkBuddy 用过它就直接读缓存,三条正路都没有时会用专家中心公开的介绍、标签与示例问题生成一份**兜底人设**,正文第一段就写明「这份人设不是原文」,保证任何一位专家都能看详情、能召唤(issue #5)。
|
|
106
110
|
- **召唤** = 往 profile 补丁写入一条**独立 Agent 预设**(`@deepseek-ai/dsh-agent-preset` 行,plugins 复刻内置 standard 预设、仅 persona 的 prefix 换成专家人设全文)——新建会话时选择「WorkBuddy 专家 · …」即专家接管该会话,标准工具/规划/压缩/委派原样保留;多个专家可共存,写入走既有 patch 写链(文件锁 + 版本校验 + 原子写),其余条目、注释与 `!!js` 表达式原样保留
|
|
107
111
|
- **捆绑技能**:召唤时可勾选一并安装——本机 WorkBuddy 缓存(`~/.workbuddy/plugins/cache/experts/`)有完整技能树就整目录复制到 `~/.agents/skills/`(`wbexpert__` 前缀,即刻被技能注册表发现);无缓存时按 CDN 的 SKILL.md 单文件兜底并如实标注来源
|
|
108
112
|
- **团队型专家(1.9.4 可召唤)**:WorkBuddy 的 53 个「专家团」人设原本依赖 `TeamCreate` / `Agent(name=…)` 两个 DSH 没有的工具。召唤时除了写主理人预设,还会把每位成员的人设各自落成一份文件(`~/.dsh/wb-market/experts/teams/<专家>/`),并在主理人人设末尾追加一段**运行时适配**:建团队 → 无需调用(编制已在召唤时固定);派活 → `subagent`(先把该成员人设 `read` 出来拼进 prompt),顺序 SOP 传 `run_in_background: false` 当场等结果;续聊用 `send_message`。原人设的铁律(不得代写成员产出、成员之间不直连、一切经主理人中转)原样保留。成员人设**不进系统提示**(否则每轮都要为 5 份人设白付上下文费),只在调度时按需读取
|
|
@@ -127,6 +131,8 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
|
|
|
127
131
|
- **技能卸载(2.2.0 新增)**:用户级 / 项目级目录里的 skill 可在详情里直接卸载(就地二次确认、**永久删除且不可撤销**);随 DSH 分发、运行时注册与自定义目录的 skill 只读,并说明不在可卸载范围内。宿主本身只提供读取接口,卸载由本插件的 `removeSkill` 完成:来源白名单 → 根目录严格包含性 → 父目录 realpath → 符号链接只 unlink 不碰目标 → 目录必须含 `SKILL.md` 且在根内
|
|
128
132
|
- **技能集合实时刷新(2.2.0 新增)**:市场安装 / 卸载技能、看板自己卸载,三处都会向模块级变更总线广播;顶部 **Skill** 数量角标与看板列表订阅同一条总线,各自重读真值,角标重取带序号守卫,快速连点也不会被乱序回包回滚。装完 / 卸完立刻对新集合,不必切页或重开面板
|
|
129
133
|
- **技能安装可辨识(2.4.0 新增)**:Skill 看板每张卡片 / 列表行显示「装于 …」——7 天内绿色高亮并给相对时间(「3 小时前装」),30 天内显示「N 天前装」,更早给绝对日期。时间优先取安装状态账本登记的首次安装时间,其次目录创建时间,最后目录修改时间;随 DSH 分发 / 运行时注册的技能没有安装事件,不显示徽标。筛选条新增「最近安装」时间线,按安装时间倒序平铺;看板名(取自 `SKILL.md` 的 `name:`)与账本登记的市场名不一致时,卡片出现「来自市场 原名」徽标,详情面板新增「市场原名」行。数据由新增 RPC `skillInstallInfo` 提供(宿主自扫标准技能根目录、只读每个 `SKILL.md` 头部 4KB 解析 `name:`),宿主需重启一次才注册;未注册时看板显式提示,不静默
|
|
134
|
+
- **技能详情与市场主页修正(2.4.1 新增)**:SkillHub 的详情接口把名称与介绍放在 `skill` 子对象(`displayName` / `summary_zh`),旧映射只读根层,于是详情弹层标题退化成 slug、介绍整块空白。现在按 `skill.displayName → 根层 name → slug`、`skill.summary_zh → skill.summary → 旧字段` 逐级回退,图标 / 上架时间 / 分类 / 来源 / 发布方名也从 `skill` 与 `owner` 取;列表项与详情回包合并时**空串不再覆盖已显示的内容**(`0` 与 `false` 照旧保留),加载中就先显示列表里的摘要,不等接口。`homepage` 落在 `api.skillhub.cn`(浏览器打开是 405)时统一改写成 `https://skillhub.cn/<namespace>/<slug>` 公开页,渲染层再拦一道,接口地址不会再被当成网页交出去;能解析到 GitHub 仓库的,反馈链接优先指向仓库(issue #4)
|
|
135
|
+
- **悬浮按钮可隐藏、看板打开时自动让位(2.4.1 新增)**:右键或长按(约半秒,触屏与手写笔同样可用)悬浮按钮弹出菜单,可直接「隐藏悬浮按钮」,隐藏后有一条 6 秒提示说明从哪儿重新打开;看板占据中栏时按钮自动收起,回到会话再出现,不再压在列表与详情文字上。若悬浮按钮是当前唯一入口,菜单里那一项会置灰并说明原因,先到「入口」换档位再隐藏——避免出现「按钮没了、面板也开不了」的死局。档位一览见下面的「打开面板」
|
|
130
136
|
- **自定义套件(2.2.0 新增)**:把常一起用的 skill 打包成「套件」——Skill 看板工具栏的「套件」打开管理窗,左侧挑技能、右侧编排(点 **+** 或拖入添加,拖拽排序,删除就地二次确认),一次保存即整集合覆盖落盘到 `~/.dsh/armory/suites.json`(staging + rename 原子写,坏数据拒绝且原文件不动)。输入框召唤菜单的「技能」子菜单顶部会出现套件分组,点一次就按成员顺序把多个 `/name` 一并插进草稿。上限 100 个套件 / 每套 40 个成员;成员按各自的技能名进「最近使用」,不会把套件名记成一条孤立记录
|
|
131
137
|
- **多市场注册表(2.0.0 新增)**:市场源不再硬编码,落 `~/.dsh/armory/marketplaces.json`(`REGISTRY_VERSION = 1`),缺失或损坏回落内置默认项、首读即落盘,支持增删改;写盘一律 staging + rename 原子替换
|
|
132
138
|
- **社区目录秒开(2.0.0 新增)**:上次成功的精简清单镜像进浏览器 `localStorage`(7 天 / 4MB 上限,超配额保留旧快照),首屏先渲染快照再被真实结果静默替换(0 网络 0 IPC);源不可达时明说「显示的是本地缓存」而非给空列表
|
|
@@ -169,14 +175,20 @@ dsh plugin --profile web remove dsh-armory
|
|
|
169
175
|
|
|
170
176
|
### 打开面板
|
|
171
177
|
|
|
172
|
-
|
|
178
|
+
三个入口席位,同一个面板:
|
|
173
179
|
|
|
180
|
+
- **左上角「全局面板」里的「大肥鱼军械库」一行**:走宿主官方的面板列表,在「插件」旁边,是主入口;
|
|
174
181
|
- **右下角悬浮按钮**:可拖拽移动,位置会被记住;
|
|
175
|
-
-
|
|
182
|
+
- **左侧栏底部入口**:展开态是 42px 的一行(图标 + 文字),侧栏收起成轨道时只剩一个圆钮。
|
|
176
183
|
|
|
177
184
|
面板浮在会话之上,关掉它(右上角「关闭」或 Esc)不会影响会话。
|
|
178
185
|
|
|
179
|
-
|
|
186
|
+
席位怎么留由面板右上角的「入口」菜单决定,共六档:`全局面板 + 悬浮按钮(推荐,默认)` / `仅全局面板(左上角,"插件"旁)` / `全局面板 + 侧栏底部入口(无悬浮按钮)` / `仅悬浮按钮` / `仅侧栏底部入口` / `三个入口全开`。**三个不能全关**——面板只能从这三个席位打开,所以它是「至少留一个」的组合,而不是三个互不相干的开关。选择存在浏览器本地(localStorage),换浏览器或清缓存要重选一次。
|
|
187
|
+
|
|
188
|
+
悬浮按钮另外两条自助规则(2.4.1 起):
|
|
189
|
+
|
|
190
|
+
- **右键或长按(约半秒)它**弹出菜单,可直接「隐藏悬浮按钮」——不必再去面板里找「入口」;隐藏后有 6 秒提示说明从哪儿重新打开。若它是当前唯一入口,这一项会置灰并指路到「入口」菜单:先留好别的入口,再关这一个。
|
|
191
|
+
- **看板占据中栏时它自动收起**:悬浮按钮是浮层,看板打开时正好盖住列表与详情的文字;离开看板页它就回来,不改变你选的档位。
|
|
180
192
|
|
|
181
193
|
### 全局 vs 项目
|
|
182
194
|
|
|
@@ -237,6 +249,12 @@ dsh plugin --profile web remove dsh-armory
|
|
|
237
249
|
**项目行那些状态文案分别是什么意思?**
|
|
238
250
|
它们把两件独立的事分开说:**连接在不在** —— `已连接 · 当前无会话使用(连接保留,下次直接用)`(最后一个会话结束了,连接按空闲策略留着)/ `已连接 · N 个会话在用 · M 工具` / `连接中…` / `连接失败` / `尚未建立连接(新会话自动挂载)`;**几个会话在用** —— 就是那句里的 `N 个会话在用`。旧版本的「待会话挂载」正是把这两件事压成一句,所以容易被读成"还没连上"。
|
|
239
251
|
|
|
252
|
+
**升级后技能详情页还是空的,或者悬浮按钮的行为没变?**
|
|
253
|
+
两步确认。先确认新包真装上去了:`dsh plugin --profile web update dsh-armory` 之后,升级后第一次打开面板会弹出一张「vX.Y.Z 的更新」卡片,标题里的版本号就是当前安装的版本;也可以直接看本机 `~/.dsh/profiles/<profile>/node_modules/dsh-armory/package.json` 的 `version`。再**完全退出 DSH 重新启动**——市场的字段映射在宿主侧模块(`lib/wb-market.js`、`lib/index.js`)里,只在进程启动时加载一次,面板里刷新只会重取界面 JS,宿主那份映射仍是旧的。若只有某个具体技能的介绍仍然缺,欢迎把它的 slug 发到 issue 里,按那条响应单独对一次。
|
|
254
|
+
|
|
255
|
+
**点开专家,详情里写着「这份人设不是原文」?**
|
|
256
|
+
这是兜底人设,不是错误。上游专家中心里约四成专家(429 位中的 185 位,「技能匠人」就在其中)只挂了目录条目,公开分发地址上没有它们的人设文件;本机 WorkBuddy 缓存里也没有时,军械库会用专家中心公开的介绍、标签与示例问题生成一份兜底人设,**保证这位专家仍能看详情、能召唤**,只是工作方法只能还原到「大致是谁、负责什么」。想要原文,把它存成 `~/.dsh/wb-market/experts/overrides/<包名>.md`(例如 `skill-smith.md`)即可,下次打开详情会自动改用原文,来源标注「本机覆盖」;删掉文件就回到缓存 / 分发 / 兜底。正文第一段也会给出这台机器上的确切路径。
|
|
257
|
+
|
|
240
258
|
**怎么升级?为什么面板没提示?**
|
|
241
259
|
从 npm 装的直接 `dsh plugin --profile web update dsh-armory` 就会升小版本,也可以直接点面板提示条上的「升级」(同一件事,免去敲命令)。面板的提示条只查 GitHub Releases、每天最多一次、可关闭、不会自己动;固定 tag 安装的用户不会自动跨版本,需要用新 tag 重新 `add`(见 [安装与升级](docs/installation.md))。
|
|
242
260
|
|
|
@@ -270,14 +288,14 @@ dsh plugin --profile web remove dsh-armory
|
|
|
270
288
|
|
|
271
289
|
```sh
|
|
272
290
|
npm install --no-save yaml@2 eslint@9 # 测试与风格检查的唯一裸依赖(运行依赖全部由宿主提供)
|
|
273
|
-
npm test # 全
|
|
291
|
+
npm test # 全 55 套件(与 CI / 发版门槛同一条)
|
|
274
292
|
npm run lint # ESLint:no-undef / no-unused-vars / no-empty 等
|
|
275
293
|
npm run test:e2e # 可选:用宿主补丁算法验证专家预设进入组合树
|
|
276
294
|
dsh --profile web --dump-config # 看 profile 的有效配置
|
|
277
295
|
dsh web # 起 Web 做真实操作验证
|
|
278
296
|
```
|
|
279
297
|
|
|
280
|
-
`npm test` 跑的是 `test/run-all.mjs`,依次执行 **
|
|
298
|
+
`npm test` 跑的是 `test/run-all.mjs`,依次执行 **55** 个独立套件(各自是独立 node 进程,任一非零退出即整体失败)。套件是显式白名单而非 `node --test` 自动发现——`test/` 下还有带副作用的迁移脚本与需要宿主模块的端到端脚本,自动发现会误跑。
|
|
281
299
|
|
|
282
300
|
| 分组 | 套件 | 覆盖 |
|
|
283
301
|
| --- | --- | --- |
|
|
@@ -285,9 +303,10 @@ dsh web # 起 Web 做真实操作验证
|
|
|
285
303
|
| 契约与入口 | `contract-consistency` `client-entry` `host-import-sources` | 面板可调方法必须在 typert 声明 / client 契约数组 / 宿主方法集三处同时存在;三个入口「全关」不可表达;VS Code `${input:}` 降级 |
|
|
286
304
|
| 客户端质量 | `client-i18n` `i18n-coverage` `whats-new-i18n` `error-boundary-copy` `persona-truncate` `tailor-window` | 中文皆包 `t()`;en-US 字典双向差集与 zh/非 zh 回落;更新日志英文覆盖逐条对齐(含缺译文回落);崩溃详情可复制;persona 4000 预览阈值;工具裁缝时间窗四档 |
|
|
287
305
|
| 工具裁缝趋势(2.2.0) | `tailor-timeline` `tailor-tax-ui` `tailor-cache-line` | 真实下发税的时间维度与跨度归因(无线上数据必须为 null 而非 0);裁缝新字段在界面上的接线(vm 真跑源码片段);账本缓存行只剩读数(「清空缓存」按钮已删,钉住不许复活) |
|
|
306
|
+
| SkillHub 修正(2.4.1) | `skillhub-detail-fix` `skillhub-ux-fix` | 详情字段回退链与目录 / 详情映射(fetch 全替身,逐条对上 issue #4 的响应形状);`skillhubHomepage` 域名改写与缺字段兜底;合并时空值不得覆盖、`0`/`false` 必须保留;`browsableHomepageUrl` 拦住接口域名;悬浮按钮订阅 / 看板激活自动收起 / 右键与长按菜单 / 唯一入口置灰 / 卸载清理(hooks 替身真渲染) |
|
|
288
307
|
| 自定义套件(2.2.0) | `suites-registry` `suites-client` | 整集合覆盖 / 幂等 / 拒绝与截断两态;id 归属契约(保存后不分裂)、引用套件展开为多个 `/name`、三级写通道降级 |
|
|
289
308
|
| 技能集合(2.2.0) | `skill-remove` `skill-refresh` | 卸载来源白名单与路径边界(根自身 / `..` 穿越 / 跨来源根 / 符号链接只删链接);装 / 卸后角标与看板实时刷新、乱序回包守卫 |
|
|
290
|
-
| 专家与团队 | `run-expert-manual` `session-persona` `team-bridge` `expert-card-actions` `recent-sort-regression` | 专家市场写链(真网目录 + 人设 + patch 往返,33
|
|
309
|
+
| 专家与团队 | `run-expert-manual` `session-persona` `team-bridge` `expert-card-actions` `recent-sort-regression` `expert-persona-source` | 专家市场写链(真网目录 + 人设 + patch 往返,33 条断言);会话级挂/换/摘;团队桥接;卡片按钮真值表;「最近使用」排序;人设取数链(覆盖优先且零人设请求、本机缓存命中不联网、CDN 兜底、404 / 网络故障 / 空缓存都落到标注过的兜底人设、包名不能穿越目录、召唤前先取人设) |
|
|
291
310
|
| 升级与安装真机 | `upgrade-plan` `verify-install-info` `verify-host-installinfo` `teardown-residue` | 一键升级判据(本地安装 / 来源未知一律不写);真 profile 数据下的来源判定(profile 不存在自行 SKIP);teardown 残留诊断 |
|
|
292
311
|
| 市场与安装链(2.0.0) | `wb-registry` `wb-install-state` `wb-auth-rules` `wb-connector-meta` `wb-awesome-market` `wb-install-flow` `auth-gate-regression` `install-toast` | 多市场注册表原子写(只剩连接器源,旧 plugins 条目读侧丢弃/写侧拒绝);安装状态与来源锁;令牌槽扫描与注入规则;连接器 R1/R2/R3 投影;awesome 过滤/瘦身/304/双源切换与更新探测五枚举;令牌替换写链;装前 401 鉴权闸;顶部安装浮层跨卸载可见 |
|
|
293
312
|
| 社区信号(2.3.0) | `community-meta` | GitHub 仓库写法解析、单次最多 8 条、6 小时缓存命中不联网、refresh + ETag 的 304 复用、404 文案、网络失败 stale 回落、403 限流跨调用生效、原子写(fetch 全替身 + mkdtemp 隔离) |
|
package/lib/expert-market.js
CHANGED
|
@@ -66,6 +66,9 @@ function skillsRoot() {
|
|
|
66
66
|
return join(homedir(), ".agents", "skills");
|
|
67
67
|
}
|
|
68
68
|
function workbuddyExpertCache() {
|
|
69
|
+
// 测试隔离口(同 DSH_ARMORY_MARKET_HOME 的纪律):设置时本机 WorkBuddy 缓存根指到临时目录。
|
|
70
|
+
const override = process.env.DSH_ARMORY_WORKBUDDY_CACHE;
|
|
71
|
+
if (override) return override;
|
|
69
72
|
return join(homedir(), ".workbuddy", "plugins", "cache", "experts");
|
|
70
73
|
}
|
|
71
74
|
// 团队专家:主理人 + N 个成员,每人一份人设。成员人设不塞进 preset(会白白撑大每轮
|
|
@@ -335,6 +338,94 @@ async function localExpertPluginJson(plugin) {
|
|
|
335
338
|
return null;
|
|
336
339
|
}
|
|
337
340
|
|
|
341
|
+
// 主理人人设的本机来源:WorkBuddy 自己下载过的专家包里就有 agents/<name>.md。
|
|
342
|
+
// 上游只把一部分专家放在公开分发地址上(2026-10-27 实测 428 个里 185 个 404),
|
|
343
|
+
// 所以本机缓存不是「优化」,而是这些专家唯一能拿到正文的途径。
|
|
344
|
+
async function localExpertPersona(plugin, agentName) {
|
|
345
|
+
const names = [agentName, plugin].map((value) => safeSegment(value || "")).filter(Boolean);
|
|
346
|
+
for (const version of await localExpertVersions(plugin)) {
|
|
347
|
+
const dir = join(version.dir, "agents");
|
|
348
|
+
for (const name of new Set(names)) {
|
|
349
|
+
try {
|
|
350
|
+
const text = await readFile(join(dir, `${name}.md`), "utf8");
|
|
351
|
+
if (text.trim()) return text;
|
|
352
|
+
} catch { /* 换个名字或换下一个版本 */ }
|
|
353
|
+
}
|
|
354
|
+
// 人设文件名与 plugin / agentName 都不一致时,接受 agents/ 下唯一那份 md。
|
|
355
|
+
try {
|
|
356
|
+
const files = (await readdir(dir)).filter((file) => /\.md$/i.test(file));
|
|
357
|
+
if (files.length === 1) {
|
|
358
|
+
const text = await readFile(join(dir, files[0]), "utf8");
|
|
359
|
+
if (text.trim()) return text;
|
|
360
|
+
}
|
|
361
|
+
} catch { /* 该版本没有 agents/ */ }
|
|
362
|
+
}
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// 本机覆盖:用户自备的人设正文,优先级高于缓存与 CDN。上游 185/429 没有公开分发、
|
|
367
|
+
// 本机也没有缓存时,这是唯一能拿到「原文」的途径。文件名走 safeSegment,不能借 plugin 穿越目录。
|
|
368
|
+
function overridePersonaPath(plugin) {
|
|
369
|
+
return join(cacheDir(), "overrides", `${safeSegment(plugin)}.md`);
|
|
370
|
+
}
|
|
371
|
+
async function overridePersona(plugin) {
|
|
372
|
+
try {
|
|
373
|
+
const text = await readFile(overridePersonaPath(plugin), "utf8");
|
|
374
|
+
if (text.trim()) return text;
|
|
375
|
+
} catch { /* 绝大多数专家没有覆盖文件 */ }
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/** 原文取不到的原因:上游缺包与网络故障说法不同,用户据此决定换专家还是重试。 */
|
|
380
|
+
function describePersonaFailure(error) {
|
|
381
|
+
const detail = String(error?.message || error);
|
|
382
|
+
if (/HTTP 404/.test(detail)) return "上游 404:专家中心目录里挂着它,但公开分发地址上没有这个包";
|
|
383
|
+
return `拉取原文失败:${detail}`;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* 兜底人设:三条正路都拿不到原文时,用专家中心公开的介绍 / 专业 / 标签 / 示例问题拼一份替身。
|
|
388
|
+
* 必须显式标注非原文——召唤出来的会话会照这份文字行事,用户有权知道它不是原作者设定;
|
|
389
|
+
* 拿到原文后放进本机覆盖目录即自动改用原文(覆盖优先级最高)。
|
|
390
|
+
*/
|
|
391
|
+
function generatedPersona(row, reason) {
|
|
392
|
+
const name = row.name || row.plugin;
|
|
393
|
+
const profession = row.profession || "该领域的专家";
|
|
394
|
+
const description = row.description || "(专家中心没有为它提供介绍文字)";
|
|
395
|
+
const category = row.categoryName || row.categoryId || "";
|
|
396
|
+
const tags = Array.isArray(row.tags) ? row.tags.filter(Boolean) : [];
|
|
397
|
+
const prompts = Array.isArray(row.quickPrompts) ? row.quickPrompts.filter(Boolean) : [];
|
|
398
|
+
const overridePath = overridePersonaPath(row.plugin).replace(/\\/g, "/");
|
|
399
|
+
const lines = [
|
|
400
|
+
`# ${name}(${profession})`,
|
|
401
|
+
"",
|
|
402
|
+
`> **这份人设不是原文。**${reason};本机 WorkBuddy 缓存里也没有它。`,
|
|
403
|
+
"> 下面的内容由 WorkBuddy 专家中心公开的介绍、标签与示例问题整理而成,",
|
|
404
|
+
"> 只能还原「大致是谁、负责什么」,不等同于原作者写的工作方法与铁律。",
|
|
405
|
+
`> 拿到原始人设后,放到 \`${overridePath}\` 即可自动改用原文。`,
|
|
406
|
+
"",
|
|
407
|
+
"## 身份",
|
|
408
|
+
`你是「${name}」,身份是「${profession}」${category ? `,属于「${category}」` : ""}。`,
|
|
409
|
+
"",
|
|
410
|
+
"## 你负责什么",
|
|
411
|
+
description,
|
|
412
|
+
"",
|
|
413
|
+
"## 工作原则",
|
|
414
|
+
"- 只做上面这段职责范围内的事;被问到范围外的内容时说明边界并给出替代方向,不冒充全才。",
|
|
415
|
+
"- 这不是原作者人设:不要声称掌握原作者未公开的资料、模板或内部流程,拿不准就直说。",
|
|
416
|
+
"- 先确认目标、已有输入与验收标准,再动手;信息不足时先问最关键的那一个。",
|
|
417
|
+
"- 给结论时附上依据与可执行的下一步,不写空泛的鼓励语。",
|
|
418
|
+
];
|
|
419
|
+
if (tags.length) lines.push(`- 额外关注:${tags.join("、")}。`);
|
|
420
|
+
if (prompts.length) lines.push("", "## 用户常这样开始", ...prompts.map((prompt) => `- ${prompt}`));
|
|
421
|
+
lines.push(
|
|
422
|
+
"",
|
|
423
|
+
"## 开场",
|
|
424
|
+
"第一次对话先用一句话说明自己是谁、能做什么,然后按上面的原则推进;不要主动展开与任务无关的话题。",
|
|
425
|
+
);
|
|
426
|
+
return `${lines.join("\n")}\n`;
|
|
427
|
+
}
|
|
428
|
+
|
|
338
429
|
// ── 专家详情:人设正文 + 捆绑技能清单 ──────────────────────────────────
|
|
339
430
|
// 召唤前给用户看的全部真实内容:人设 MD 原文、plugin.json 的技能声明、quickPrompts。
|
|
340
431
|
export async function wbExpertDetail(payload) {
|
|
@@ -356,13 +447,35 @@ export async function wbExpertDetail(payload) {
|
|
|
356
447
|
if (!row.agentName && pluginJson?.agentName) row.agentName = String(pluginJson.agentName);
|
|
357
448
|
const promptFile = String(row.promptFile || (pluginJson ? `/plugins/${plugin}/agents/${pluginJson.agentName || plugin}.md` : "")).trim();
|
|
358
449
|
if (!promptFile) throw new Error(`专家 ${plugin} 没有人设文件路径(promptFile 缺失)`);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
450
|
+
// 取数顺序:本机覆盖 → 本机 WorkBuddy 缓存 → 公开分发地址 → 兜底生成。
|
|
451
|
+
// 上游 185/429 没有公开分发人设(issue #5),所以「三条路都空」是常态而非异常:
|
|
452
|
+
// 这时给一份明确标注非原文的替身,保证专家至少能看详情、能召唤,不再抛 404。
|
|
453
|
+
let persona = (await overridePersona(plugin)) || "";
|
|
454
|
+
let personaSource = persona ? "override" : "";
|
|
455
|
+
let personaNotice = "";
|
|
456
|
+
if (!persona) {
|
|
457
|
+
persona = (await localExpertPersona(plugin, row.agentName || pluginJson?.agentName)) || "";
|
|
458
|
+
if (persona) personaSource = "workbuddy-cache";
|
|
459
|
+
}
|
|
460
|
+
if (!persona) {
|
|
461
|
+
try {
|
|
462
|
+
const fetched = await fetchText(EXPERT_ORIGIN + promptFile);
|
|
463
|
+
if (fetched.trim()) {
|
|
464
|
+
persona = fetched;
|
|
465
|
+
personaSource = "cdn";
|
|
466
|
+
} else {
|
|
467
|
+
personaNotice = "公开分发地址上的人设文件是空的";
|
|
468
|
+
}
|
|
469
|
+
} catch (error) {
|
|
470
|
+
personaNotice = describePersonaFailure(error);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
if (!persona) {
|
|
474
|
+
persona = generatedPersona(row, personaNotice);
|
|
475
|
+
personaSource = "generated";
|
|
476
|
+
personaNotice = personaNotice || "原文不可用";
|
|
364
477
|
}
|
|
365
|
-
if (!persona.trim()) throw new Error("
|
|
478
|
+
if (!persona.trim()) throw new Error("人设正文为空");
|
|
366
479
|
const skillNames = Array.isArray(pluginJson?.skills)
|
|
367
480
|
? pluginJson.skills.map((entry) => basename(String(entry).replace(/\/+$/, ""))).filter(Boolean)
|
|
368
481
|
: [];
|
|
@@ -374,6 +487,8 @@ export async function wbExpertDetail(payload) {
|
|
|
374
487
|
promptFile,
|
|
375
488
|
persona,
|
|
376
489
|
personaChars: persona.length,
|
|
490
|
+
personaSource,
|
|
491
|
+
personaNotice,
|
|
377
492
|
version: String(pluginJson?.version || ""),
|
|
378
493
|
skills,
|
|
379
494
|
avatarPluginUrl: pluginJson?.avatar ? `${EXPERT_ORIGIN}/plugins/${encodeURIComponent(plugin)}/${String(pluginJson.avatar).replace(/^\//, "")}` : row.avatarUrl,
|
package/lib/whats-new-en.js
CHANGED
|
@@ -448,6 +448,34 @@ export const WHATS_NEW_EN = {
|
|
|
448
448
|
where: 'Floating button / Panel -> Entries',
|
|
449
449
|
},
|
|
450
450
|
],
|
|
451
|
+
'2.4.2': [
|
|
452
|
+
{
|
|
453
|
+
text: '**Documentation release**: the README (Chinese and English) now matches what actually ships — the three entry seats with six modes, hiding the floating button by right-click or long-press, how it steps aside while the board occupies the centre column, and the 2.4.1 SkillHub detail fixes. Runtime code is identical to 2.4.1; nothing changes in behaviour',
|
|
454
|
+
where: 'Project README',
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
text: '**A new FAQ entry**: if the detail dialog is still blank after upgrading, confirm the installed package version and then quit DSH completely and start it again — the market field mapping lives in host-side modules loaded once at process start, so reloading the panel is not enough',
|
|
458
|
+
where: 'README -> FAQ',
|
|
459
|
+
},
|
|
460
|
+
],
|
|
461
|
+
'2.4.3': [
|
|
462
|
+
{
|
|
463
|
+
text: '**Summoning an expert is no longer blocked by an upstream 404**: the persona now comes from "local WorkBuddy cache first, public distribution URL second". Roughly four in ten experts in the upstream directory (185 of 429) have no publicly distributed persona file at all, which used to fail with "failed to fetch persona" every time; now, as long as your local WorkBuddy has used that expert, its detail opens and it can be summoned (issue #5)',
|
|
464
|
+
where: 'Experts -> Detail / Summon',
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
text: '**An expert whose original persona is unavailable is still always usable**: when all three proper sources (local override, local WorkBuddy cache, public distribution) are empty, a **stand-in persona** is built from the public description, tags and sample prompts of the expert center. Its first paragraph states that this is not the original text and gives the path where the original belongs, so the expert can be viewed and summoned normally instead of turning into a dead 404. 185 of the 429 upstream experts fall into this case (issue #5)',
|
|
468
|
+
where: 'Experts -> Detail / Summon',
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
text: '**New local override**: `~/.dsh/wb-market/experts/overrides/<plugin>.md` has the highest priority — drop the original persona there (copied from another machine, exported from WorkBuddy, or written yourself) and it is used automatically, with the detail source labelled "local override"; delete the file to fall back to cache, distribution or the stand-in. The plugin name is sanitised, so no name can climb out of the directory (issue #5)',
|
|
472
|
+
where: 'Experts -> Detail',
|
|
473
|
+
},
|
|
474
|
+
{
|
|
475
|
+
text: '**Two README updates (Chinese and English)**: the experts section now states the resolution order (local override, WorkBuddy cache, public distribution, stand-in) and how the stand-in is labelled, and the FAQ gains "what does it mean when the detail says this is not the original text", with the path to restore the original; the FAQ correction left over from the previous release is in the npm package this time too',
|
|
476
|
+
where: 'README -> Experts / FAQ',
|
|
477
|
+
},
|
|
478
|
+
],
|
|
451
479
|
};
|
|
452
480
|
|
|
453
481
|
/**
|
package/lib/whats-new.js
CHANGED
|
@@ -516,4 +516,38 @@ export const WHATS_NEW = [
|
|
|
516
516
|
},
|
|
517
517
|
],
|
|
518
518
|
},
|
|
519
|
+
{
|
|
520
|
+
version: '2.4.2',
|
|
521
|
+
items: [
|
|
522
|
+
{
|
|
523
|
+
text: '**文档版**:README(中 / 英)与实机功能对齐——三个入口席位与六档切换、悬浮按钮右键 / 长按隐藏、看板占据中栏时自动让位,以及 2.4.1 的 SkillHub 详情修正都写进了说明;运行代码与 2.4.1 完全相同,本次没有任何行为变化',
|
|
524
|
+
where: '项目主页 README',
|
|
525
|
+
},
|
|
526
|
+
{
|
|
527
|
+
text: '**新增一条常见问题**:升级后详情页仍空白时,先确认已安装的包版本,再完全退出 DSH 重新启动——市场的字段映射在宿主侧模块里,只在进程启动时加载一次,只刷新面板不会生效',
|
|
528
|
+
where: 'README → 常见问题',
|
|
529
|
+
},
|
|
530
|
+
],
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
version: '2.4.3',
|
|
534
|
+
items: [
|
|
535
|
+
{
|
|
536
|
+
text: '**召唤专家不再被上游 404 挡住**:人设改为「本机 WorkBuddy 缓存 → 公开分发地址」取数。上游目录里约四成专家(429 位中的 185 位)其实没有公开分发人设文件,以前一律报「拉取人设失败」,现在只要本机 WorkBuddy 用过这位专家就能正常看详情、正常召唤(issue #5)',
|
|
537
|
+
where: '专家 → 详情 / 召唤',
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
text: '**拿不到原文的专家也一定能用**:三条正路(本机覆盖 / 本机 WorkBuddy 缓存 / 公开分发)都空时,用专家中心公开的介绍、标签与示例问题生成一份**兜底人设**,正文第一段就写明「这份人设不是原文」,并附上原作者人设的存放路径;召唤照常可用,不再弹 404 把专家变成摆设。上游 429 位里有 185 位属于这种情况(issue #5)',
|
|
541
|
+
where: '专家 → 详情 / 召唤',
|
|
542
|
+
},
|
|
543
|
+
{
|
|
544
|
+
text: '**新增本机覆盖**:`~/.dsh/wb-market/experts/overrides/<包名>.md` 优先级最高——拿到原始人设(从别的机器、从 WorkBuddy 导出或自己写的)放进去就自动改用原文,详情来源标注「本机覆盖」;删掉文件即回到缓存 / 分发 / 兜底。包名经过净化,不存在借名字穿越目录(issue #5)',
|
|
545
|
+
where: '专家 → 详情',
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
text: '**README(中 / 英)补两处**:专家一节写明「本机覆盖 → WorkBuddy 缓存 → 公开分发 → 兜底人设」的取数顺序与兜底人设的标注方式,常见问题新增「详情里写着『这份人设不是原文』怎么办」并给出换回原文的路径;上一版遗留的那条 FAQ 校正也一并进了 npm 包',
|
|
549
|
+
where: 'README → 专家 / 常见问题',
|
|
550
|
+
},
|
|
551
|
+
],
|
|
552
|
+
},
|
|
519
553
|
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-armory",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.3",
|
|
4
4
|
"description": "Unified Skill + MCP + Expert + Plugin board for DeepSeek Harness (desktop app and Web GUI) — custom skill suites, skill install/uninstall with live refresh, global panel page, JSON import, WorkBuddy connector & SkillHub & Expert & DSH community plugin market installs, MCP OAuth authorization, tool-usage tailor with wire-tax trends, and profile-backed Host Remote management.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|