dsh-plugin-manager demo

๐Ÿš€ The plugin butler for DeepSeek Harness
Install ยท Uninstall ยท Start ยท Stop โ€” manage your whole DSH plugin ecosystem in one place

Features ยท Installation ยท Configuration ยท Development ยท ไธญๆ–‡

--- # dsh-plugin-manager Manage DeepSeek Harness plugins **as easily as ordering takeout**. No more hunting through GitHub, typing CLI commands, or hand-editing configs. Open ่ฎพ็ฝฎ โ†’ ๆ’ไปถ โ†’ **Plugin Manager** and every built-in / third-party plugin is right there โ€” install, uninstall, start, stop, and GitHub deep-links all on one page. ![Plugin list](assets/plugin-list.png) ![Install dialog](assets/install-dialog.png) ## โœจ Features ### ๐Ÿงญ Full visibility at a glance - **Built-in vs third-party**: enumerates 130+ built-in plugins from the live Loader (consistent with DSH's own list); packages in profile `dependencies` are auto-flagged as manageable third-party - **State at a glance**: running โ— / stopped / failed-to-load, source badges (npm / GitHub / local), version, and GitHub entry right on each card ### ๐Ÿงฉ Smarter than you'd expect - **Multiple install sources**: npm names, `github:owner/repo#main`, local paths, tarball URLs โ€” all supported - **Bare-name smart resolve**: type a bare name like `dsh-paste-input` and it auto-detects whether it's an npm package or a GitHub repo โ€” GitHub hits show candidate repos for one-click install - **GitHub marketplace search**: search `topic:dsh-plugin` by keyword to discover hidden gems in the ecosystem ### ๐ŸŽ› Precision under the hood - **Stop / start**: resolves a third-party bundle's loader entry ids and writes / removes the `disabled` flag in the profile `cordis.patch.yml` โ€” reconcile-proof - **Uninstall**: clean and thorough, even sweeping leftover stop entries - **GitHub deep-link**: click the version number (โ†—) on a card to jump straight to the repo ### โšก Automation to the last mile - **Auto-restart**: optionally auto-restart dsh web after install/uninstall (off by default); a 10s countdown auto-refreshes, then a top-right toast offers one-click jump back - **GitHub token auto-discovery**: probes env / gh CLI / shell rc / git config for `GH_TOKEN`, and kindly explains the rate limit when unset - **Filters & search**: status tabs + source filter + fuzzy search, collapsible built-in / third-party groups ### ๐ŸŒ Polished for everyone - Full ไธญๆ–‡ / English UI, following the DSH language preference > โš ๏ธ Install / uninstall / stop / start take effect **after a restart** (stop/start may apply immediately when HMR is active). ## ๐Ÿ“ฆ Installation ```bash # From GitHub dsh plugin --profile web add github:webkong/dsh-plugin-manager#main # Or from a local path (development) dsh plugin --profile web add /path/to/dsh-plugin-manager ``` Restart dsh web, then open ่ฎพ็ฝฎ โ†’ ๆ’ไปถ โ†’ **Plugin Manager**. ## โš™๏ธ Configuration The `web` profile is managed by default. Override it โ€” and disable auto-restart โ€” in the load row: ```yaml - insert: - id: pmgr name: '@webkong/dsh-plugin-manager' config: profile: web # profile to manage (default: web) ``` The auto-restart toggle is also switchable in the UI anytime (persisted to `~/.dsh/dsh-plugin-manager.json`). ## ๐Ÿ”ง Development ```bash pnpm install pnpm build # esbuild: src/ โ†’ lib/ (Host ESM + Client __ModuleLoader__ bundle) pnpm typecheck # strict type-checking under dual tsconfig (node / DOM+React) pnpm test # node --test pure-function unit tests (9 cases) pnpm check # typecheck + artifact syntax check ``` ### Structure (TypeScript, modular) **v0.5.0 migrated the whole codebase to TypeScript modules** (following the official ui-plugin layout); build artifacts live in `lib/`: ``` dsh-plugin-manager/ โ”œโ”€โ”€ package.json # dsh.bundle / dsh.client declarations, scripts โ”œโ”€โ”€ cordis.patch.yml # bundle patch: mounts the pmgr row โ”œโ”€โ”€ build.mjs # esbuild 3-stage build (Host / Client / pure-function submodules) โ”œโ”€โ”€ tsconfig.json # Host type-check (node env) โ”œโ”€โ”€ tsconfig.client.json # Client type-check (DOM + React env) โ”œโ”€โ”€ lib/ # build artifacts (gitignored) โ”‚ โ”œโ”€โ”€ index.js # Host single-file ESM bundle โ”‚ โ”œโ”€โ”€ client.js # Client __ModuleLoader__ bundle โ”‚ โ”œโ”€โ”€ entryIds.js # pure-function submodules (imported by unit tests) โ”‚ โ”œโ”€โ”€ github.js / patch.js / spec.js โ””โ”€โ”€ src/ โ”œโ”€โ”€ host/ # Host source (TypeScript, node env) โ”‚ โ”œโ”€โ”€ index.ts # entry: name/inject/apply + webServer route registration โ”‚ โ”œโ”€โ”€ handlers.ts # HTTP dispatch (list/install/uninstall/stop/start/search/resolve/settings/restart) โ”‚ โ”œโ”€โ”€ manager.ts # business layer: inventory, CRUD, search/resolve (DI of fs tools) โ”‚ โ”œโ”€โ”€ fsutil.ts # node:fs + child_process + settings persistence โ”‚ โ”œโ”€โ”€ resolve.ts # dual-anchor package resolution / metadata reading โ”‚ โ”œโ”€โ”€ entryIds.ts # bundle patch loader-entry id discovery โ”‚ โ”œโ”€โ”€ github.ts # GitHub URL extraction + GH_TOKEN reading โ”‚ โ”œโ”€โ”€ spec.ts # install-spec validation โ”‚ โ”œโ”€โ”€ patch.ts # cordis.patch.yml stop/start text ops โ”‚ โ””โ”€โ”€ http.ts # JSON responses / loopback guard โ””โ”€โ”€ client/ # Client source (TypeScript, DOM + React env) โ”œโ”€โ”€ index.ts # apply entry + settings tab / shell.overlay registration โ”œโ”€โ”€ api.ts # fetch wrapper + pmgr method table โ”œโ”€โ”€ components.tsx # status tabs / toolbar / install dialog / plugin card โ”œโ”€โ”€ i18n.ts # zh / en dictionary (key-typed) โ”œโ”€โ”€ spec.ts # client-side spec validation + bare-name detection โ”œโ”€โ”€ styles.ts # CSS injection โ”œโ”€โ”€ toast.tsx # restart toast + one-click jump โ”œโ”€โ”€ types.ts # contract types (wire shapes / dialog state) โ””โ”€โ”€ ui.tsx # page orchestration / grouping / action dialogs โ”œโ”€โ”€ assets/ # demo GIF + screenshots โ””โ”€โ”€ test/pure.test.mjs # unit tests (node --test) ``` ### Wire contract The Host exposes an HTTP API on the `webServer` prefix route `/pmgr/*` (loopback-only); the client calls it via browser `fetch`: | Route | Description | | --- | --- | | `GET /pmgr/list` | plugin inventory + settings | | `POST /pmgr/install` | install (`{spec}`) | | `POST /pmgr/uninstall` | uninstall (`{name}`) | | `POST /pmgr/stop` / `POST /pmgr/start` | stop / start (`{name}`) | | `POST /pmgr/search` | GitHub plugin search (`{q}`) | | `POST /pmgr/resolve` | resolve a bare name (npm check / GitHub candidates) | | `POST /pmgr/settings` | update settings (`{autoRestart}`) | | `POST /pmgr/restart` | trigger an auto-restart | ## ๐Ÿ“„ License [MIT](LICENSE)