dsh-tinyfish-search
English | 简体中文
DeepSeek Harness plugin that backs the built-in web_search tool with the TinyFish Search API. One GET per query, no model call — fast and free (TinyFish Search is free at any wallet balance).
What it does
DeepSeek Harness's built-in web_search tool normally runs through the DeepSeek Anthropic-compatible endpoint (web-search-deepseek). This plugin registers an alternative web search provider on the ctx.web capability seam:
- Stable provider id:
tinyfish
- Every
web_search call becomes GET https://api.search.tinyfish.ai?query=... with the X-API-Key header
results[] (title / snippet / url / date) are normalized into the seam's portable source shape
- No LLM turn consumed per search — unlike the Anthropic server-tool approach
Installing the bundle takes over the built-in web_search automatically: the
bundle patch overrides the web seam row (searchProvider: tinyfish,
fetchProvider: http restated), because dsh-base pins the seam to
deepseek-official and would otherwise keep the tool on the DeepSeek backend.
It also re-enables the host-level tool-web row (disabled: false plus
search: true, fetch: true and the base timeouts restated): the
dsh-web-app bundle ships that row disabled (the Web app normally composes
web tools per agent preset), so without it the model would see no web_search
tool at all on a clean web profile install. Scope note: re-enabling the
host row makes the tools visible to every agent preset on the profile —
including presets that would not otherwise carry web tools (e.g. minimal);
a preset that mounts its own tool-web row still shadows this global
registration for its agents. To scope the tools to one preset instead,
override or remove the tool-web row in your profile's cordis.patch.yml
and add tool-web to that preset's agent composition. Later layers (profile
/ home cordis.patch.yml / --patch) can still override both rows.
Configuration is also exposed as a dsh-tinyfish-search settings section
(Plugins settings page): a saved edit reaches the next search without a
restart.
Requirements
- DeepSeek Harness
dsh CLI (any profile with the web seam, e.g. web) — verified on 0.1.6-alpha.2 (latest release)
- Node.js
^22.19.0 || >=24.0.0 (matches the harness engine range)
- A TinyFish API key (free to create; Search is free)
- The harness credential seam and launch environment (
@deepseek-ai/dsh-credentials, @deepseek-ai/dsh-launch-environment) are required peers — every dsh profile carries them already
Documentation
Install
dsh plugin --profile web add dsh-tinyfish-search
or from the repository / a tarball:
dsh plugin --profile web add ./dsh-tinyfish-search # source checkout
dsh plugin --profile web add ./dsh-tinyfish-search-0.10.0.tgz
dsh plugin --profile web add github:maxwell-feng/dsh-tinyfish-search
Git installs fetch sources, not built artifacts: pnpm runs the package's prepare script, which builds lib/ from source. pnpm ≥ 10 requires you to allow the build once (it prints the exact pnpm-workspace.yaml snippet).
See the Install Guide for requirements, all install methods, and verification.
Configure
Set your API key (recommended — no secret in config files):
Linux / macOS:
export TINYFISH_API_KEY="your_api_key_here" # current shell
echo 'export TINYFISH_API_KEY="your_api_key_here"' >> ~/.bashrc # permanent (bash)
echo 'export TINYFISH_API_KEY="your_api_key_here"' >> ~/.zshrc # permanent (zsh)
source ~/.bashrc # or reopen the terminal
Windows (PowerShell):
setx TINYFISH_API_KEY "your_api_key_here" # permanent — takes effect in new terminals
$env:TINYFISH_API_KEY = "your_api_key_here" # current session only
Or set fields in your profile's cordis.yml / patch layer:
- insert:
- id: dsh-tinyfish-search
name: dsh-tinyfish-search
config:
# apiKey: "literal-key" # alternative to the env var; avoid committing it
# apiKeyEnv: TINYFISH_API_KEY # default
# baseURL: https://api.search.tinyfish.ai # default
# location: US # optional geo targeting forwarded to TinyFish
# language: en # optional search language forwarded to TinyFish
| Field | Default | Meaning |
|---|
apiKey | — | Literal TinyFish API key (secret role; wins over the env var) |
apiKeyEnv | TINYFISH_API_KEY | Environment variable carrying the API key |
baseURL | https://api.search.tinyfish.ai | TinyFish Search API endpoint base |
location | — | Optional geo location forwarded as TinyFish's location (e.g. US); blank/unset sends nothing |
language | — | Optional search language forwarded as TinyFish's language (e.g. en); blank/unset sends nothing |
See the Configuration Guide for the full schema, credential resolution order, and runtime settings UI.
Verify
dsh --profile web --dump-config | grep tinyfish # layer present
Inside a session, call web_search and check that results carry TinyFish URLs/snippets. The web search settings card in the GUI (网页搜索) shows the provider state.
Usage
After installation, no code changes required. In any session with the web profile:
- The model calls
web_search as usual (e.g. “search for TinyFish docs”).
- The harness routes it through
ctx.web → tinyfish → https://api.search.tinyfish.ai.
- Results appear as
WebSearchSource[] (url / title / snippet / publishedAt) in the tool result.
- Check GUI: Settings → Web Search shows provider
tinyfish and available: true when the API key is configured.
Abort and error semantics follow the dsh-web seam: WEB_PROVIDER_CREDENTIAL_MISSING when no key, WEB_ABORTED on cancellation, WEB_PROVIDER_ERROR otherwise.
See the Usage Guide for providers, credential configuration, worked examples, and the error table.
Uninstall
dsh plugin --profile web remove dsh-tinyfish-search
Removes the bundle layer and the tinyfish provider registration, and restores
the composed web / tool-web rows to exactly what the underlying bundles
ship (an inserted row's override returns to the row's own defaults when the
inserting layer is removed). Restart dsh --profile web to confirm
web_search falls back to the base deepseek-official provider (or none if
no other provider is installed).
Updating
dsh plugin --profile web add dsh-tinyfish-search@latest
# or from git, to pick up changes before they reach npm:
dsh plugin --profile web add github:maxwell-feng/dsh-tinyfish-search
Upgrading to 0.8.1 from ≤ 0.8.0 needs no manual steps: the settings section,
patch rows, and credential reference are all carried by the bundle layer, and
pnpm refreshes the package in place. It resolves all Dependabot security alerts
for js-yaml (upgraded to 4.3.2, fixing CVE-2026-84375 and related advisories),
retaining the pure TypeScript architecture (zero JavaScript tracked), and the
USER_AGENT is bumped to dsh-tinyfish-search/0.8.1.
Upgrading to 0.10.0 from ≤ 0.9.0 needs no manual steps: aligned with DeepSeek
Harness 0.1.6-alpha.2 (@deepseek-ai/dsh-* peers now ^0.1.6-alpha.2, Node
^22.19.0 || >=24.0.0), and the USER_AGENT is bumped to
dsh-tinyfish-search/0.10.0.
Upgrading to 0.9.0 from ≤ 0.8.3 needs no manual steps: aligned with DeepSeek
Harness 0.1.6-alpha.1 (@deepseek-ai/dsh-* peers now ^0.1.6-alpha.1, Node
^22.19.0 || >=24.0.0), and the published package now ships only lib/,
cordis.patch.yml, and LICENSE — the guides stay in this repository and are
no longer installed into your profile. The USER_AGENT is bumped to
dsh-tinyfish-search/0.9.0.
Upgrading to 0.8.3 from ≤ 0.8.1 needs no manual steps: hardened with enterprise-grade SSRF security defenses, verified against DeepSeek Harness 0.1.5-rc.2, and USER_AGENT attribution updated to dsh-tinyfish-search/0.8.3.
Upgrading to 0.8.1 from ≤ 0.8.0 needs no manual steps: resolved all Dependabot
security alerts for js-yaml (CVE-2026-84375, GHSA-5p4m-2wfm-xmqj, CVE-2026-59869, CVE-2026-53550),
retaining the pure TypeScript architecture (zero JavaScript tracked), and the
USER_AGENT is bumped to dsh-tinyfish-search/0.8.1.
Upgrading to 0.7.0 from ≤ 0.6.1 needs no manual steps: the settings section,
patch rows, and credential reference are all carried by the bundle layer, and
pnpm refreshes the package in place. The codebase has been fully refactored
into modular TypeScript components conforming to official guidelines, and the
USER_AGENT is bumped to dsh-tinyfish-search/0.7.0.
Upgrading to 0.6.1 from ≤ 0.5.0 needs no manual steps: the settings section,
patch rows, and credential reference are all carried by the bundle layer, and
pnpm refreshes the package in place. The user-visible changes are the
manifest declaration (manifestVersion: 1, @deepseek-ai/dsh-* peers now ^0.1.5-rc.2, Node >=22) and
the USER_AGENT attribution (dsh-tinyfish-search/0.6.1).
Upgrading to 0.5.0 from ≤ 0.4.0 needs no manual steps: the settings section,
patch rows, and credential reference are all carried by the bundle layer, and
pnpm refreshes the package in place. The only user-visible changes are the
harness floor (@deepseek-ai/dsh-* peers now ^0.1.5-rc.1, Node >=22) and
the USER_AGENT attribution (dsh-tinyfish-search/0.5.0).
Upgrading to 0.3.0 from ≤ 0.2.1 needs no manual steps: the settings section,
patch rows, and credential reference are all carried by the bundle layer, and
pnpm refreshes the package in place. The only user-visible change is the
web/tool-web row behavior documented above, which stays identical unless
you had already overridden those rows yourself.
Development
pnpm install
pnpm build # tsc -> lib/
pnpm test # node --test (mocked fetch)
Publishing to npm runs through GitHub Actions with npm Trusted Publishing (OIDC) — see .github/workflows/publish.yml and the npm docs. Tag vX.Y.Z (or dispatch the workflow) to release; provenance is generated automatically.
Release notes
See CHANGELOG.md (bilingual) and the GitHub Releases page.
License
MIT — see LICENSE.