Skip to content

Releases

v0.4.0 — rate-limit resilient

Choose a tag to compare

@vclike vclike released this 11 Sep 02:15

Maintained fork of awesome-dsh-plugin/dsh-find-plugin 0.3.7, fixing the anonymous-search-quota failures (GitHub search HTTP 403).

Install

dsh plugin --profile web add github:vclike/dsh-find-plugin

Then restart dsh web. Set a GITHUB_TOKEN credential to get 30 req/min instead of the anonymous 10 req/min (per public IP, shared).

Why

Upstream calls api.github.com/search/repositories anonymously. That endpoint allows only 10 requests/minute per public IP, shared by everyone behind the same egress IP, so the tool failed constantly. Measured on 2026-09-11 through a carrier CGNAT shared egress:

  • 13 rapid calls -> 7x403 / 6x200 alternating
  • 403 body: API rate limit exceeded for <shared egress IP>. (But here's the good news: Authenticated requests get a higher rate limit...)
  • headers: x-ratelimit-limit: 10, x-ratelimit-remaining: 0
  • a session's first call could already 403

Upstream's only mitigation is a 5-minute per-query cache (the agent changes keywords every call, so it misses), and the ~3400-entry curated list was consulted only after a successful search - never as a fallback.

Fixes & additions

  • Token auth via the DSH GITHUB_TOKEN credential (10 -> 30 req/min, not IP-shared). The credentials service is optional, read with ctx.get() rather than inject (a missing required service would stop the plugin from loading at all).
  • Retry once on 403/429 (honouring retry-after) and once on network errors, then throw a typed GitHubSearchRateLimited carrying limit / remaining / resetAt.
  • Failure caching (60s) so a retry loop cannot keep burning the quota.
  • Dual-source results: live GitHub + curated keyword matches, deduped by URL; GitHub first (star-ranked, as upstream), curated-only entries fill the remaining slots and render with a [curated] marker.
  • Curated registry cache: disk cache at $DSH_HOME/cache/dsh-find-plugin/registry.json + If-None-Match / If-Modified-Since conditional requests (304 = zero body). Fallback chain: memory -> disk (~3400 entries) -> bundled snapshot (~176).
  • Curated matching: rank by matched-token count first (AND-ish semantics for multi-word queries), then weighted score, then stars; descriptions truncated to 240 chars.
  • Forward exec.signal; timeoutMs 10s -> 25s.
  • Tests: 33 offline cases (mock fetch) + 3 opt-in live network cases + tsc --noEmit over src/*.ts.
  • Dropped the broken prepack script (it referenced a tsconfig.json and scripts/strip-client-export.mjs that are not shipped, so pnpm build always failed - and it would have reverted fixes applied to lib/).

Compatibility

DSH 0.1.5-rc.2 verified. Tool name, inject and parameters are unchanged, so this is a drop-in replacement.

Credits

Upstream plugin and the curated list by awesome-dsh-plugin; the same problem is tracked upstream as issue #5.