nonmean/dhs-plugin-explorer ↗★ 0
dsh-plugin-explorer
Browse GitHub repos tagged dsh-plugin: names, readmes, and statistics, with a Sync button and live search.
AI Analysis
核心用途是在 DSH 侧边栏提供一个插件浏览器模态框。适合想要直接在 Web 界面中发现、搜索和查看 GitHub 上各类 DSH 社区插件的用户。
Install
This plugin has no verified bundle, or compatibility checks failed. Read the repository notes first. Read the full README ↗
README
Read the full README ↗dsh-plugin-explorer
A local tool for the DeepSeek Harness web GUI that browses the GitHub
dsh-plugin topic: every repo's
name, README, and statistics (stars, forks, open issues, language,
license, last update, topics), with a Sync button to refresh the data and
an in-memory search over the cached snapshot.
It is a client plugin
(dsh.client dual-face package) that mounts one entry into the sidebar's
footer action list (sidebar.footer.action): a Plugin Explorer trigger
beside Settings that opens the tool's modal.
Using the tool
- Open the web GUI (
http://127.0.0.1:3080) and refresh the page. - Click Plugin Explorer in the sidebar footer (bottom-left, next to Settings).
- Press Sync to fetch the topic's repos from the GitHub search API (sorted by stars, up to 1000 repos — GitHub's search cap).
- Search filters the cached snapshot by repo name, description, topics, language, license, and README text (readmes the tool already fetched).
- Expand a repo's README to load and render it (fetched lazily on first expand, then cached).
Data persists in localStorage under dsh-plugin-explorer:repos:v1 and
dsh-plugin-explorer:readmes:v1, so the list survives restarts and works
offline. The readme cache is size-bounded (oldest entries evicted).
GitHub API notes
- Unauthenticated REST rate limits apply (60 req/h core, 10 req/min search, per IP). One full sync costs up to 10 search requests; READMEs cost one request each and are cached. Rate-limit hits abort gracefully with a message and keep the previous data (a partial sync is preserved).
- The tool talks to
api.github.comstraight from the browser (CORS is permissive); no token is required for public data. If you hit limits often, set aGITHUB_TOKEN? No — the browser cannot read your env; the tool is intentionally anonymous.
Architecture
src/
index.ts node half: empty apply() (mounts the loader row)
client/
index.ts browser half: inject ['slots'], slots.inject(...)
into 'sidebar.footer.action', register RepoExplorer
RepoExplorer.tsx trigger + modal: sync, search, list, README expand
RepoExplorer.module.css
github.ts GitHub REST client + localStorage cache + helpers
The browser bundle (lib/client.js) is emitted by tsdown in the shell's
closure-factory format: window.__ModuleLoader__.load({ id, factory }) with
the frozen platform module table as externals (react, @deepseek-ai/cordis,
@deepseek-ai/dsh-client-ui-primitives, ...), CSS Modules compiled by
lightningcss and injected as `` tags.
Mounting into the GUI
The tool is mounted through the web profile's user patch layer (no changes
to the DeepSeek Harness checkout):
# ~/.dsh/profiles/web/cordis.patch.yml
- insert:
- id: dsh-plugin-explorer
name: dsh-plugin-explorer
plus a symlink so the profile can resolve the package:
ln -s /Users/boxiao/Documents/dev/dhs-plugin-explorer \
/Users/boxiao/.dsh/profiles/node_modules/dsh-plugin-explorer
New rows are read at GUI boot (config hot-reload is off in the web profile),
so a restart of the dsh web process was required once. After that,
rebuilds of lib/client.js hot-reload through the client-plugin HMR chain
(the host polls the bundle and broadcasts rebuilt over SSE; no refresh
needed).
Development loop
pnpm install # registry dev deps only; dsh types resolve through a
# node_modules/@deepseek-ai -> ~/.dsh/profiles/node_modules/@deepseek-ai
# symlink (the exact package versions the GUI runs)
pnpm run typecheck # tsc --noEmit against the real dsh .d.ts artifacts
pnpm run build # tsdown: lib/index.js + lib/client.js (+ .map)
pnpm run watch # tsdown --watch; bundle rewrites trigger client HMR
Known limitations
- GitHub search caps topic results at 1000 of ~2370 repos; the status line reports the topic total and the capped list length.
- The list renders the first 300 matches at once (scroll container); the status line notes when more matches exist.
- Unauthenticated rate limits can interrupt a sync; partial results are kept and the UI explains the reset time.