deepseek-web-retrieval 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/README.md +113 -53
  3. package/dist/cli.js +2427 -1813
  4. package/docs/adr/0002-shared-config-base-layer.md +43 -0
  5. package/docs/agents/claude-code.md +273 -0
  6. package/docs/agents/codex.md +50 -27
  7. package/docs/agents/opencode-v2.md +59 -33
  8. package/docs/agents/pi.md +50 -27
  9. package/docs/configuration.md +109 -0
  10. package/docs/design/config-layering-design.md +180 -0
  11. package/docs/design/installer-design.md +24 -13
  12. package/docs/hosts.jsonc +5 -1
  13. package/docs/integration.md +15 -9
  14. package/docs/research/control-matrix.md +49 -11
  15. package/docs/research/mcp-compatibility.md +6 -3
  16. package/docs/research/ori-question-sourcing.md +336 -0
  17. package/docs/research/result-quality-passthrough.md +159 -0
  18. package/docs/research/search-api-defaults.md +18 -2
  19. package/docs/research/search-inline-content.md +244 -0
  20. package/examples/opencode.global.jsonc +3 -2
  21. package/package.json +2 -1
  22. package/src/core/auth.ts +3 -0
  23. package/src/core/client.ts +26 -4
  24. package/src/core/config-file.ts +168 -0
  25. package/src/core/config-summary.ts +82 -0
  26. package/src/core/constants.ts +15 -1
  27. package/src/core/descriptions.ts +6 -2
  28. package/src/core/env.ts +102 -32
  29. package/src/core/format.ts +19 -1
  30. package/src/core/options.ts +22 -2
  31. package/src/core/search.ts +6 -0
  32. package/src/core/types.ts +11 -0
  33. package/src/installer/cli.ts +50 -16
  34. package/src/installer/config-command.ts +116 -0
  35. package/src/installer/hosts/claude-code.ts +325 -0
  36. package/src/installer/hosts/codex.ts +9 -4
  37. package/src/installer/hosts/index.ts +3 -0
  38. package/src/installer/hosts/opencode.ts +9 -5
  39. package/src/installer/hosts/pi.ts +34 -9
  40. package/src/installer/ownership.ts +54 -1
  41. package/src/installer/paths.ts +7 -1
  42. package/src/installer/state.ts +73 -20
  43. package/src/installer/types.ts +11 -1
  44. package/src/installer/uninstall.ts +4 -1
  45. package/src/mcp/auth.ts +2 -3
  46. package/src/mcp/cli.ts +4 -3
  47. package/src/mcp/serve.ts +10 -1
  48. package/src/mcp/server.ts +7 -2
  49. package/src/opencode/plugin.ts +22 -2
  50. package/src/pi/extension.ts +78 -9
package/CHANGELOG.md CHANGED
@@ -1,6 +1,28 @@
1
1
  # Changelog
2
2
 
3
- All notable changes to this project are documented here, with one sentence per item.
3
+ All notable changes to this project are documented here, one sentence per item.
4
+
5
+ ## 0.8.0
6
+
7
+ - Add Claude Code as a supported host: an MCP-only integration registered in `.mcp.json` (project scope) or `~/.claude.json` (user scope), with a full installer host module (plan/apply/uninstall, both scopes), a `docs/agents/claude-code.md` guide, a version probe with drift note, and managed-policy detection that reports a `managed-settings.json` layer outranking the install.
8
+ - Route Claude Code tiers through its own settings files: forced capabilities deny the built-in `WebSearch`/`WebFetch` via `permissions.deny` in `.claude/settings.json` or `~/.claude/settings.json` (merged with the user's entries), off capabilities deny the full `mcp__deepseek__*` tool ids, and preferred writes a rules block into `CLAUDE.md`; web-capable competitor servers are excluded under forced via server-level `mcp__<server>` deny rules instead of refusing the tier.
9
+ - Add a billed `claude-code` Docker e2e scenario that runs headless `claude -p` prompts with DeepSeek as the LLM over its Anthropic-compatible endpoint (single key for both legs) and asserts the deny-based kill switch keeps the built-in tools out of the session, plus installer/reinit coverage of the new host in the keyless scenarios.
10
+ - Guard Pi's global config files with the shared-file ownership sidecar, and release claims before deleting the install record on uninstall, so two installs under different config homes can no longer claim the same `~/.pi/agent` file.
11
+ - Run the Codex and Claude Code version probes through a shell so Windows npm `.cmd` shims launch and the drift check no longer silently skips on Windows.
12
+ - Correct the research attribution for Claude Code's MCP `2026-07-28` default negotiation (v2 runtime from 2.1.274+, changelog bullet at 2.1.299 — not 2.1.296).
13
+ - Restructure the README around a quickstart and a defaults table, moving the full configuration reference (knob classes, the complete file-key ↔ `DEEPSEEK_*` mapping, special semantics) to a new docs/configuration.md guide.
14
+ - Generate the configuration guide's knob table from the config vocabulary itself (`bun run docs:matrix` regenerates it, `--check` fails CI on drift), so the documented key ↔ variable ↔ default mapping can no longer hand-drift from the code.
15
+
16
+ ## 0.7.0
17
+
18
+ - Layer a shared config file (`$XDG_CONFIG_HOME/deepseek-web-retrieval/config.json`, camelCase keys) under the environment on every host, with the precedence `built-in defaults < shared file < DEEPSEEK_* environment < host-native config`; unknown and host-integration keys are warned about and ignored, and the API key stays out of the file.
19
+ - Add a `config` command that prints every knob with its effective value and source (default, file, or environment — a count-derived `maxResults` is labeled `count`), replays shared-file problems, and verifies the key, config, and network end to end with `config --search "<query>"`.
20
+ - Forward every `DEEPSEEK_*` option variable — not just the API key — in the Codex installer's `env_vars` entry, so shell-set knobs reach the stdio server without hand-editing `config.toml`.
21
+ - Surface DeepSeek's `rerank_score`, `authority`, and `site_name` on search results in both text and structured output, accept an optional `original_question` on the MCP and Pi search tools (sent as `ori_question`), and add the `searchLocalization` deployment knob.
22
+ - Couple `maxResults` to `count` when left unset — configuring only `count` was a silent no-op — and retry transient failures (408/425/429/5xx) twice by default instead of failing the billed call on the first attempt.
23
+ - Resolve the shared config directory the Windows way on win32 (`%APPDATA%`, with an explicitly set `XDG_CONFIG_HOME` still winning), for the shared config file and the installer's global records alike.
24
+ - Add `init --pin` to register the exact running CLI version (`deepseek-web-retrieval@<version>`) instead of the unpinned name, with package-identity comparisons that still match a pinned ref to its lineage.
25
+ - `config` now warns and exits 1 when a `DEEPSEEK_*` variable is set but unusable (unknown name, non-numeric value, no-op switch value) instead of silently showing the default.
4
26
 
5
27
  ## 0.6.0
6
28
 
package/README.md CHANGED
@@ -1,33 +1,52 @@
1
1
  # DeepSeek Web Retrieval
2
2
 
3
- **DeepSeek Search and Fetch for OpenCode, Pi, and Codex.**
3
+ **DeepSeek Search and Fetch for OpenCode, Pi, Codex, and Claude Code.**
4
4
 
5
5
  Search the web and fetch pages as Markdown through
6
6
  [DeepSeek's APIs](https://api-docs.deepseek.com/guides/search), using a **native OpenCode
7
- plugin**, a **native Pi extension**, or **MCP for Codex**. All three share the same retrieval
8
- core, with results formatted for each host.
7
+ plugin**, a **native Pi extension**, or **MCP for Codex and Claude Code**. All four share
8
+ the same retrieval core, with results formatted for each host.
9
9
 
10
10
  This is an unofficial community project, not affiliated with DeepSeek or the supported
11
11
  host projects.
12
12
 
13
+ Jump to: [Features](#features) · [Quickstart](#quickstart) · [Usage](#usage) ·
14
+ [General behavior](#general-behavior) · [Configuration](#configuration) ·
15
+ [Development](#development)
16
+
13
17
  ## Features
14
18
 
15
- - **One package, three hosts** — a native OpenCode v2 plugin, a native Pi extension,
16
- and a stdio MCP server for Codex, all sharing one retrieval core
19
+ - **One package, four hosts** — a native OpenCode v2 plugin, a native Pi extension,
20
+ and a stdio MCP server for Codex and Claude Code, all sharing one retrieval core
17
21
  - **Routing control per tool** — search and fetch are set independently to optional,
18
22
  preferred, forced, or off; the tier table in Usage explains each
19
23
  - **Review before anything is written** — `init` prints the full plan and writes only
20
24
  with `--apply`; uninstall restores from snapshots while preserving edits you made
21
25
  afterwards
22
26
  - **Knows the host's web landscape** — detects conflicting web tools and rules,
23
- configures Pi's MCP fallback for direct tool exposure, and reports Codex version
24
- drift
27
+ configures Pi's MCP fallback for direct tool exposure, and reports Codex and
28
+ Claude Code version drift
25
29
  - **Your key never enters a config file** — installs reference the environment
26
30
  (`${DEEPSEEK_API_KEY}` indirection or `env_vars`), so a project-scope install
27
31
  commits clean
28
32
  - **Fails loudly, never switches silently** — no fallback to another provider, and
29
33
  localhost/private URLs are blocked before a request leaves the machine
30
34
 
35
+ ## Quickstart
36
+
37
+ Requires Node.js 20+ and npm, plus a DeepSeek API key with Search and Fetch access
38
+ (retrieval is billed per successful request; the account needs balance).
39
+
40
+ ```bash
41
+ export DEEPSEEK_API_KEY=sk-...
42
+ # Preview the plan for your host — nothing is written yet:
43
+ npx deepseek-web-retrieval init --host opencode --scope project --search forced --fetch preferred
44
+ # Re-run with --apply to write it:
45
+ npx deepseek-web-retrieval init --host opencode --scope project --search forced --fetch preferred --apply
46
+ ```
47
+
48
+ For Pi, Codex, or Claude Code, other scopes, or finer routing control, see [Usage](#usage).
49
+
31
50
  ## Usage
32
51
 
33
52
  Choose your host:
@@ -37,23 +56,11 @@ Choose your host:
37
56
  | OpenCode v2 | Native plugin: search provider and Fetch tools | [OpenCode guide](docs/agents/opencode-v2.md) |
38
57
  | Pi | Native extension: Search and Fetch tools; MCP also available | [Pi guide](docs/agents/pi.md) |
39
58
  | Codex | MCP server over stdio, with readable text results | [Codex guide](docs/agents/codex.md) |
59
+ | Claude Code | MCP server over stdio in `.mcp.json` or `~/.claude.json` | [Claude Code guide](docs/agents/claude-code.md) |
40
60
 
41
- The installer CLI requires Node.js 20+ and npm. Retrieval requires a DeepSeek API key
42
- with access to Search and Fetch and sufficient account balance. Set `DEEPSEEK_API_KEY`
43
- in the environment that launches your host; OpenCode can also use its stored DeepSeek key.
44
-
45
- Run the command for your host to preview a configuration:
46
-
47
- ```bash
48
- # OpenCode: select DeepSeek as the search provider and prefer its Fetch tool.
49
- npx deepseek-web-retrieval init --host opencode --scope project --search forced --fetch preferred
50
-
51
- # Pi: use the native extension and prefer both tools.
52
- npx deepseek-web-retrieval init --host pi --scope project --search preferred --fetch preferred
53
-
54
- # Codex: register the MCP server and prefer both tools.
55
- npx deepseek-web-retrieval init --host codex --scope global --search preferred --fetch preferred
56
- ```
61
+ Set `DEEPSEEK_API_KEY` in the environment that launches your host; OpenCode can also
62
+ use its stored DeepSeek key. Run `init` for your host to preview a configuration — the
63
+ command shape is the quickstart's; each host guide shows its recommended tiers.
57
64
 
58
65
  `--search` and `--fetch` each pick a tier — how strongly the host steers toward the
59
66
  DeepSeek tool, chosen independently per capability:
@@ -75,12 +82,12 @@ Tiers: search=preferred, fetch=preferred
75
82
 
76
83
  Files:
77
84
  ~/.codex/config.toml
78
- set mcp_servers.deepseek = {"command":"npx","args":["-y","deepseek-web-retrieval"],"env_vars":["DEEPSEEK_API_KEY"]} (was (absent))
85
+ set mcp_servers.deepseek = {"command":"npx","args":["-y","deepseek-web-retrieval"],"env_vars":["DEEPSEEK_API_KEY","DEEPSEEK_... (was (absent))
79
86
  ~/.codex/AGENTS.md
80
87
  upsert marked rules block
81
88
 
82
89
  Notes:
83
- - Codex stdio children do not inherit the parent environment, so the entry forwards DEEPSEEK_API_KEY explicitly via env_vars; the key must be set in the shell that launches Codex.
90
+ - Codex stdio children do not inherit the parent environment, so the entry forwards DEEPSEEK_API_KEY and every DEEPSEEK_* option variable explicitly via env_vars; shell-set knobs reach the server without hand-editing config.toml (the shared config file works without any forwarding).
84
91
  - Rules block upserted in ~/.codex/AGENTS.md; Codex reads ~/.codex/AGENTS.md plus every AGENTS.md from the project root to the cwd.
85
92
  - Shared config ownership is recorded in ~/.codex/.config.toml.deepseek-web-retrieval.codex.owner.json; uninstall releases it. Keep this local metadata with the config.
86
93
 
@@ -91,14 +98,17 @@ Repeat your chosen command with `--apply` to write the plan. The host guides exp
91
98
  activation steps and per-host tier limits. Pi defaults to the extension path; add
92
99
  `--path mcp` to use its MCP fallback.
93
100
 
101
+ Add `--pin` to register the exact version of the CLI you are running
102
+ (`deepseek-web-retrieval@<version>`) instead of the unpinned name, so hosts keep
103
+ resolving that release rather than every latest publish. The trade-off is no
104
+ auto-updates: re-run `init --pin` from a newer CLI to move the pin.
105
+
94
106
  Other stdio MCP hosts may use the server, but the supported setup guides and installer
95
- currently cover the three hosts above. See the [integration model](docs/integration.md)
96
- for tested versions and the [control tiers](docs/research/control-matrix.md) for routing
97
- limits. For an existing installation, follow the
107
+ currently cover the four hosts above. See the [integration model](docs/integration.md)
108
+ for tested versions and the [control tiers](docs/research/control-matrix.md) for
109
+ routing limits. For an existing installation, follow the
98
110
  [upgrade instructions](docs/integration.md#upgrading-existing-installs).
99
111
 
100
- For shared search, fetch, retry, and privacy behavior, see below.
101
-
102
112
  ## General behavior
103
113
 
104
114
  What this adapter layer adds on top of the
@@ -106,44 +116,55 @@ What this adapter layer adds on top of the
106
116
  own capabilities (Markdown-only output, no JavaScript rendering, no private networks or
107
117
  binary files, per-request billing) are documented there.
108
118
 
119
+ | Default | Value | Knob |
120
+ | --- | --- | --- |
121
+ | Results per search | 10 | `count` |
122
+ | Fetch output cap | 16,000 characters | `fetchMaxChars` |
123
+ | Search summary cap | 1,200 characters | `maxSummaryChars` |
124
+ | Request timeout, body read included | 30 s | `searchTimeoutMs` / `fetchTimeoutMs` |
125
+ | Transient retries | 2 (range 0–5) | `maxRetries` |
126
+
109
127
  ### Search
110
128
 
111
- - Requests summaries only (`need_content: false`, `summary` falling back to `snippet`);
112
- full page content never enters the results.
113
- - Returns at most ten results by default (matching the API's `count` default and the
114
- industry norm for AI-native search APIs), deduplicating URLs.
115
- - Optional `rerank_score` and `authority` thresholds are off by default — the default
116
- returns exactly what DeepSeek ranked, including results without a score;
117
- when a positive threshold is set, results below it (or without a score to
118
- compare) are dropped.
119
- - Builds `blockedDomains`, `includeDomains`, and `language` into query operators and
129
+ - Requests summaries only (`need_content: false`, falling back from `summary` to
130
+ `snippet`); full page content never enters the results.
131
+ - Deduplicates URLs; an empty result set is normal, not an error.
132
+ - Builds `blockedDomains`, `includeDomains`, and `language` into query operators, and
120
133
  rejects the final query locally when it exceeds the API's 128-character limit.
121
- - An empty result set is normal and is not an error.
134
+ - Optional `rerank_score` and `authority` thresholds are off by default — the default
135
+ returns exactly what DeepSeek ranked. A positive threshold drops results below it.
136
+ A missing `rerank_score` is dropped too; an unknown `authority` stays unless
137
+ `allowUnknownAuthority` is set to false.
138
+ - On the paths where this package defines the search tool's inputs (the MCP server and
139
+ the Pi extension), the tool accepts an optional `original_question`: the user's
140
+ question in their own words. It is forwarded as DeepSeek's `ori_question`, trimmed
141
+ and truncated to 128 characters; on the Pi extension, a blank input falls back to the
142
+ most recent user message in the session.
122
143
 
123
144
  ### Fetch
124
145
 
125
- - Output is capped at 16,000 characters by default, including the title; a
126
- `[content truncated]` marker is added when the limit leaves room for it.
146
+ - Output is capped per the table above, title included; a `[content truncated]` marker
147
+ is added when the limit leaves room for it.
127
148
  - A page that already opens with its title as a top-level heading does not get a
128
149
  duplicate title.
129
- - Responses larger than 5 MiB are rejected before parsing; URLs must be absolute
130
- `http://` or `https://`, credential-free, and at most 8,192 characters.
150
+ - URLs must be absolute `http://` or `https://`, credential-free, and at most 8,192
151
+ characters; responses larger than 5 MiB are rejected before parsing.
131
152
  - `format: "text"` and `format: "html"` are rejected rather than misrepresented.
132
153
  - Allowed/blocked domain lists and private-host blocking are enforced on the client,
133
154
  before a request leaves the machine.
134
155
 
135
156
  ### Timeouts and retries
136
157
 
137
- Request timeouts include reading the response body. Retries are disabled by default;
138
- when enabled, retryable responses are 408, 425, 429, and 5xx, and `Retry-After` is honored
139
- up to 10 seconds. Other failures, including 401, timeouts, and network errors, fail
158
+ Request timeouts include reading the response body. Transient failures are retried per
159
+ the table; retryable responses are 408, 425, 429, and 5xx, and `Retry-After` is honored
160
+ up to 10 seconds. Other failures — including 401, timeouts, and network errors — fail
140
161
  without retrying.
141
162
 
142
163
  ### No automatic fallback
143
164
 
144
- If no API key is available, Search and Fetch fail. If DeepSeek is unavailable, returns an
145
- error, or times out, the request fails. The tool does not silently switch to another search
146
- provider or fetch implementation.
165
+ If no API key is available, Search and Fetch fail. If DeepSeek is unavailable, returns
166
+ an error, or times out, the request fails. The tool does not silently switch to another
167
+ search provider or fetch implementation.
147
168
 
148
169
  ### Privacy and cost
149
170
 
@@ -151,6 +172,46 @@ Queries and URLs are sent to `https://api.deepseek.com`; the API key is sent onl
151
172
  Bearer token to DeepSeek and to nothing else. Retrieval is billed per successful request —
152
173
  see the official docs for pricing and rate limits before enabling a team deployment.
153
174
 
175
+ ## Configuration
176
+
177
+ Every knob resolves through one chain, low → high, identically on every host:
178
+
179
+ `built-in defaults < shared config file < DEEPSEEK_* environment < host-native config`
180
+
181
+ A higher layer always wins, so nothing already configured loses effect.
182
+
183
+ The shared file works on every host and takes camelCase keys:
184
+ `$XDG_CONFIG_HOME/deepseek-web-retrieval/config.json` — by default
185
+ `~/.config/deepseek-web-retrieval/config.json` on Linux and macOS and
186
+ `%APPDATA%\deepseek-web-retrieval\config.json` on Windows.
187
+
188
+ ```json
189
+ {
190
+ "count": 20,
191
+ "blockedDomains": ["pinterest.com"],
192
+ "language": "zh",
193
+ "searchLocalization": "203.0.113.7"
194
+ }
195
+ ```
196
+
197
+ Unknown keys and host-integration keys are warned about on stderr and ignored. The API
198
+ key does not go in the file — it keeps its existing channels (`DEEPSEEK_API_KEY` in the
199
+ environment, or OpenCode's stored credential).
200
+
201
+ Which layer to set for a knob, the full file-key ↔ `DEEPSEEK_*` mapping, per-knob
202
+ defaults, and special semantics live in the [configuration guide](docs/configuration.md).
203
+ Per-host mechanics — how the environment reaches a stdio server, each host's output caps
204
+ and deadlines — live in the host guides: [Codex](docs/agents/codex.md),
205
+ [Claude Code](docs/agents/claude-code.md),
206
+ [Pi](docs/agents/pi.md), [OpenCode](docs/agents/opencode-v2.md).
207
+
208
+ To see what actually resolves, run `npx deepseek-web-retrieval config`: every knob
209
+ printed with its value and its source (`default`, `file`, or `env`). Problems in the
210
+ file or in `DEEPSEEK_*` variables are replayed as visible warnings, and it exits 1 when
211
+ there are any — so it doubles as a dotfile CI check. `npx deepseek-web-retrieval config
212
+ --search "<query>"` runs one billed search through the effective configuration to verify
213
+ the key, config, and network end to end.
214
+
154
215
  ## Development
155
216
 
156
217
  ```bash
@@ -162,10 +223,9 @@ Use `bun run lint:fix` to apply Biome's safe lint fixes and formatting. See
162
223
  [CONTRIBUTING.md](CONTRIBUTING.md) for development checks, e2e scenarios, and
163
224
  [automated tag releases](CONTRIBUTING.md#automated-releases).
164
225
 
165
- The test suite mocks the DeepSeek HTTP API and the OpenCode and Pi host APIs, and drives the
166
- MCP server with SDK clients pinned to each supported protocol revision. Real API calls
226
+ The test suite mocks the DeepSeek API and the OpenCode and Pi host APIs; real API calls
167
227
  require a funded DeepSeek account. Shared retrieval logic lives in `src/core/`; adapters
168
- live in `src/<agent>/` (the cross-host MCP server lives in `src/mcp/`). Adapter docs live
228
+ live in `src/<agent>/` (the cross-host MCP server lives in `src/mcp/`), with adapter docs
169
229
  in `docs/agents/<agent>.md`.
170
230
 
171
231
  ## Prior art