dsh-web-search-openai
English | 中文
A standalone DeepSeek Harness bundle that keeps the stable web_search tool and replaces only its search backend with an OpenAI Responses native Web Search provider. The provider sends tools: [{ "type": "web_search" }], maps url_citation annotations to DSH WebSearchResult.sources, and exposes the stable provider id openai-responses.
The bundled patch is configured for https://llmapi.imedloop.com/v1/responses, model gpt-5.6-sol, and credential reference GPT_API_KEY. The endpoint must implement native Responses Web Search; ordinary Responses text generation or function calling is insufficient. See the official OpenAI Web Search guide.
Install
In the DSH Web UI plugin field, paste only:
github:Alberssssss/dsh-web-search-openai
From a terminal:
dsh plugin --profile web add github:Alberssssss/dsh-web-search-openai
For local development, build and add this checkout instead:
pnpm install
pnpm run build
dsh plugin --profile web add /cfs/zzkj/home/lth/dsh-web-search-openai
Pin a reviewed commit when appropriate:
github:Alberssssss/dsh-web-search-openai#<commit>
Restart the web profile Host, refresh the browser connection, and create a new session. A page refresh alone does not reload Cordis plugins, and an existing session retains the composition with which it was created.
Runtime flow
model calls DSH web_search
-> ctx.web selects openai-responses
-> provider resolves GPT_API_KEY
-> POST /v1/responses with native web_search
-> require web_search_call and URL citations
-> map answer text and citations to WebSearchResult
-> existing DSH tool UI, event log, and source rendering stay unchanged
The provider rejects a successful HTTP response if it contains no web_search_call or no usable HTTP(S) url_citation. It never extracts URLs from model prose. Duplicate citation URLs are removed, titles are retained when supplied, and the shared DSH web service applies the final maxResults truncation.
Relationship to dsh-pharma-product-facts
This bundle supplies URL discovery only. It does not change the conversation model, force the model to call web_search, fetch cited page bodies, or validate medical claims. The companion pharma bundle can consume its results through the stable DSH web_search tool, then independently fetch and validate CDE/NMPA evidence before finalizing an answer:
pharma-product-facts -> DSH web_search -> openai-responses
-> candidate official URLs -> pharma source validation -> final answer
Either bundle can run independently. dsh-pharma-product-facts works with any usable DSH search provider; install the companion with:
dsh plugin --profile web add github:Alberssssss/dsh-pharma-product-facts-plugin
Configuration
The bundle owns two patch operations: it inserts the provider row and replaces the existing web row's searchProvider. A profile layer can override either row:
- id: web
name: '@deepseek-ai/dsh-web'
config:
searchProvider: openai-responses
- id: web-search-openai
name: dsh-web-search-openai
config:
apiKeyEnv: GPT_API_KEY
baseURL: https://llmapi.imedloop.com/v1
model: gpt-5.6-sol
maxOutputTokens: 4096
| Key | Default | Meaning |
|---|
apiKey | omitted | Literal key; prefer apiKeyEnv so no secret enters configuration. |
apiKeyEnv | GPT_API_KEY | Credential reference resolved for every search through ctx.credentials, with launch-environment fallback when that service is absent. |
baseURL | https://api.openai.com/v1 | Responses API base; /responses is appended. The shipped bundle explicitly overrides it with the imedloop proxy. |
model | required | Model that supports native Responses Web Search. The shipped bundle selects gpt-5.6-sol. |
maxOutputTokens | 4096 | Positive-integer output cap for the auxiliary Responses request. The imedloop route can spend more than 1024 tokens on reasoning before emitting cited text. |
The key is resolved for every request, so replacing GPT_API_KEY in the DSH credential store affects the next search without rebuilding this package. The exact secret-free request body is appended as web/openai-search-llm-request when an initiating DSH agent exists; headers and credentials are never logged.
Security and failures
- Credential-bearing requests set
redirect: "error"; a 3xx response is rejected before its Location is contacted.
- Caller cancellation covers credential resolution, network dispatch, and response parsing and surfaces as
WEB_ABORTED.
- Missing credentials surface as
WEB_PROVIDER_CREDENTIAL_MISSING; network, HTTP, malformed-body, missing-search, and missing-citation failures surface as WEB_PROVIDER_ERROR.
- Only HTTP(S) URL citations enter
sources; malformed and local schemes are discarded.
- Provider responses remain external model output. Consumers such as
pharma-product-facts must still fetch and validate the cited primary source before treating a snippet or answer as evidence.
Model Experience
Auxiliary Responses request
What the model sees
A separate Responses model receives Search the web for the following query and cite the sources you use:\n<query> and the native web_search tool declaration. This auxiliary request is not part of the conversation model's context.
Token effect
Every search incurs a separate Responses model request; maxOutputTokens caps its generated output. Native Web Search usage and billing remain properties of the configured endpoint and account.
KV Cache effect
The search request is independent of the conversation request cache. The instruction and tool declaration are stable, while the query changes per call.
Known Limitations and Deferred Work
- The Responses API does not expose a portable result-count control used here; DSH enforces
maxResults after mapping citations.
- URL citation annotations provide URL and title but no portable source snippet, so
snippet is absent.
- The package does not add a fetch provider. It changes only
web_search and leaves source retrieval to the existing consumer workflow.
- Native search may cite a dynamically rendered page that exposes no extractable body. Consumers that require primary-source text must locate a directly fetchable document or report the evidence gap.
- A proxy may accept Responses text generation while rejecting native Web Search. The provider fails loudly instead of degrading to uncited prose.
Development
pnpm run typecheck
pnpm run test:coverage
pnpm run build
pnpm run pack:check
Git installs use committed lib/ files and execute no install-time lifecycle script.