dsh-find-plugin
Find DeepSeek Harness (DSH) plugins from inside the agent — it searches the live
GitHub dsh-plugin topic and the curated
awesome-dsh-plugin list (~3400 entries with
bilingual descriptions), merges the results and returns ready-to-run
dsh plugin add commands.
会话内发现 DSH 插件:同时查 GitHub dsh-plugin topic 与 curated 列表(约 3400 条,
全带中英双语描述),合并去重后给出可直接执行的安装命令。
这是 vclike/dsh-find-plugin,基于上游
awesome-dsh-plugin/dsh-find-plugin0.3.7 的维护分支。改动与实测证据见 CHANGELOG.md。
Why this fork / 为什么有这个分支
Upstream calls the GitHub search API anonymously. That endpoint allows only
10 requests/minute per public IP, and the quota is shared by everyone behind
the same egress IP — so the tool fails with a bare GitHub search HTTP 403 all
the time (measured: 13 rapid calls → 7×403 / 6×200; even a session's first
call can 403). Upstream's only mitigation is a 5-minute per-query cache, and the
~3400-entry curated list is used only after a successful search, so it can
never act as a fallback.
上游匿名调用 GitHub 搜索接口,而该接口只有 10 次/分钟/公网 IP 的额度、且按出口 IP
共享 —— 于是 find_dsh_plugin 经常直接以 403 失败(实测 13 次连发 7 次 403;一次会话的
首次调用就可能 403)。上游的防护只有 5 分钟按 query 缓存,而 curated 列表只在搜索
成功之后才被使用,起不到兜底作用。
This fork adds token auth, dual-source merge, a persistent + conditional registry cache, and a real degradation chain.
本分支补上:token 鉴权、双源合并、registry 磁盘缓存 + 条件请求、以及真正的降级链。
What's different / 与上游的差异
| upstream 0.3.7 | this fork 0.4.0 | |
|---|---|---|
| GitHub auth | anonymous (10 req/min/IP) | GITHUB_TOKEN credential → 30 req/min, not IP-shared |
| 403 / 429 | throw | retry once, then a typed rate-limit error carrying limit/remaining/resetAt |
| network error | throw | retry once |
| failure caching | none | 60s (a retry loop can't keep burning quota) |
| curated list | description enrichment only, after a successful search | merged as a real second source; also the fallback |
| registry fetch | 2.7MB every hour, memory only | disk cache + If-None-Match/If-Modified-Since (304 = zero body) |
| offline fallback | bundled snapshot (~176 entries, stale) | memory → disk cache (~3400) → bundled snapshot |
| result labelling | — | per-item source, [curated] marker in rendered text |
exec.signal |
declared timeoutMs, signal ignored |
forwarded; timeoutMs 25s |
| tests | none shipped | 33 offline cases + opt-in live cases + tsc --noEmit |
Install
dsh plugin --profile web add github:vclike/dsh-find-plugin
Then restart dsh web (bundle layers are composed at boot).
Configure a GitHub token (recommended)
Without a token the tool still works, but it is capped at 10 requests/minute per public IP and degrades to the curated list whenever that is exhausted. With a token you get 30 requests/minute and no shared-IP interference.
The token is read from the DSH credential named GITHUB_TOKEN (via
ctx.credentials.resolve('GITHUB_TOKEN')) — the same credential
dsh-github-companion uses, usually backed by the GITHUB_TOKEN environment
variable of the DSH process. The plugin stays zero-dependency: it never
imports @deepseek-ai/dsh-credentials, it only resolves that reference through
the credentials service when one exists.
未配置 token 时也能用,但受 10 次/分钟/公网 IP 限制,额度耗尽即降级到 curated 列表;
配置后为 30 次/分钟且不受共享出口 IP 影响。凭据名是 GITHUB_TOKEN(与
dsh-github-companion 同一份)。
Output
1. dsh-mnemon ★143 — 跨会话记忆 / cross-session memory
https://github.com/owner/dsh-mnemon
install: dsh plugin --profile web add github:owner/dsh-mnemon
2. some-curated-only ★7 [curated] — 仅见于 curated 列表的条目
https://github.com/other/some-curated-only
install: dsh plugin --profile web add github:other/some-curated-only
来源:GitHub 实时 `dsh-plugin` 搜索(按 stars 排序) + curated 列表(source=live,3408 条,
标 [curated] 的是仅见于 curated 的条目)。All plugins are third-party code — review the
source and pin a commit when installing. Browse https://awesome-dsh-plugin.com
Ranking: GitHub results first (star-ranked, as upstream), then curated-only
matches fill the remaining limit slots. When GitHub is unavailable the note
states why, and the results are curated keyword matches only.
排序:GitHub 结果在前(按 stars,与上游一致),curated-only 条目补足剩余名额。 GitHub 不可用时 note 说明原因,结果为 curated 关键词匹配(并标注)。
Tool parameters
| param | meaning |
|---|---|
query (required) |
keywords, e.g. "wechat notifications", "TUI", "跨会话记忆" |
limit |
max results, default 8, capped at 20 |
lang |
preferred description language (en / zh), default en |
Development
node --test "test/**/*.test.mjs" # 33 offline cases (mock fetch), ~8s
FINDP_LIVE=1 node --test test/live.test.mjs # 3 cases against the real network
npm run typecheck # tsc --noEmit over src/*.ts (TS 5.9.3)
lib/**/*.js is the runtime artifact and source of truth; src/**/*.ts is the
typed mirror, validated by typecheck but never compiled over lib/ — upstream's
prepack would silently revert fixes applied to lib/, so that script is removed
here.
lib/ 是运行时产物与唯一真源;src/*.ts 是类型镜像,由 typecheck 校验但不会编译
覆盖 lib/(上游的 prepack 会静默还原对 lib/ 的修复,本分支已移除该脚本)。
Layout / 目录:
lib/index.js tool registration, dual-source merge, rendering
lib/github.js GitHub search: token, retry, typed rate-limit error, caches
lib/registry.js curated registry: disk cache, conditional request, fallbacks
data/registry-snapshot.json last-resort bundled snapshot
test/ node:test suites (offline by default)
License
MIT — same as upstream. Upstream copyright remains with its authors; see LICENSE.
No comments yet. Be the first to write one.