@jpa957/dsh-web-search-anysearch
[English] | 中文
An AnySearch-backed search provider plugin for DeepSeek Harness, registered on the ctx.web seam (web-search-anysearch).
The plugin ships two halves, like the built-in providers:
- Host half: registers the
anysearchsearch provider with round-robin key rotation and per-key cooldown failover, and installs a settings section so the configuration is editable in the web app. - Browser half: its own tab in the Settings navigation (Settings → AnySearch) where the API key, endpoint, and result count are filled in the UI — no patch-file editing.
Install
dsh plugin --profile web add @jpa957/dsh-web-search-anysearch
(or from a local checkout: dsh plugin --profile web add /path/to/dsh-web-search-anysearch)
The bundle's patch layer registers the provider automatically. To make it the web seam's default search backend, add the pin to your own patch layer, applied after the bundle's layer:
- id: web
config:
searchProvider: anysearch
fetchProvider: http
Migrating from a hand-mounted copy? Remove the old
- insert:row that pointed at the plugin file from your profile patch first — the bundle now supplies its own registration, and a duplicate id would fail the composition. Keep thesearchProvider: anysearchpin.
Configuration in the Settings tab
Open the web app's Settings → AnySearch tab: the page lets you set
- API key — stored in the Host's credentials store under the key reference below; the literal is never sent back to the browser (the card only reports configured / unset).
- Key reference — the credential/environment name the provider resolves per search; defaults to
ANYSEARCH_API_KEY. A comma-separated value forms a key pool. - Endpoint base — defaults to
https://api.anysearch.comwhen blank. - Max results — result count requested per search (1-10).
Edits are staged and written on Save; Discard reverts. The settings namespace is web-search-anysearch (the section the card edits), so the same configuration can also be managed through the settings document.
Key-pool behavior
Keys are gathered from the credentials reference (comma-split), plus any composition-layer apiKey/apiKeys literals, deduplicated. Searches rotate round-robin; a key-scoped failure — rate limiting (HTTP 429 / "retry after N seconds", honoring the API's retry-after header), quota exhaustion, or auth rejection (401/403) — puts that key on cooldown (60s default, 10min for auth/quota) and retries the next key within the same search, up to six attempts. An exhausted pool aggregates one WEB_PROVIDER_ERROR naming the pool size, masked key, and the API's request_id. An empty pool searches anonymously.
Key safety
Keys enter only through the credentials domain (Settings page or $ANYSEARCH_API_KEY), or through the composition config if you explicitly put them there. This repository contains no secrets; tests use obviously fake as_sk_unit-* keys. Diagnostics mask keys to their first ten characters.
How it behaves
- Rotation: round-robin cursor advances on every successful search.
- Failover: key-scoped failures cool the key down and retry the next key inside the same search; non-key-scoped failures (network, 5xx, unprocessable bodies) surface immediately.
- Self-correction: if every key is cooling down, the earliest-deadline key is retried anyway.
- Aborts surface as
WEB_ABORTEDfrom the fetch, body-parse, and signal phases. - Mapping: entries without a URL are dropped, duplicate URLs collapse,
contentis preferred oversnippet;truncatedis alwaysfalsebecause the web service owns the finalmaxResultsbound (clamped to the API's documented 1-10).
Development
node tests/unit.mjs # offline unit tests (plain node, no framework)
node tests/client-bundle.mjs # client-bundle contract smoke test
node tests/live.mjs # live anonymous smoke test against the real endpoint
The browser half (lib/client.js) is a prebuilt, hand-maintained bundle in the client-module factory format — no build step is required. When installing from a git URL or npm, the committed lib/client.js is what the web app serves.
No comments yet. Be the first to write one.