Add an in-app plugin marketplace fed by a remote web catalog: the host plugin-inventory gateway gains marketplaceList/Install/Uninstall remotes, a durable per-user install table reconciled against the actual profile, and git/npm/tarball/bundle install paths with non-interactive git and vendored pnpm. The Web Settings surface gains a sibling 插件市场 tab that lists the catalog with recommended badges, repository links, and a combined sort (recommended first, then catalog priority, then id). Add a host + client skill manager: list local skills by direct filesystem discovery, and install/uninstall/toggle/edit their SKILL.md from git/npm/ tarball/local sources in the writable user root. Co-Authored-By: Claude <noreply@anthropic.com>
3.9 KiB
Agent Note: skills manager settings tab + built-in host plugin
Status: implemented
English | 中文
Problem
Skills are discovered by dsh-skill-filesystem from filesystem roots
($DSH_HOME/skills, project .agents/skills, bundled, …) as SKILL.md bundles,
but there is no management surface — no way to see all local skills, install one
from a git/npm/tarball/local source, uninstall it, or toggle its invocation. The
plugin settings section had config/list/marketplace tabs but no skills tab.
Decision
Add a skills management tab beside 插件配置 / 插件列表 / 插件市场 in the Plugins settings section, backed by a new built-in host plugin.
Host: packages/host/skill-manager (@deepseek-ai/dsh-host-skill-manager).
SkillManagerGateway (serviceKey skillManager) exposes five direct Remotes:
list()— readsctx.skills.list({})(the global layer: user/bundled/custom/runtime skills) and marksmanaged= lives in$DSH_HOME/skills(source === 'user-dsh').install(spec)— resolves agit | npm | tarball | localsource into a validatedSKILL.mdbundle and copies it to$DSH_HOME/skills/<name>; the provider watcher discovers it with no restart.uninstall(name)— deletes a user-root skill; refuses names not installed there.setEnabled(name, patch)— rewritesSKILL.mdfrontmatterdisable-model-invocation/user-invocable.setDescription(name, description)— rewritesSKILL.mdfrontmatterdescription.
src/install.ts materializes the source (git clone, npm pack+tar, tarball fetch+tar,
local dir), unwraps a single top-level dir, locates SKILL.md (root or skills/<name>/),
and validates the provider-mandated name + description. Git runs with the same
non-interactive environment as the plugin marketplace (GIT_TERMINAL_PROMPT=0 +
StrictHostKeyChecking=accept-new) so a first-time clone never hangs.
src/skill-io.ts parses/rewrites the frontmatter (matching the provider's key semantics)
and does the read/install/delete filesystem work. No durable install table is needed:
the filesystem is the installed state, unlike plugin installs which record a profile
dependency.
Client: packages/client/ui-settings-skill-manager
(@deepseek-ai/dsh-client-ui-settings-skill-manager). Registers
settings.plugins.tab id skills (order 30). SkillManagerSettingsTab lists skills
with their invocation tags and manage/read-only labels, plus an install row (source
select + spec) and per-managed-skill toggle / edit-description / delete actions.
Wiring: the host + client packages are composed in packages/bundle/web-app
(cordis.patch.yml + package.json), @deepseek-ai/dsh-host-skill-manager is added to
REQUIRED_PLUGINS (protected, not toggleable), and the skillManager namespace is
mounted in packages/api/remotes/src/client/index.ts.
Verification
- Host:
tests/skill-manager.spec.ts(Remote surface + list/install/uninstall/toggle/ description against a temp$DSH_HOME),tests/install.spec.ts(local source resolution + validation),tests/skill-io.spec.ts(frontmatter parse/rewrite + fs). - Client:
tests/skill-manager.client.spec.tsx(render, install, toggle, edit, delete, load-failure retry). pnpm run build:lib:host+pnpm run build:lib:client(regenerates theskillManagerTypert Host/Client Remote artifacts); all modified packages typecheck.
Alternatives
- Fold skill management into
plugin-inventory. Rejected: skills are filesystem artifacts with a different install target than plugins (skill root vs profile deps), so a separate host package keeps each seam's ownership clear. - A durable install table like the plugin marketplace. Rejected: a skill is installed iff its bundle exists in the user root; the watcher already derives the catalog from the filesystem, so an extra table would only drift.