web-search-opencode-responses
文件与数据 活跃维护

web-search-opencode-responses

bailynlove/web-search-opencode-responses

实现OpenCode Zen Go Responses API的服务端网页搜索能力,作为WebSearchProvider可直接对接该API服务,无需复杂配置即可为相关应用提供实时网页搜索功能,部署接入简单高效。

1
Stars 标星
0
Forks 分支
1
Watchers 关注
0
Open Issues
JavaScript
主要语言
None
开源协议
20 KB
仓库大小
1 个月前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:bailynlove/web-search-opencode-responses
git clone https://github.com/bailynlove/web-search-opencode-responses.git
git clone git@github.com:bailynlove/web-search-opencode-responses.git
README.md main

web-search-opencode-responses

A DeepSeek Harness (dsh)
WebSearchProvider plugin that runs web search server-side through the
OpenAI Responses API
on the OpenCode Zen Go gateway — so web_search bills
to your OpenCode plan instead of consuming DeepSeek API quota.

The official web-search-deepseek provider is Anthropic-bound: it speaks
DeepSeek's Anthropic-compatible Messages API (POST /messages on
https://api.deepseek.com/anthropic/v1), a wire that only ever reaches
DeepSeek's own endpoint — it cannot be pointed at OpenCode. This plugin
exists to bypass that limitation: it swaps in the OpenAI Responses API
(POST /responses with the native web_search server tool) against
https://opencode.ai/zen/go/v1, so the same WebSearchProvider seam runs
search on the OpenCode plan. The only thing carried over from the official
provider is the working principle — one search is one model call whose
inference backend executes the search; the wire, endpoint, and billing are all
different.

How sources are derived

The gateway does not populate url_citation annotations, so the provider maps:

  1. web_search_call actions of type open_page — pages the server actually
    opened (highest trust; the #ws_call_id=… tracking fragment is stripped);
  2. url_citation annotations, when a gateway provides them (they override the
    hostname fallback title and can add snippets);
  3. as a fallback, absolute URLs in the final answer text — what the model
    reports having found after searching.

If none of these yield a source, the search fails loud
(WEB_PROVIDER_ERROR) instead of returning an unsourced answer.

Install (into a web profile)

The package ships as a dsh bundle: one install command both adds the plugin
dependency and applies the patch layer that points the web seam at this
provider.

From a profile directory (or with --profile <name>), install from GitHub:

dsh plugin --profile web add github:bailynlove/web-search-opencode-responses

That links the package, appends it to dsh.profile.bundles, and applies its
cordis.patch.yml — inserting the web-search-opencode-responses row and
setting web.searchProvider: opencode-responses. Verify the layer, then boot:

dsh --profile web --dump-config   # shows a "# == web-search-opencode-responses" layer
dsh --profile web

To pin a specific release instead of the moving default branch, use a commit:

dsh plugin --profile web add github:bailynlove/web-search-opencode-responses#<sha>

For a local checkout during development, keep the older file: wiring: declare
"web-search-opencode-responses": "file:./plugins/web-search-opencode-responses"
in the profile package.json and add the same two patch rows (insert the
plugin, set web.searchProvider: opencode-responses) to the profile's
cordis.patch.yml.

Configuration

The plugin registers a settings section (web-search-opencode-responses) on
the Host. Note: the dsh web Plugin configuration tab only shows cards for
the provider namespaces the web client ships (DeepSeek, Shell, Agent loop) — a
third-party namespace like this one has no client card yet, so configure it
through the settings document instead:

  • key — visual: dsh web Settings → Models, write the OPENCODE_GO_API_KEY
    credential (stored in ~/.dsh/.credentials.yaml).
  • endpoint / model / key reference — edit the settings document ~/.dsh/settings.yaml,
    opened in the web UI by the Open configuration file button:

    web-search-opencode-responses:
    baseURL: https://opencode.ai/zen/go/v1   # optional; /responses is appended
    model: deepseek-v4-flash                  # optional; server-side search model
    apiKeyEnv: OPENCODE_GO_API_KEY            # optional; credential reference
    apiKey: ""                                # optional; literal key over the ref

    The file hot-reloads, so a change applies on the next search; the
    provider reads the section per search, no restart needed.

Equivalent static values can be authored in the plugin's cordis.patch.yml
entry (the composition base); the settings document overrides it. See the
Configuration field table below:

field default meaning
apiKey literal key; prefer the credential store
apiKeyEnv OPENCODE_GO_API_KEY credential reference resolved per search
baseURL https://opencode.ai/zen/go/v1 gateway endpoint; /responses appended
model deepseek-v4-flash Responses model with server-side search

The key resolves through dsh's credentials service first (the web Models page
writes ~/.dsh/.credentials.yaml), then the launching environment; a stored
secret never leaves the machine — the wire surface redacts it.

Tests

node --test test/mapping.test.mjs test/provider.test.mjs   # unit, offline
node test/integration.mjs                                  # real API, needs the key

Notes

  • Undocumented routing. OpenCode's go docs
    list deepseek-v4-flash only under chat/completions and list Grok/GPT/Muse
    under /v1/responses. Empirically the gateway also routes deepseek models on
    /v1/responses and executes server-side web_search there (repeatedly
    verified with fresh, real results), matching DeepSeek's own Responses API,
    where web_search is documented as server-side. If OpenCode ever restricts
    routing to the documented matrix, searches start failing with
    WEB_PROVIDER_ERROR — loud, never fake. Note the officially listed responses
    models are not a fallback: grok-4.5 accepted the tool but executed no search
    and answered from memory.
  • Each search consumes one model round; the server injects search results into
    the model context (≈25k input tokens observed) — billed to OpenCode.
  • Search quality is the model's: it rewrites queries and opens pages
    autonomously across several rounds.
  • The answer-text URL fallback engages only when the output contains at least
    one executed web_search_call action — URLs from a model that never searched
    are memory, not sources.