DSH Plugins Marketplace

DSH Plugins

Plugins

/

Tools & Capabilities

/

dsh-web-search-brave

n

dsh-web-search-brave

Manifest valid

Brave Search provider for DeepSeek Harness (dsh) — independent dsh plugin hardened against web_search hangs, missing request timeouts, and HTTP 429 rate-limit storms.

hasBundlePatch

License: MIT DeepSeek Harness plugin dsh

dsh-web-search-brave

Brave Search provider plugin for DeepSeek Harness (dsh) — hardened so web_search cannot hang your session, and multi-query searches stop drowning in HTTP 429 rate limits.

An independent implementation of the DeepSeek Harness ctx.web search-provider seam. It targets the official provider interface and is modeled on the official @deepseek-ai/dsh-web-search-deepseek provider's structure, which is the documented way to write a seam provider. It is not a fork of the separately developed dsh-web-search-brave packages — see Compatibility.

Not affiliated with or endorsed by DeepSeek. The @deepseek-ai/... package name follows DeepSeek's first-party naming convention for seam providers; it is not an official DeepSeek package and is never published to npm. The provider interface and module scaffolding derive from the official @deepseek-ai/dsh-web-search-deepseek (MIT, © 2026 DeepSeek); the Brave integration is original to this package.

  • Keywords: DeepSeek Harness, dsh, dsh plugin, Brave Search API, web search provider, web_search tool, HTTP 429 rate limit, request timeout, agent tool call hang

The bug this fixes

If your dsh session ever froze when the web_search tool was called — spinner forever, nothing in the transcript, sometimes needing a full restart — this is why.

BraveSearchProvider.search() in 0.1.1 armed no timer of its own and handed fetch only the caller's AbortSignal. DeepSeek Harness enforces tool timeouts through @deepseek-ai/dsh-tool-call-timeout-policy, which is explicitly cooperative: it awaits the tool promise without racing it. So when a request never settles, no tool result is ever recorded, the turn waits indefinitely, and the UI looks frozen.

Observed live, with a 60 s tool budget configured and never applied:

CallResult
web_search, 1 queryreturned in 1.1 s
web_search, 4 queriesnever returned — 8 m 29.7 s, until the user interrupted it

The second problem compounds it. One multi-query web_search call fans out as N parallel requests (the fan-out lives in dsh-tool-web), while Brave rate-limits per second. On the free tier that spends the whole budget on 429s:

4 concurrent queries, unspacedOutcome
upstream 0.1.10 of 4 succeeded (WEB_PROVIDER_ERROR, HTTP 429), in 731 ms

What this version changes

Three configurable knobs, all bounded by the same hard deadline so nothing can hang:

SettingDefaultWhat it does
searchTimeoutMs15000Hard provider-level deadline. Fuses your AbortSignal with AbortSignal.timeout(). This is the freeze fix. Created before queueing, so queue wait counts against the budget.
minRequestIntervalMs1500Serializes the fan-out through a per-process queue, one request at a time, spaced. 1100 measured 3/4 successes; 1500 measured 4/4.
maxRetries2Bounded retries on HTTP 429, honouring Retry-After (capped at 3 s). Bounded by searchTimeoutMs, so retrying cannot reintroduce a hang.

Deadline expiry is reported as a clear WEB_PROVIDER_ERROR timeout; caller cancellation is still reported as WEB_ABORTED. Nothing else about the provider contract changed.

After the fix, on the same live API:

beforeafter
stalled server, no caller signalnever settlesrejects in 4.0 s
4 concurrent queries0/44/4 in 5.5 s
1 query903 ms843 ms

Install

dsh plugin --profile web add github:nedzen/dsh-web-search-brave

Or from this local checkout:

dsh plugin --profile web add file:$HOME/Sites/dsh-web-search-brave

Then pin the seam to it in your profile's cordis.patch.yml. A patch replaces the whole config, so restate every key the web row owns — omitting fetchProvider silently drops it and breaks web_fetch:

- id: web
  config:
    searchProvider: brave-search
    fetchProvider: http          # do not omit

- id: web-search-brave
  name: "@deepseek-ai/dsh-web-search-brave"
  config:
    apiKeyEnv: BRAVE_SEARCH_API_KEY
    baseURL: https://api.search.brave.com/res/v1
    maxResults: 10
    searchType: web
    # searchTimeoutMs: 15000      # optional overrides
    # minRequestIntervalMs: 1500
    # maxRetries: 2

The API key resolves from the credentials service first, then the launching environment (.env files are layered in automatically). Store it as BRAVE_SEARCH_API_KEY, or point apiKeyEnv at whatever name you export.

Verify it works

test/freeze-regression.mjs reproduces the freeze with a server that accepts the TCP connection and then never responds. Cases A (stalled server, no caller signal) and C (fan-out spacing) go RED on 0.1.1 and GREEN here.

cd ~/.dsh/profiles/web
set -a; . ~/.dsh/.env; set +a
node ~/Sites/dsh-web-search-brave/test/freeze-regression.mjs \
  ./node_modules/@deepseek-ai/dsh-web-search-brave/lib/index.js "0.1.3"

Node rather than Bun is deliberate: dsh runs this provider under Node's fetch, and the abort/timeout semantics being asserted are undici's.

Self-check in a live session — the timing tells you which build is loaded:

4-query web_searchBuild
returns in under 1 s, usually HTTP 429old 0.1.1
takes 4.5 s or more, normally succeedsthis build

Tuning

  • Many parallel queries time out. searchTimeoutMs also covers queue wait. If the model fires several web_search calls at once (e.g. maxParallelToolCalls above ~3 with 4 queries each), the tail can exceed 15 s and fail fast rather than hang. Raise searchTimeoutMs to 30000.
  • Paid Brave plan. Set minRequestIntervalMs: 0 and maxRetries: 0 to trade robustness for speed.
  • Still rate-limited. Raise minRequestIntervalMs, or run a multi-provider fallback chain instead of a single backend.

Troubleshooting

I edited the source and nothing changed. A file: dependency is copied into the profile by pnpm, and pnpm install reports "Already up to date" while keeping the stale copy. Remove it and reinstall:

rm -rf ~/.dsh/profiles/web/node_modules/@deepseek-ai/dsh-web-search-brave
dsh plugin --profile web install

I reinstalled but the running session is unchanged. Only config hot-reloads. Plugin JavaScript is ESM-cached and dsh-hmr ships with no watch roots (root: []), so restart dsh to load new provider code.

WEB_DUPLICATE_PROVIDER. Another provider already registered the brave-search id — check for two rows declaring this bundle.

Compatibility

Targets the 0.1.x DeepSeek Harness line: @deepseek-ai/dsh-*@^0.1.1-rc.2 peers. The timeout/spacing/retry settings are additive, so dsh 0.2.x should also work — verify against your own build rather than assuming.

Same name, different plugin. dsh-web-search-brave is also the name of unrelated, separately developed packages, e.g. cnChenKai/dsh-web-search-brave (npm dsh-web-search-brave, 0.2.4). They are different implementations with incompatible configuration: that one registers the provider id brave and configures count/safesearch/textDecorations; this one registers brave-search and configures maxResults/searchType. Pick one, don't wire both into the same profile, and don't expect a config to port across.

Related

License

MIT. Implementation © 2026 nedzen. The provider interface and module scaffolding derive from the official @deepseek-ai/dsh-web-search-deepseek (MIT, © 2026 DeepSeek). See LICENSE.

Comments

Loading…

From the same category

reactive-resume

DeepSeek Harness plugin for Reactive Resume: bridges your resumes and job applications into a Harness session over MCP.

Tools & CapabilitiesManifest valid

★ 41.7k

↓ 223/wk

MIT

Aug 24, 2026

dsh plugin --profile web add dsh-plugin-reactive-resume

by Tencent

Let AI agents use your real, logged-in browser without interrupting your work. CLI + extension for browser automation across any shell-capable AI agent.

Tools & CapabilitiesManifest valid

★ 8.3k

↓ 7.5k/wk

MIT

TypeScript

Oct 6, 2026

dsh plugin --profile terminal add @wxg-prc-cpg/browser-skill-dsh-plugin

by yjh051108

dsh-routing-suite — injector + router-standard kit: install the runtime injector first, then the task-aware reasoning-mode router preset (measured P1-P23).

Tools & CapabilitiesManifest valid

★ 7k

MIT

JavaScript

Sep 18, 2026

dsh plugin --profile web add @dsh-external/dsh-super-injector

by Q00

Agent OS: the agent gets smarter on its own. We just hold the line: Interview-gated, staged evaluation, budgeted evolution loop. MCP server, 14 runtimes: Claude Code, Codex CLI, Gemini CLI, OpenCode,

Tools & CapabilitiesManifest valid

★ 6.2k

MIT

Python

Oct 7, 2026

Index only — not installable

by dsh-market

The plugin market inside DeepSeek Harness — browse, search, one-click install · DSH 可视化插件市场

Tools & CapabilitiesManifest valid

★ 5.7k

↓ 156.3k/wk

MIT

TypeScript

Oct 7, 2026

dsh plugin --profile web add dshmarket

by superdesigndev

OpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn

Tools & CapabilitiesManifest valid

★ 4.7k

NOASSERTION

Python

Oct 7, 2026

dsh plugin --profile web add treg-dsh