Files
deepseek-harness/packages/web/web-search-exa
imccyu 2c85c484d3 build(release): reference workspace members through the workspace protocol
1504 hand-written ranges pointing at workspace members become workspace:^, so
pnpm pack substitutes each member's real version at publication: sibling
peerDependencies follow the family version instead of being pinned at ^0.0.1,
and a reference to a vendored package follows that package's own line. Without
this, publishing 0.0.2 ships peer ranges naming a version that does not exist,
and 0.0.1-rc.1 does not satisfy ^0.0.1 either.

It also retires ranges that had gone stale against the workspace: ^4.0.0-rc.6
for a 4.0.0-rc.7 checkout, ^3.17.0 for schemastery 3.18.0.

workspace:* stays where an exact published version is the point, which is how
the Landlock entry pins its platform packages.

A workspace constraint now requires the protocol, so a new package cannot
reintroduce a hand-written range. The same constraint caught packages/boot/cmdline
arriving on master without the publishable trio, which this change completes.
2026-08-11 00:17:09 +08:00
..

@deepseek-ai/dsh-web-search-exa

English | 中文

An Exa-backed WebSearchProvider for the harness web capability seam (ctx.web). It calls Exa's POST /search endpoint with highlight contents and maps the flat results[] into the seam's normalized WebSearchResult.

This is an implementation package: it registers a provider into ctx.web, it does not own the ctx.web key and it does not register a model-facing tool (that is @deepseek-ai/dsh-tool-web). Like @deepseek-ai/dsh-llm-deepseek, it is a function/namespace plugin (inject: ['web']) that registers its backend, not a default-export service.

Config

Key Default Meaning
apiKey $EXA_API_KEY Exa API key. Empty/absent makes the provider unavailable.
baseURL https://api.exa.ai Endpoint base; /search is appended. An unparseable value makes the provider unavailable.
searchType auto Retrieval mode sent as Exa's type: auto (Exa decides), keyword, or neural.
numResults (unset) Default result count when a request carries no maxResults. Unset sends no default. Must be a positive integer.
highlightsPerResult 1 Highlight sentences requested per result (Exa's highlightsPerUrl). Must be a positive integer.
- id: web-search-exa
  name: '@deepseek-ai/dsh-web-search-exa'
  config:
    apiKey: !!js process.env.EXA_API_KEY

Mapping

Exa returns a flat results[] and no generated answer, so content is omitted. Each result maps to a WebSearchSource: urlurl, titletitle, snippet ← the first non-empty highlights[] entry (a result with no highlight has no portable snippet and is dropped), publishedAtpublishedDate. A request's maxResults wins over the configured numResults default and is sent as Exa's numResults for a cost/latency optimization; the final bound is enforced by the seam. Provider failures (HTTP errors, network failure, unparseable or wrong-shape bodies) surface as WebError WEB_PROVIDER_ERROR; an aborted request surfaces as WEB_ABORTED. HTTP redirects are rejected before the Location target is contacted and surface as WEB_PROVIDER_ERROR.

Model Experience

Indirectly, through dsh-tool-web, which retains this provider's maxResults-bounded URLs, titles, first highlights, and publication dates or its exact Exa search aborted, Exa search request failed: <error>, and Exa returned an unprocessable response body: <error> failures under the consumer's error wrapper while generated answers and provider-private fields remain outside context.

KV Cache effect

No direct invalidation; the named consumer owns any request-prefix changes.

Known Limitations and Deferred Work

  • A result with no non-blank highlight is dropped entirely — no portable snippet to map, so fewer sources than the requested count can return.
  • Only searchType/numResults/highlightsPerResult are exposed — Exa's other controls (livecrawl, category, domain/date filters, full-text contents) wait on provider-neutral Service Definition fields (seam Agent Note).
  • Abort classification is error-shape-based — only a DOMException named AbortError maps to WEB_ABORTED; an abort carrying a custom reason (e.g. dsh-timeout's TimeoutReason) surfaces as WEB_PROVIDER_ERROR.