dsh-armory 2.4.2 → 2.4.4

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 CHANGED
@@ -110,11 +110,13 @@ Experts (WorkBuddy expert center, 429 experts / 15 industries; category filter +
110
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
111
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)
112
112
  - **WB Market (direct installs)**: a third board tab with two markets in one place —
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**
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**. Before installing, a connector that pins a local executable is checked first: a missing file or unsupported platform is blocked with the exact path instead of being written and then losing its tools after ten reconnect attempts (issue #3). Cards report the **real connection state** — connected / needs authorization / not connected — and a 401/403 offers Re-authorize instead of a reconnect that cannot help; details show the authorization expiry and can refresh it, writing the new credential back to the config
114
+ - **Community MCP (official Registry, new in 2.4.4)**: switch the Connectors tab to community entries from the official MCP Registry, with no WorkBuddy account; keyword search, cursor pagination, an "only directly runnable (npx / uvx)" filter, details with the launch command, args, environment variables and runnability, and "Add MCP" that only prefills the form and writes nothing until you confirm. Community entries are not reviewed by the Armory, and a permanent notice says so; the data layer accepts only active, runnable entries and https repository links
114
115
  - **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
115
116
  - Skills belong to their respective authors. Both upstreams are third-party interfaces whose fields may change; the panel carries a persistent note saying so
116
117
  - **Experts (direct, 1.9.0)** — a dedicated board tab (the sidebar entry is renamed **Skills · MCP · Experts**):
117
118
  - **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
119
+ - **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).
118
120
  - **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
119
121
  - **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
120
122
  - **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
@@ -122,7 +124,7 @@ Experts (WorkBuddy expert center, 429 experts / 15 industries; category filter +
122
124
  - **Summon menu (in-session quick access, enhanced in 1.9.3)** — the small board icon at the right of the composer toolbar opens three categories (**Skills / MCP / Experts**); hovering a category expands its submenu, and clicking an entry writes a reference into the composer (skills = `/skill-name`, MCP = names the `mcp__server__*` tools, experts = attaches to the current session):
123
125
  - **Six rows per screen, scrollable**: a submenu shows six entries at a time and scrolls for the rest (thin themed scrollbar), while the **Manage skills / MCP / experts…** button stays pinned to the bottom instead of scrolling away
124
126
  - **Most-recently-used first**: entries you just used float to the top with a "recent" badge, the rest keep their original order; the recency pool holds 40 entries
125
- - **Experts attach / swap / detach at any time**: click one to take over the current session (including one already mid-conversation), click another to replace it, click the chip's × to drop it. It affects **only that session** — no tool catalog changes, nothing persisted
127
+ - **Experts attach / swap / detach at any time**: click one to take over the current session (including one already mid-conversation), click another to replace it, click the chip's × to drop it. It affects **only that session** — no tool catalog changes and no profile edits. The choice is remembered per session in `~/.dsh/wb-market/experts/session-persona.json` (only which session has which expert): switching sessions, restarting the host, or an agent rebuild after context compaction brings the expert back automatically; only the × button cancels it for good. Stand-in personas are never persisted
126
128
  - **What you see is what's active**: once an expert is attached, the session header shows the expert that is **actually in effect** (the host's "preset chosen at session creation" label steps aside while an expert is attached); the header badge, the composer chip and the menu stay in sync within the same frame after attach / swap / detach
127
129
  - **Plugins page (new in 2.0.0; DSH community only since 2.3.x)**: one searchable, filterable directory backed by the `awesome-dsh-plugins` list, each entry labelled with whether it can be installed —
128
130
  - **DSH community**: the `awesome-dsh-plugins` list (a single bare-JSON file, 5000+ entries, jsdelivr primary → fastly fallback), slimmed to `SLIM_MAX_BYTES = 3MB` before caching; update checks resolve `main` to the latest commit SHA via the GitHub API and fetch from the immutable `@<SHA>` URL (bypassing jsDelivr's 12h CDN cache on branch URLs; falls back to the branch URL + conditional ETag requests when the API is unreachable)
@@ -138,6 +140,7 @@ Experts (WorkBuddy expert center, 429 experts / 15 industries; category filter +
138
140
  - **Skill board categories (new in 2.0.0)**: skills are grouped into **dev / design & creation / docs & office / productivity & automation / ops / uncategorised**, with grid and list views, a category filter and a persistent "showing N/M skills" line. Details add the category, source directory and file location, with one-click "copy SKILL.md path" and "copy @session reference"
139
141
  - **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
140
142
  - **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
143
+ - **Model-side skill disable / release (new in 2.4.4)**: in the Tool Tailor's skill ledger, the inline Disable button writes `disable-model-invocation: true` into the `SKILL.md` frontmatter (the host's official key), so the model no longer loads that skill or pays its context tax, while manual `/` references keep working; Release removes the key and restores it. Only user-level and project-level standard skills roots are accepted: source allowlist → absolute path with strict root containment → realpath must stay inside; `bundled` / `runtime` / `custom` skills get no button. Duplicate keys are collapsed and every other byte, including line endings, is preserved
141
144
  - **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
142
145
  - **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)
143
146
  - **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
@@ -155,9 +158,11 @@ Experts (WorkBuddy expert center, 429 experts / 15 industries; category filter +
155
158
  - **Jump to the end**: a "Jump to end" pill stays in the modal's bottom-right corner (sticky inside the dialog, keyboard-focusable, smooth scroll); at the bottom it rests below Close / Install / Reload rather than covering that row
156
159
  - **Community directory and update-probe fixes (2.1.0)**: the instant-open snapshot no longer shadows the real list (previously the real result was dropped once the snapshot painted, leaving the directory stuck on the old snapshot), and update probing now follows the same source chain as the directory itself (it asks the source the cache actually came from, then falls back to the others, first ETag wins) — fixing the "directory opens but every update check says `probe-failed`" trap on machines where the primary source is unreachable
157
160
  - **Who made it, and is it still maintained? (new in 2.3.0)**: every market card carries a zero-network "people" signal first — the publisher's avatar / name and last-updated date (SkillHub publisher or GitHub repo owner for skills, repo owner for plugins and community entries, the directory's own avatar and update time for experts). Opening a detail pane then makes one on-demand call to the public GitHub API to add the maintainer's profile, last commit, open issues, stars, license and primary language, plus an honest badge for **committed in the last 30 days / no update for over 6 months / archived**. Requests are cached for 6 hours and reuse ETags, at most 8 repositories per call; unauthenticated rate limits fall back to the old cache and say so. A lookup failure only hides that row — it never blocks the detail body
158
- - **Recent activity (new in 2.3.0)**: a timeline at the top of the Market page that belongs only to this machine — it compares the last successful directory load with this one and reports added, removed, and version or verification-status changes, with entry names and relative timestamps. No network, no telemetry, no invented online counts or live feed; when nothing changed it says so. Events expire after 7 days, at most 8 are kept, and you can clear them in one click. Skills are only recorded on the default page with no keyword and the default sort, so paging and searching cannot manufacture fake activity
161
+ - **Recent activity (new in 2.3.0)**: a timeline at the top of the Market page that belongs only to this machine — it compares the last successful directory load with this one and reports added, removed, and version or verification-status changes, with entry names and relative timestamps. No network, no telemetry, no invented online counts or live feed; when nothing changed it says so. Events expire after 7 days, at most 8 are kept, and you can clear them in one click. Skills are only recorded on the default page with no keyword and the default sort, so paging and searching cannot manufacture fake activity; clicking an entry switches to that tab and clears its search, filters, sort and page so you land on the unfiltered full market
159
162
  - **Loadout (new in 2.3.0)**: the "Loadout" button in the Market header exports this machine's MCP servers, skills, experts and plugins as a shareable JSON file — names, types, sources, versions and the minimum identity fields only. It **never contains keys, headers, URL query parameters or environment-variable values**, and skill bodies and expert personas stay out too. A friend's loadout can be pasted or opened from a file; the panel compares it item by item as `installed / update available / not installed`, and "Find in market" only jumps to the matching market with a search term — it **never installs or writes configuration automatically**. Capped at 200 items / 256KB, with truncation labelled
160
163
  - **Reach real people (new in 2.3.0)**: detail panes open with real exits — a repository and its discussions / issues when one can be resolved, the upstream homepage when there is one, and a prefilled GitHub issue to the Armory for any entry; you can also copy the feedback template (entry, type, source, version, environment) and edit it before posting. All links open in a new tab, and you see the content before anything is submitted. There is deliberately **no in-app forum, likes or bookmarks**: send people to where the community already is instead of building an empty stage inside the plugin
164
+ - **Faster market loading (2.4.4 optimization)**: the host-side market and expert data layers now load on first use; the first paint prefetches only the current tab (the unconditional 400ms prefetch of plugin and expert directories is gated); the plugin snapshot compares a signature, is written on an idle frame and has a 4.5MB budget; the skill list uses stale-while-revalidate; the connector count is cached for 10 minutes; the Tool Tailor report is cached per `days`, deduplicates concurrent calls and supports a `refresh` bypass; hovering a card prefetches its details, and switching categories reuses loaded data. Diagnosis, measurements and per-item rollback switches are in [market load performance](docs/perf-market-load.md)
165
+ - **Security hardening (2.4.4)**: external links go through one allowlist — `https` only, `http` only for loopback, and `javascript:` / `file:` / `data:` are rejected before any process starts; `revealSkill` accepts only a skill name and scope, with the path resolved by the host registry; community repository links are https-only; skill-disable writes are pinned to the four standard skills roots and verified by realpath
161
166
  - Import MCP configuration from other clients installed on this machine: Claude Code, Codex (`config.toml`), OpenCode (including `.jsonc`), pi, Claude Desktop, Cursor, Windsurf, VS Code, Gemini CLI, Roo Code, and the cross-tool shared config. Everything is previewed before writing, with "merge" and "replace" modes
162
167
  - Follows the DSH dark/light theme and adapts to narrow/mobile widths
163
168
  - Update notice and **one-click upgrade**: a dismissible banner when a newer release exists (at most one check per day; disable with `DSH_ARMORY_DISABLE_UPDATE_CHECK`). Nothing happens until you press Upgrade — it **never auto-updates**; the upgrade itself is executed by DSH's official pluginManager, which handles version checks and rollback. Local dev copies installed via `link:` / `file:` / `github:` get no button (it would replace your link with an npm package)
@@ -236,7 +241,10 @@ The detail pane lists the tools a server currently registers; expand one for its
236
241
  That server is disabled, so it registers no tools. Enable it in the panel.
237
242
 
238
243
  **I upgraded but the skill detail is still blank, or the floating button behaves as before.**
239
- Check two things. First, that the new package actually landed: after `dsh plugin --profile web update dsh-armory`, look at the version at the bottom of the panel. 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.
244
+ 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.
245
+
246
+ **Opening an expert, the detail says this persona is not the original text?**
247
+ 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.
240
248
 
241
249
  **How do I upgrade? Why did the panel not notify me?**
242
250
  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.
@@ -270,6 +278,7 @@ The plugin ships Chinese (source language) and English:
270
278
  - [Installation and upgrades](docs/installation.md) (Chinese)
271
279
  - [JSON import](docs/json-import.md) (Chinese)
272
280
  - [Design and limits](docs/design.md) (Chinese)
281
+ - [Market load performance](docs/perf-market-load.md) (Chinese)
273
282
  - [Official DeepSeek Harness plugin publishing guide](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md)
274
283
 
275
284
  ## Links
package/README.md CHANGED
@@ -101,11 +101,13 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
101
101
  - **升级后主动说一次变了什么**:版本变了后第一次打开面板弹一张小卡片,列出本次更新内容,并指路新功能在哪(例如「入口」开关在面板右上角);确认一次后不再提示,不联网、不发任何数据
102
102
  - **工具裁缝**(1.7.0 新增):扫描本机会话日志(解析 `tool/call` / `tool/result` / `request/header` 三类事件,不读消息正文),统计每个工具近 7/30/90 天的调用次数、错误率与最后使用时间;上下文税给**两个口径**——按当前注册表估算的 Schema 快照(它是 Schema 长度的纯函数,只有改动注册表才会变),以及按天采样 `request/header` 得到的每轮真实下发清单税,两者差额非零时说明栏指出「改了没生效 / 线上下发的比注册表多」;窗口内零调用的 MCP 工具自动进「死工具清单」,行内可一键禁用/启用对应服务器(复用官方写链,随时可恢复)。**默认显示全部工具与真实调用次数**,零调用的行以底色标出;想只看死工具时点「只看零调用(N)」切换。顶部说明栏常驻回显「显示 N/M 个工具」,避免筛选态被误读成「所有计数都是 0」;本机日志覆盖不足窗口天数、或有条目缺时间戳(`undatedCalls`)时也在这里显形,不再静默。账本缓存行只读(「清空缓存」按钮已删——实测既不回收空间也不修任何事)。全程只读,多帧 zstd 日志逐帧解析、个别帧损坏跳过不中断
103
103
  - **WB 市场(直连安装,1.8.0 新增)**:看板第四个分类,两个市场一处浏览——
104
- - **连接器(MCP)**:直读 WorkBuddy 官方分发 ZIP(`static.workbuddy.cn`,与 WorkBuddy 桌面端同一数据源),316 个连接器按需解析;可安装的 242 个(streamable-http 为主),CLI 型 / 需 WorkBuddy token 注入的 74 个如实标注「仅展示」并给出原因。安装 = 把该连接器的 `mcpServers` 合并写入 MCP 配置,与「导入 JSON」同一链路(准入、同名跳过、entry id 预留一致),全局与项目作用域都可选;ZIP 按 ETag 缓存在 `~/.dsh/wb-market/`,解压用 Node 内置 zlib,**零新增运行时依赖**
104
+ - **连接器(MCP)**:直读 WorkBuddy 官方分发 ZIP(`static.workbuddy.cn`,与 WorkBuddy 桌面端同一数据源),316 个连接器按需解析;可安装的 242 个(streamable-http 为主),CLI 型 / 需 WorkBuddy token 注入的 74 个如实标注「仅展示」并给出原因。安装 = 把该连接器的 `mcpServers` 合并写入 MCP 配置,与「导入 JSON」同一链路(准入、同名跳过、entry id 预留一致),全局与项目作用域都可选;ZIP 按 ETag 缓存在 `~/.dsh/wb-market/`,解压用 Node 内置 zlib,**零新增运行时依赖**。安装前预检本地客户端型连接器写死的本机程序——缺文件 / 平台不符直接拦住并说明缺哪个路径,不再写进配置后重连十次注销工具(issue #3);卡片状态按**真实连接态**区分「已连接 / 需授权 / 未连接」,401/403 就地给「重新授权」而不是让你反复重连,详情可看授权有效期并「刷新授权」把新凭据写回配置
105
+ - **社区 MCP(官方 Registry,2.4.4 新增)**:连接器页可切到官方 MCP Registry 的社区条目,不依赖 WorkBuddy 账号;关键词搜索 + 游标分页 + 「只看可直接运行(npx / uvx)」,详情给出启动命令、参数、环境变量与可运行性,点「加入 MCP」只预填表单、确认后才写盘。社区条目未经军械库审核,来源行与详情常驻声明;数据层只接受 active 且可运行的条目,仓库链接仅放行 https
105
106
  - **技能(SkillHub)**:直读 SkillHub 公开 API(`api.skillhub.cn`,19 万+ 技能),支持搜索(`keyword`)、排序(下载/安装/星标/评分)、分页;详情含发布方认证与安全扫描状态。安装 = 逐文件下载并按清单 sha256 校验后写入 `~/.agents/skills/`(与官方 skill 子系统同一发现范围),装完即刻生效;已装的显示「已安装」,可一键卸载、重装即更新。下载量排序在**当前页内**本地完成(上游 `sortBy=downloads` 现在会挂起),其余排序照常走远程;单次请求 15 秒超时,超时文案已中文化
106
107
  - 技能版权归原作者所有;两个均为第三方接口,字段可能随上游改版变化(面板顶部有常驻说明)
107
108
  - **专家直连(1.9.0 新增,体验对齐 WorkBuddy 专家中心)**:看板独立分类「专家」(侧栏入口同步更名「技能 · MCP · 专家」)——
108
109
  - **目录**:直读 WorkBuddy 专家中心官方分发(`expert_center.json`,429 位专家 / 15 个行业分类,ETag 缓存在 `~/.dsh/wb-market/experts/`),分类筛选 + 关键词搜索 + 详情弹层(召唤前看人设正文、捆绑技能、试试这样问)
110
+ - **人设来源(2.4.3)**:详情与召唤按「本机覆盖 → 本机 WorkBuddy 缓存(`~/.workbuddy/plugins/cache/experts/<包>/<版本>/agents/`)→ 公开分发地址 → 兜底人设」取数。上游目录里约四成专家(429 位中的 185 位,例如「技能匠人」skill-smith)其实没有公开分发人设文件;本机 WorkBuddy 用过它就直接读缓存,三条正路都没有时会用专家中心公开的介绍、标签与示例问题生成一份**兜底人设**,正文第一段就写明「这份人设不是原文」,保证任何一位专家都能看详情、能召唤(issue #5)。
109
111
  - **召唤** = 往 profile 补丁写入一条**独立 Agent 预设**(`@deepseek-ai/dsh-agent-preset` 行,plugins 复刻内置 standard 预设、仅 persona 的 prefix 换成专家人设全文)——新建会话时选择「WorkBuddy 专家 · …」即专家接管该会话,标准工具/规划/压缩/委派原样保留;多个专家可共存,写入走既有 patch 写链(文件锁 + 版本校验 + 原子写),其余条目、注释与 `!!js` 表达式原样保留
110
112
  - **捆绑技能**:召唤时可勾选一并安装——本机 WorkBuddy 缓存(`~/.workbuddy/plugins/cache/experts/`)有完整技能树就整目录复制到 `~/.agents/skills/`(`wbexpert__` 前缀,即刻被技能注册表发现);无缓存时按 CDN 的 SKILL.md 单文件兜底并如实标注来源
111
113
  - **团队型专家(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 份人设白付上下文费),只在调度时按需读取
@@ -113,7 +115,7 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
113
115
  - **召唤菜单(会话内快速调用,1.9.3 增强)**:会话输入框工具行右侧的看板小图标 → 「技能 / MCP / 专家」三分类,悬停展开子菜单,点一条即把引用写进输入框(技能 = `/技能名`、MCP = 点名 `mcp__服务__*`、专家 = 挂到当前会话)——
114
116
  - **每屏 6 行 + 滚动**:子菜单一次显示 6 条,超出的往下滚(细滚动条跟随主题);「管理技能 / MCP / 专家…」固定在底部,不被列表滚走
115
117
  - **最近使用置顶**:刚用过的条目自动排到最前并带「最近」标记,其余保持原有顺序;最近使用记录池 40 条
116
- - **专家随时挂 / 换 / 摘**:点一个专家即接管当前会话(包括已经聊了一半的),再点别的直接替换,点 chip 的 × 立刻取消;**只影响这一个会话**,不动工具目录、不写任何持久化配置
118
+ - **专家随时挂 / 换 / 摘**:点一个专家即接管当前会话(包括已经聊了一半的),再点别的直接替换,点 chip 的 × 立刻取消;**只影响这一个会话**,不动工具目录与 profile 配置。选择会随会话记住(`~/.dsh/wb-market/experts/session-persona.json` 只记「哪个会话挂了谁」):切换会话、宿主重启、上下文压缩后 agent 重建时自动把专家补回来,不需要重新勾选;点 × 才是真正永久取消
117
119
  - **显示与实效一致**:挂专家后,会话标题栏显示的始终是**当前真正生效**的专家(宿主那条「会话创建时的预设」标签在挂载期间自动让位);三处显示(标题栏徽章、输入框 chip、菜单)挂/换/摘后同帧同步
118
120
  - **插件市场(2.0.0 新增;2.3.x 只保留 DSH 社区)**:新增「插件」页,直连 `awesome-dsh-plugins` 社区清单,可搜索、可筛选,每条标明可装性——
119
121
  - **DSH 社区**:`awesome-dsh-plugins` 社区清单(单文件裸 JSON、五千余条,jsdelivr 主源 → fastly 备源),拉取后瘦身到 `SLIM_MAX_BYTES = 3MB` 再落缓存;更新检测先经 GitHub API 把 `main` 解析到最新提交 SHA、再按 `@<SHA>` 不可变地址取数(绕开 jsdelivr 对分支地址的 12h CDN 缓存,API 不可达时回落分支地址 + ETag 条件请求)
@@ -128,6 +130,7 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
128
130
  - **安装状态账本(2.0.0 新增)**:`~/.dsh/armory/install-state.json`(`INSTALL_STATE_VERSION = 1`)记录每条连接器 / 技能 / 插件的 `source {marketplace, url, kind}`,市场页据此支持**跨页**筛出已安装项(技能侧仍只筛当前页,两处文案分别说明),并把「本插件装的」与「别处手动配的」分开;登记失败不影响安装,只补一句提示
129
131
  - **技能看板分类(2.0.0 新增)**:技能按 **编程开发 / 设计与创作 / 文档办公 / 效率与自动化 / 开发运维 / 未分类** 六类归置,网格与列表双视图可切、可按分类过滤,常驻「显示 N / M 个 skill」;详情新增所属分类、来源目录、文件位置,可一键「复制 SKILL.md 路径」「复制 @会话引用」
130
132
  - **技能卸载(2.2.0 新增)**:用户级 / 项目级目录里的 skill 可在详情里直接卸载(就地二次确认、**永久删除且不可撤销**);随 DSH 分发、运行时注册与自定义目录的 skill 只读,并说明不在可卸载范围内。宿主本身只提供读取接口,卸载由本插件的 `removeSkill` 完成:来源白名单 → 根目录严格包含性 → 父目录 realpath → 符号链接只 unlink 不碰目标 → 目录必须含 `SKILL.md` 且在根内
133
+ - **技能模型侧禁用 / 释放(2.4.4 新增)**:工具裁缝的技能账本里,行内「禁用」写 `SKILL.md` frontmatter 的 `disable-model-invocation: true`(宿主 `dsh-skill-filesystem` 官方键),模型不再加载该技能、不再缴它的上下文税,输入框手动 `/引用` 不受影响;「释放」移除该键即恢复。只对用户级 / 项目级标准 skills 根开放:来源白名单 → 绝对路径 + 根目录严格包含 → realpath 不得出根;`bundled` / `runtime` / `custom` 不出按钮,重复键统一收敛,其余字节与换行风格原样保留
131
134
  - **技能集合实时刷新(2.2.0 新增)**:市场安装 / 卸载技能、看板自己卸载,三处都会向模块级变更总线广播;顶部 **Skill** 数量角标与看板列表订阅同一条总线,各自重读真值,角标重取带序号守卫,快速连点也不会被乱序回包回滚。装完 / 卸完立刻对新集合,不必切页或重开面板
132
135
  - **技能安装可辨识(2.4.0 新增)**:Skill 看板每张卡片 / 列表行显示「装于 …」——7 天内绿色高亮并给相对时间(「3 小时前装」),30 天内显示「N 天前装」,更早给绝对日期。时间优先取安装状态账本登记的首次安装时间,其次目录创建时间,最后目录修改时间;随 DSH 分发 / 运行时注册的技能没有安装事件,不显示徽标。筛选条新增「最近安装」时间线,按安装时间倒序平铺;看板名(取自 `SKILL.md` 的 `name:`)与账本登记的市场名不一致时,卡片出现「来自市场 原名」徽标,详情面板新增「市场原名」行。数据由新增 RPC `skillInstallInfo` 提供(宿主自扫标准技能根目录、只读每个 `SKILL.md` 头部 4KB 解析 `name:`),宿主需重启一次才注册;未注册时看板显式提示,不静默
133
136
  - **技能详情与市场主页修正(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)
@@ -146,9 +149,11 @@ dsh plugin --profile web add github:2026heshao/dsh-armory
146
149
  - **长文跳转**:弹层右下角常驻「跳到末尾」按钮(sticky 在弹层内,滚动时不消失,键盘可聚焦),点一下平滑滚到 README 底部;贴底时按钮排在「关闭 / 安装 / 重新读取」之后,不会盖住操作行
147
150
  - **社区目录与更新探测修正(2.1.0)**:秒开快照不再顶掉真实目录(此前快照一渲染真实结果就被丢弃,目录于是一直停在旧快照);更新探测与目录改走同一条源链(先问这份缓存实际来自哪个源、再兜底其余源,首个拿到 ETag 的源胜出),修掉「主源不通的机器上目录能开、点检查更新却每次 `probe-failed`」
148
151
  - **谁在做、还在维护吗(2.3.0 新增)**:市场卡片先给一层不联网的「人」信号——发布方头像 / 名称与最近更新日期(技能看 SkillHub 发布方或 GitHub 仓库 owner,插件与社区条目看仓库 owner,专家看目录自带头像与更新时间);打开详情再按需查一次 GitHub 公开接口,补上维护者主页、最近提交、开放 issue 数、Star、License、主语言,并用标签直说「近 30 天有提交 / 超过半年未更新 / 已归档」。请求按 6 小时缓存与 ETag 复用,单次最多 8 个仓库,未认证限流时回落旧缓存并标明;查不到只收起这一行,不阻塞详情正文
149
- - **最近动静(2.3.0 新增)**:市场页顶部有一条只属于这台机器的时间线——对比「上次成功读取目录」与「这一次」的新增、移除、版本或核验状态变化,并标出条目名与相对时间。它不联网、不埋点、不伪造在线人数或实时消息;没有变化就直说「暂无新变化」。事件 7 天过期、最多保留 8 条,可一键清除;技能只在默认页 / 无关键词 / 默认排序时记录,翻页与搜索不会制造假动静
152
+ - **最近动静(2.3.0 新增)**:市场页顶部有一条只属于这台机器的时间线——对比「上次成功读取目录」与「这一次」的新增、移除、版本或核验状态变化,并标出条目名与相对时间。它不联网、不埋点、不伪造在线人数或实时消息;没有变化就直说「暂无新变化」。事件 7 天过期、最多保留 8 条,可一键清除;技能只在默认页 / 无关键词 / 默认排序时记录,翻页与搜索不会制造假动静;点任一条会切到对应页签并清掉该页签的搜索、筛选、排序与页码,直达未过滤的全量市场,不必自己先清条件
150
153
  - **装备清单(2.3.0 新增)**:市场页右上「装备清单」把本机的 MCP、技能、专家与插件导出成一份可分享的 JSON——只含名称、类型、来源、版本与必要的身份字段,**绝不写入密钥、header、URL 查询参数或环境变量的值**,技能正文与专家人设也不进清单。朋友发来的清单可以粘贴或选文件导入,面板按 `已安装 / 可更新 / 本机没有` 三态逐项对比,`去市场` 只负责跳到对应市场并带上搜索词,**不自动安装、不自动写配置**。上限 200 条 / 256KB,超限截断并标注
151
154
  - **找到真实的人(2.3.0 新增)**:详情底部给出真实出口——能解析到仓库的,给出去仓库、看讨论 / 提 Issue;有来源主页的,给出源站;任何条目都可以「向军械库反馈」(预填 GitHub Issue),或先复制反馈模板(条目、类型、来源、版本、环境)自己改完再发。所有链接在新标签页打开,内容先由用户过目、确认后才提交。**刻意不做站内论坛、点赞或收藏**:社区在哪,就把人送到哪,而不是在插件里搭一个没有人的布景
155
+ - **市场加载提速(2.4.4 优化)**:宿主侧市场 / 专家数据层改为首次调用时按需加载;首屏只预取当前页签(插件与专家目录的 400ms 无条件预取改为门控);插件快照先比签名、在空闲帧写盘并设 4.5MB 预算;技能列表走 SWR;连接器条数加 10 分钟缓存;工具裁缝报告缓存按 `days` 收敛、并发去重并支持 `refresh` 旁路;卡片 hover 预取详情,切分类复用已有数据。完整诊断、实测与逐项回退开关见 [市场加载性能](docs/perf-market-load.md)
156
+ - **安全加固(2.4.4)**:外链统一走白名单——只允许 `https`,`http` 仅限本机回环,`javascript:` / `file:` / `data:` 在启动进程前就被拒绝;`revealSkill` 只接受技能名与作用域,路径由宿主注册表解析;社区条目仓库链接仅放行 https;技能禁用写入面钉死在四类 skills 根并经 realpath 校验
152
157
 
153
158
  ## 安装
154
159
 
@@ -249,7 +254,10 @@ dsh plugin --profile web remove dsh-armory
249
254
  它们把两件独立的事分开说:**连接在不在** —— `已连接 · 当前无会话使用(连接保留,下次直接用)`(最后一个会话结束了,连接按空闲策略留着)/ `已连接 · N 个会话在用 · M 工具` / `连接中…` / `连接失败` / `尚未建立连接(新会话自动挂载)`;**几个会话在用** —— 就是那句里的 `N 个会话在用`。旧版本的「待会话挂载」正是把这两件事压成一句,所以容易被读成"还没连上"。
250
255
 
251
256
  **升级后技能详情页还是空的,或者悬浮按钮的行为没变?**
252
- 两步确认。先确认新包真装上去了:`dsh plugin --profile web update dsh-armory` 之后看面板底部的版本号。再**完全退出 DSH 重新启动**——市场的字段映射在宿主侧模块(`lib/wb-market.js`、`lib/index.js`)里,只在进程启动时加载一次,面板里刷新只会重取界面 JS,宿主那份映射仍是旧的。若只有某个具体技能的介绍仍然缺,欢迎把它的 slug 发到 issue 里,按那条响应单独对一次。
257
+ 两步确认。先确认新包真装上去了:`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 里,按那条响应单独对一次。
258
+
259
+ **点开专家,详情里写着「这份人设不是原文」?**
260
+ 这是兜底人设,不是错误。上游专家中心里约四成专家(429 位中的 185 位,「技能匠人」就在其中)只挂了目录条目,公开分发地址上没有它们的人设文件;本机 WorkBuddy 缓存里也没有时,军械库会用专家中心公开的介绍、标签与示例问题生成一份兜底人设,**保证这位专家仍能看详情、能召唤**,只是工作方法只能还原到「大致是谁、负责什么」。想要原文,把它存成 `~/.dsh/wb-market/experts/overrides/<包名>.md`(例如 `skill-smith.md`)即可,下次打开详情会自动改用原文,来源标注「本机覆盖」;删掉文件就回到缓存 / 分发 / 兜底。正文第一段也会给出这台机器上的确切路径。
253
261
 
254
262
  **怎么升级?为什么面板没提示?**
255
263
  从 npm 装的直接 `dsh plugin --profile web update dsh-armory` 就会升小版本,也可以直接点面板提示条上的「升级」(同一件事,免去敲命令)。面板的提示条只查 GitHub Releases、每天最多一次、可关闭、不会自己动;固定 tag 安装的用户不会自动跨版本,需要用新 tag 重新 `add`(见 [安装与升级](docs/installation.md))。
@@ -284,14 +292,14 @@ dsh plugin --profile web remove dsh-armory
284
292
 
285
293
  ```sh
286
294
  npm install --no-save yaml@2 eslint@9 # 测试与风格检查的唯一裸依赖(运行依赖全部由宿主提供)
287
- npm test # 全 54 套件(与 CI / 发版门槛同一条)
295
+ npm test # 全 65 套件(与 CI / 发版门槛同一条)
288
296
  npm run lint # ESLint:no-undef / no-unused-vars / no-empty 等
289
297
  npm run test:e2e # 可选:用宿主补丁算法验证专家预设进入组合树
290
298
  dsh --profile web --dump-config # 看 profile 的有效配置
291
299
  dsh web # 起 Web 做真实操作验证
292
300
  ```
293
301
 
294
- `npm test` 跑的是 `test/run-all.mjs`,依次执行 **54** 个独立套件(各自是独立 node 进程,任一非零退出即整体失败)。套件是显式白名单而非 `node --test` 自动发现——`test/` 下还有带副作用的迁移脚本与需要宿主模块的端到端脚本,自动发现会误跑。
302
+ `npm test` 跑的是 `test/run-all.mjs`,依次执行 **65** 个独立套件(各自是独立 node 进程,任一非零退出即整体失败)。套件是显式白名单而非 `node --test` 自动发现——`test/` 下还有带副作用的迁移脚本与需要宿主模块的端到端脚本,自动发现会误跑。
295
303
 
296
304
  | 分组 | 套件 | 覆盖 |
297
305
  | --- | --- | --- |
@@ -302,7 +310,12 @@ dsh web # 起 Web 做真实操作验证
302
310
  | SkillHub 修正(2.4.1) | `skillhub-detail-fix` `skillhub-ux-fix` | 详情字段回退链与目录 / 详情映射(fetch 全替身,逐条对上 issue #4 的响应形状);`skillhubHomepage` 域名改写与缺字段兜底;合并时空值不得覆盖、`0`/`false` 必须保留;`browsableHomepageUrl` 拦住接口域名;悬浮按钮订阅 / 看板激活自动收起 / 右键与长按菜单 / 唯一入口置灰 / 卸载清理(hooks 替身真渲染) |
303
311
  | 自定义套件(2.2.0) | `suites-registry` `suites-client` | 整集合覆盖 / 幂等 / 拒绝与截断两态;id 归属契约(保存后不分裂)、引用套件展开为多个 `/name`、三级写通道降级 |
304
312
  | 技能集合(2.2.0) | `skill-remove` `skill-refresh` | 卸载来源白名单与路径边界(根自身 / `..` 穿越 / 跨来源根 / 符号链接只删链接);装 / 卸后角标与看板实时刷新、乱序回包守卫 |
305
- | 专家与团队 | `run-expert-manual` `session-persona` `team-bridge` `expert-card-actions` `recent-sort-regression` | 专家市场写链(真网目录 + 人设 + patch 往返,33 条断言);会话级挂/换/摘;团队桥接;卡片按钮真值表;「最近使用」排序 |
313
+ | 社区 MCP(2.4.4) | `mcp-community` `community-pager` `community-detail` | Registry 映射 / active 与可运行过滤 / 游标 / 缓存重算 serverName / 4xx 与 5xx 分流;已读取总数与游标栈;详情字段、焦点与「加入 MCP」动作 |
314
+ | 技能禁用(2.4.4) | `skill-disable` | frontmatter 手术(重复键收敛 / CRLF / 空块 / 无闭行);来源白名单、根包含、realpath、BOM 与无合法 frontmatter 拒绝;幂等重放不写盘 |
315
+ | 连接器体检(2.4.4) | `connector-auth-health` `wb-connector-local` | 真实连接态 / 已安装但未连接 / 需授权(401/403)/ 安装闸 / 授权状态;本机固定依赖 found / missing / platform 与安装前拦截 |
316
+ | 项目 MCP 与系统打开(2.4.4) | `workspace-runtime` `system-open-spawn-guard` | 会话登记不依赖配置文件存在、对齐并入存活但未登记的会话;headless 缺 `xdg-open` 不拖走进程(含旧写法必崩的反向自测) |
317
+ | 市场加载与客户端护栏(2.4.4) | `perf-market-load` `client-guards` | 懒加载 / 快照 / SWR / 账本缓存 / hover 预取逐段抽源码真跑 + 反向自测;路径信任 / 链接协议 / 详情竞态 / 重连判定 / 人设提示 |
318
+ | 专家与团队 | `run-expert-manual` `session-persona` `team-bridge` `expert-card-actions` `recent-sort-regression` `expert-persona-source` | 专家市场写链(真网目录 + 人设 + patch 往返,33 条断言);会话级挂/换/摘;团队桥接;卡片按钮真值表;「最近使用」排序;人设取数链(覆盖优先且零人设请求、本机缓存命中不联网、CDN 兜底、404 / 网络故障 / 空缓存都落到标注过的兜底人设、包名不能穿越目录、召唤前先取人设) |
306
319
  | 升级与安装真机 | `upgrade-plan` `verify-install-info` `verify-host-installinfo` `teardown-residue` | 一键升级判据(本地安装 / 来源未知一律不写);真 profile 数据下的来源判定(profile 不存在自行 SKIP);teardown 残留诊断 |
307
320
  | 市场与安装链(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 鉴权闸;顶部安装浮层跨卸载可见 |
308
321
  | 社区信号(2.3.0) | `community-meta` | GitHub 仓库写法解析、单次最多 8 条、6 小时缓存命中不联网、refresh + ETag 的 304 复用、404 文案、网络失败 stale 回落、403 限流跨调用生效、原子写(fetch 全替身 + mkdtemp 隔离) |
@@ -324,6 +337,7 @@ CI(`.github/workflows/ci.yml`)与发版门槛(`.github/workflows/release.y
324
337
  - [安装与升级](docs/installation.md)
325
338
  - [JSON 导入](docs/json-import.md)
326
339
  - [设计与限制](docs/design.md)(共享连接模型、连接状态语义、已知限制、依赖细节)
340
+ - [市场加载性能](docs/perf-market-load.md)(诊断、实测、逐项回退开关)
327
341
  - [DeepSeek Harness 官方插件发布指南](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/develop/basic/publish.md)
328
342
 
329
343
  ## 相关链接