dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
Tavily-backed search provider for dsh: registers the tavily provider on the ctx.web seam so the web_search tool runs against the Tavily Search API
English · 中文
Built for dsh-TUI.
A host-plane Cordis plugin for dsh: it registers the tavily search provider
on dsh's web seam (ctx.web), so the web_search tool goes to the Tavily
Search API (POST https://api.tavily.com/search).
web_search tool itself: the tool, its system
prompt and its result card are untouched — only the search backend changes.web-search-deepseek) stays available as a fallback
you can switch to; set web.searchProvider back to deepseek-official (or
delete the key) to do so.apiKey in the
configuration first, then the credentials service (refs: in
~/.dsh/.credentials.yaml), then the launch environment. The reference
defaults to TAVILY_API_KEY, and the provider never stores a key.tavily) registers on ctx.web; web.searchProvider: tavily
makes it the default choice.web_search runs, the seam hands { query, maxResults } to this provider.{baseURL}/search.results[] → sources[] (title / url /
content→snippet, plus published_date → publishedAt when present), and a
top-level answer (Tavily's AI summary) becomes the tool's optional content.WEB_ABORTED; an HTTP failure or an unparsable body →
WEB_PROVIDER_ERROR; a missing key → WEB_PROVIDER_CREDENTIAL_MISSING (the
message names the configuration step).| Field | Default | Meaning |
|---|---|---|
apiKeyEnv | TAVILY_API_KEY | Credential reference (environment-variable name). |
apiKey | (none) | A literal key, only when you do not want a reference. |
baseURL | https://api.tavily.com | Overridable with TAVILY_BASE_URL. |
searchDepth | basic | basic / advanced (deeper, higher credit use). |
topic | general | general / news. |
includeAnswer | true | Ask for Tavily's AI summary (mapped to content). |
maxResults | 10 | Fallback cap; web_search passes 8 per call, Tavily's ceiling is 20. |
Get a Tavily account and an API key. Register at https://tavily.com/,
create a key in the dashboard, and store it under refs: in
~/.dsh/.credentials.yaml — or export TAVILY_API_KEY in the environment
that launches dsh (see
Where the key lives).
Never commit the key to a repository or paste it into a settings document.
Install it into your profile — it is published on npm as dsh-web-tavily:
dsh plugin --profile dsh-tui add dsh-web-tavily
# from a local checkout instead:
# dsh plugin --profile dsh-tui add file:<path to this package>
Restart dsh-tui before editing the patch (/restart). Adding a plugin
only rewrites the profile's bundle list; it does not load the plugin into
the running session. Restarting here means the tavily provider is already
registered when the patch below is saved.
Make tavily the default search backend. This has to be written in the
profile's user patch layer (the web: section of settings.yaml does not
affect service configuration) — edit
~/.dsh/profiles/dsh-tui/cordis.patch.yml and add:
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: tavily
fetchProvider: http-trusted
⚠️ Saving this file hot-reloads the running session — it is not
"restart to apply". The profile's patch layer is watched, so the session is
reconfigured the instant the file is written. If the plugin is not loaded yet
(step 3 skipped), the web row immediately points at a provider that is not
registered, and web_search / web fetch fail in that session with
WEB_PROVIDER_CONFIGURED_MISSING. A /restart recovers it, because at
boot the plugin is registered and the patched row is read together. Editing
the patch first and restarting later is also safe for the boot — it just
leaves this session's web capability unavailable until that restart.
The web row belongs to the dsh-base layer, so do not add a new row with
insert: — the duplicate id crashes the boot with
duplicate loader entry id: web. Override the existing row by id instead, and
note that an override replaces the whole config, which is why
fetchProvider is restated above.
The plugin's own section lives in ~/.dsh/settings.yaml (it also appears in the
settings screen under “Web search Tavily”):
dsh-web-tavily:
apiKeyEnv: TAVILY_API_KEY
searchDepth: basic
topic: general
includeAnswer: true
maxResults: 10
TAVILY_BASE_URL overrides the API origin; the credential reference defaults to
TAVILY_API_KEY.
The settings screen renders this namespace as a bilingual card (Web search (Tavily) / 联网搜索(Tavily)) with a description for every field, so the reference is the one control you normally touch. The key itself never enters the settings document.
Add it under refs: in ~/.dsh/.credentials.yaml (that file holds machine-local
credentials; do not commit or share it):
refs:
TAVILY_API_KEY: 'tvly-...'
Exporting TAVILY_API_KEY in the environment that launches dsh works too — the
credentials store is consulted first, the launch environment second. A literal
key in dsh-web-tavily.apiKey is accepted as well and wins over both, but it
puts the secret in a settings document, so treat it as a last resort.
Set web.searchProvider to deepseek-official (or delete the key and let the
seam use the only provider available). The seam does not fall back
automatically: a broken Tavily configuration fails loudly rather than quietly
using DeepSeek.
http-trusted)The plugin also registers an http-trusted fetch provider, which works around
web_fetch being refused by the official http provider's safety preflight in
fake-IP proxy environments (Clash and friends resolving domains to
198.18.0.0/15): WEB_BLOCKED_URL: resolves to a non-public IP address.
@deepseek-ai/dsh-web-fetch-http transport and
relaxes exactly one check — the “resolved address must be public” preflight
additionally allows 198.18.0.0/15, the proxy fake-IP range. Everything else
is unchanged: private, loopback and reserved ranges are still refused
(WEB_BLOCKED_URL), IPv6 answers are still dropped, and address pinning,
same-origin redirects, the content-type allowlist, byte/character caps and the
no-credentials cookie rule all stay in place.http provider (below).http://192.168.x.x/ and friends)
are still refused.# the web row in ~/.dsh/profiles/dsh-tui/cordis.patch.yml
config:
searchProvider: tavily
fetchProvider: http-trusted
Rolling back to the official http: set fetchProvider back to http. The
cost is that web_fetch is refused again in a fake-IP proxy environment, in
exchange for the complete safety preflight.
duplicate loader entry id: web on boot — the profile's cordis.patch.yml
used insert: for a row that already exists; rewrite it as the by-id override
shown above.web_search answers WEB_PROVIDER_CONFIGURED_MISSING — the web row points
at a provider that is not registered: either the plugin did not load (check the
bundles list), or cordis.patch.yml was saved before the plugin was loaded,
which is a live reload (see Install). /restart recovers it.web_fetch answers WEB_BLOCKED_URL ... non-public IP — the proxy fake-IP
preflight refused it: switch to http-trusted, or turn the proxy's fake-IP
mode off.web_search fail
(WEB_PROVIDER_CREDENTIAL_MISSING / WEB_PROVIDER_ERROR); the message names
what to configure.max_results is clamped to Tavily's ceiling of 20.searchDepth / topic is an error, never a silent fallback to the
default.v* tags drive .github/workflows/release.yml, which publishes to npm through trusted publishing (OIDC) — no token is stored in the repository.Once installed and configured, let the model call web_search as usual: the
sources list it returns (and the optional summary) now comes from Tavily.
MIT — see LICENSE.