deepseek-web-retrieval 0.3.0 → 0.4.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.
- package/CHANGELOG.md +17 -0
- package/README.md +42 -19
- package/dist/cli.js +5 -15
- package/docs/agents/codex.md +4 -4
- package/docs/agents/opencode-v2.md +5 -5
- package/docs/agents/pi.md +4 -4
- package/docs/research/search-api-defaults.md +309 -0
- package/package.json +1 -1
- package/src/core/constants.ts +9 -3
- package/src/core/options.ts +1 -1
- package/src/mcp/config.ts +2 -14
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here.
|
|
4
4
|
|
|
5
|
+
## 0.4.0
|
|
6
|
+
|
|
7
|
+
- Ground the search defaults in surveyed industry factory defaults
|
|
8
|
+
([research](docs/research/search-api-defaults.md)): every surveyed AI-native search API
|
|
9
|
+
returns ten results by default and none filters results client-side by score or
|
|
10
|
+
authority, so `maxResults` moves 5 → 10 (matching the API `count` default) and the
|
|
11
|
+
`minRerank`/`minAuthority` thresholds move to 0 with `allowUnknownAuthority` flipping
|
|
12
|
+
to `true` — the pass-through default returns what DeepSeek ranked, and the thresholds
|
|
13
|
+
remain available as opt-ins. `DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY` becomes a
|
|
14
|
+
false-only switch (`false`/`0`/`no`/`off` disables) since the default is now on.
|
|
15
|
+
Unchanged and now evidence-backed: `maxRetries=0` (search-API SDK cohort: tavily-python
|
|
16
|
+
and Linkup ship no retries; the 2-retry defaults belong to chat-completion SDKs), the
|
|
17
|
+
30 s timeout, and the 1,200/16,000-character truncations
|
|
18
|
+
- Drop the "Token- and cost-efficient" bullet from the README's Features section —
|
|
19
|
+
the default parameters are no longer endorsed as a selling point, and their behavior
|
|
20
|
+
is stated neutrally in General behavior
|
|
21
|
+
|
|
5
22
|
## 0.3.0
|
|
6
23
|
|
|
7
24
|
- Close the lifecycle gaps in the keyless e2e coverage with a `reinit` scenario: tier
|
package/README.md
CHANGED
|
@@ -9,6 +9,24 @@ coding agents are in progress.
|
|
|
9
9
|
|
|
10
10
|
This is an unofficial community project. It is not affiliated with OpenCode or DeepSeek.
|
|
11
11
|
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **One core, every host** — a native OpenCode v2 plugin plus a stdio MCP
|
|
15
|
+
server for everything else; identical retrieval behavior on each
|
|
16
|
+
- **Tiered routing** — optional, preferred, forced, or off, per capability;
|
|
17
|
+
forced refuses when exclusivity is impossible
|
|
18
|
+
- **Plan-then-apply installer** — every write previewed as old → new before
|
|
19
|
+
touching disk; arrays merge instead of replacing; uninstall reverses
|
|
20
|
+
exactly what was applied
|
|
21
|
+
- **Trap-aware detection** — catches what the agents' own docs don't warn
|
|
22
|
+
about: Codex's silent `[tools] web_search` no-op, Pi's codemode hiding MCP
|
|
23
|
+
tools; conflicting rules and web-capable servers surface in the plan
|
|
24
|
+
- **Git-safe installs** — the key never enters config files
|
|
25
|
+
(`${DEEPSEEK_API_KEY}` indirection or `env_vars`), so a project-scope
|
|
26
|
+
install commits clean
|
|
27
|
+
- **Fails loudly, never falls back** — no silent provider switches;
|
|
28
|
+
localhost and private URLs blocked before they leave the machine
|
|
29
|
+
|
|
12
30
|
## Usage
|
|
13
31
|
|
|
14
32
|
Shipped adapters:
|
|
@@ -31,28 +49,34 @@ For shared search, fetch, retry, and privacy behavior, see below.
|
|
|
31
49
|
|
|
32
50
|
## General behavior
|
|
33
51
|
|
|
52
|
+
What this adapter layer adds on top of the
|
|
53
|
+
[DeepSeek Search and Fetch APIs](https://api-docs.deepseek.com/guides/search) — the APIs'
|
|
54
|
+
own capabilities (Markdown-only output, no JavaScript rendering, no private networks or
|
|
55
|
+
binary files, per-request billing) are documented there.
|
|
56
|
+
|
|
34
57
|
### Search
|
|
35
58
|
|
|
36
|
-
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
59
|
+
- Requests summaries only (`need_content: false`, `summary` falling back to `snippet`);
|
|
60
|
+
full page content never enters the results.
|
|
61
|
+
- Returns at most ten results by default (matching the API's `count` default and the
|
|
62
|
+
industry norm for AI-native search APIs), deduplicating URLs. Optional
|
|
63
|
+
`rerank_score` and `authority` thresholds are off by default; when enabled they
|
|
64
|
+
drop results below the configured score or tier.
|
|
65
|
+
- Builds `blockedDomains`, `includeDomains`, and `language` into query operators and
|
|
66
|
+
rejects the final query locally when it exceeds the API's 128-character limit.
|
|
41
67
|
- An empty result set is normal and is not an error.
|
|
42
68
|
|
|
43
69
|
### Fetch
|
|
44
70
|
|
|
45
|
-
-
|
|
46
|
-
- Output is capped at 16,000 characters by default, including the title. A
|
|
71
|
+
- Output is capped at 16,000 characters by default, including the title; a
|
|
47
72
|
`[content truncated]` marker is added when the limit leaves room for it.
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
- Responses larger than 5 MiB are rejected before parsing
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
files are unsupported.
|
|
73
|
+
- A page that already opens with its title as a top-level heading does not get a
|
|
74
|
+
duplicate title.
|
|
75
|
+
- Responses larger than 5 MiB are rejected before parsing; URLs must be absolute
|
|
76
|
+
`http://` or `https://`, credential-free, and at most 8,192 characters.
|
|
77
|
+
- `format: "text"` and `format: "html"` are rejected rather than misrepresented.
|
|
78
|
+
- Allowed/blocked domain lists and private-host blocking are enforced on the client,
|
|
79
|
+
before a request leaves the machine.
|
|
56
80
|
|
|
57
81
|
### Timeouts and retries
|
|
58
82
|
|
|
@@ -68,10 +92,9 @@ provider or fetch implementation.
|
|
|
68
92
|
|
|
69
93
|
### Privacy and cost
|
|
70
94
|
|
|
71
|
-
Queries and URLs are sent to `https://api.deepseek.com
|
|
72
|
-
Bearer token to DeepSeek
|
|
73
|
-
|
|
74
|
-
wait, reduce concurrency, or increase retries.
|
|
95
|
+
Queries and URLs are sent to `https://api.deepseek.com`; the API key is sent only as a
|
|
96
|
+
Bearer token to DeepSeek and to nothing else. Retrieval is billed per successful request —
|
|
97
|
+
see the official docs for pricing and rate limits before enabling a team deployment.
|
|
75
98
|
|
|
76
99
|
## Development
|
|
77
100
|
|
package/dist/cli.js
CHANGED
|
@@ -16,7 +16,7 @@ var __export = (target, all) => {
|
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
|
|
18
18
|
// src/core/constants.ts
|
|
19
|
-
var SEARCH_ENDPOINT = "https://api.deepseek.com/v1/tools/search", FETCH_ENDPOINT = "https://api.deepseek.com/v1/tools/fetch", DEFAULT_SEARCH_COUNT = 10, DEFAULT_MAX_RESULTS =
|
|
19
|
+
var SEARCH_ENDPOINT = "https://api.deepseek.com/v1/tools/search", FETCH_ENDPOINT = "https://api.deepseek.com/v1/tools/fetch", DEFAULT_SEARCH_COUNT = 10, DEFAULT_MAX_RESULTS = 10, DEFAULT_MIN_RERANK = 0, DEFAULT_MIN_AUTHORITY = 0, DEFAULT_MAX_SUMMARY_CHARS = 1200, DEFAULT_FETCH_MAX_CHARS = 16000, DEFAULT_TIMEOUT_MS = 30000, MIN_TIMEOUT_MS = 1000, MAX_TIMEOUT_MS = 120000, MAX_QUERY_CHARS = 128, MAX_URL_CHARS = 8192, MAX_ERROR_BODY_CHARS = 2000, MAX_RESPONSE_BYTES, FETCH_TRUNCATION_MARKER = `
|
|
20
20
|
|
|
21
21
|
[content truncated]`, DEFAULT_API_KEY_SOURCE = "auto", DEFAULT_MAX_RETRIES = 0, MAX_RETRIES = 5, DEFAULT_RETRY_BASE_DELAY_MS = 250, MAX_RETRY_DELAY_MS = 1e4, API_KEY_ENV = "DEEPSEEK_API_KEY", ENABLE_SEARCH_ENV = "DEEPSEEK_ENABLE_SEARCH", ENABLE_FETCH_ENV = "DEEPSEEK_ENABLE_FETCH";
|
|
22
22
|
var init_constants = __esm(() => {
|
|
@@ -4128,7 +4128,7 @@ function resolveSearchOptions(input) {
|
|
|
4128
4128
|
maxResults: clampInt(input?.maxResults, DEFAULT_MAX_RESULTS, 0, 50),
|
|
4129
4129
|
minRerank: finiteNumber(input?.minRerank, DEFAULT_MIN_RERANK),
|
|
4130
4130
|
minAuthority: finiteNumber(input?.minAuthority, DEFAULT_MIN_AUTHORITY),
|
|
4131
|
-
allowUnknownAuthority: input?.allowUnknownAuthority
|
|
4131
|
+
allowUnknownAuthority: input?.allowUnknownAuthority !== false,
|
|
4132
4132
|
blockedDomains: normalizeDomains(input?.blockedDomains),
|
|
4133
4133
|
includeDomains: normalizeDomains(input?.includeDomains),
|
|
4134
4134
|
language: optionalText(input?.language),
|
|
@@ -4195,10 +4195,8 @@ var DOMAINS_ENV = {
|
|
|
4195
4195
|
fetchAllowedDomains: "DEEPSEEK_FETCH_ALLOWED_DOMAINS",
|
|
4196
4196
|
fetchBlockedDomains: "DEEPSEEK_FETCH_BLOCKED_DOMAINS"
|
|
4197
4197
|
};
|
|
4198
|
-
var FLAG_ENV = {
|
|
4199
|
-
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY"
|
|
4200
|
-
};
|
|
4201
4198
|
var FALSE_ONLY_ENV = {
|
|
4199
|
+
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY",
|
|
4202
4200
|
fetchBlockPrivateHosts: "DEEPSEEK_FETCH_BLOCK_PRIVATE_HOSTS",
|
|
4203
4201
|
searchEnabled: ENABLE_SEARCH_ENV,
|
|
4204
4202
|
fetchEnabled: ENABLE_FETCH_ENV
|
|
@@ -4212,7 +4210,7 @@ function pluginOptionsFromEnv(env) {
|
|
|
4212
4210
|
putNumber(options, "maxResults", env);
|
|
4213
4211
|
putNumber(options, "minRerank", env);
|
|
4214
4212
|
putNumber(options, "minAuthority", env);
|
|
4215
|
-
|
|
4213
|
+
putFalseOnly(options, "allowUnknownAuthority", env);
|
|
4216
4214
|
putDomains(options, "blockedDomains", env);
|
|
4217
4215
|
putDomains(options, "includeDomains", env);
|
|
4218
4216
|
putText(options, "language", env);
|
|
@@ -4248,10 +4246,6 @@ function putText(target, key, env) {
|
|
|
4248
4246
|
if (trimmed)
|
|
4249
4247
|
target[key] = trimmed;
|
|
4250
4248
|
}
|
|
4251
|
-
function putBoolean(target, key, env) {
|
|
4252
|
-
if (isTrueValue(env[FLAG_ENV[key]]))
|
|
4253
|
-
target[key] = true;
|
|
4254
|
-
}
|
|
4255
4249
|
function putFalseOnly(target, key, env) {
|
|
4256
4250
|
if (isFalseValue(env[FALSE_ONLY_ENV[key]]))
|
|
4257
4251
|
target[key] = false;
|
|
@@ -4264,10 +4258,6 @@ function putDomains(target, key, env) {
|
|
|
4264
4258
|
if (domains.length > 0)
|
|
4265
4259
|
target[key] = domains;
|
|
4266
4260
|
}
|
|
4267
|
-
function isTrueValue(value) {
|
|
4268
|
-
const trimmed = value?.trim().toLowerCase();
|
|
4269
|
-
return trimmed === "true" || trimmed === "1" || trimmed === "yes" || trimmed === "on";
|
|
4270
|
-
}
|
|
4271
4261
|
function isFalseValue(value) {
|
|
4272
4262
|
const trimmed = value?.trim().toLowerCase();
|
|
4273
4263
|
return trimmed === "false" || trimmed === "0" || trimmed === "no" || trimmed === "off";
|
|
@@ -4725,7 +4715,7 @@ var SEARCH_QUERY_OPERATORS = "Use site:/-site: operators in the query to include
|
|
|
4725
4715
|
var package_default = {
|
|
4726
4716
|
$schema: "https://json.schemastore.org/package.json",
|
|
4727
4717
|
name: "deepseek-web-retrieval",
|
|
4728
|
-
version: "0.
|
|
4718
|
+
version: "0.4.0",
|
|
4729
4719
|
description: "Token-efficient DeepSeek Search and Fetch for coding agents, starting with OpenCode v2.",
|
|
4730
4720
|
type: "module",
|
|
4731
4721
|
license: "MIT",
|
package/docs/agents/codex.md
CHANGED
|
@@ -127,10 +127,10 @@ defaults and clamping match the other adapters. `DEEPSEEK_API_KEY` goes in `env_
|
|
|
127
127
|
| --- | --- | --- |
|
|
128
128
|
| `DEEPSEEK_ENABLE_SEARCH` | `true` | Register the search tool. Only an explicit `false`/`0`/`no`/`off` disables it; at least one tool must stay enabled. |
|
|
129
129
|
| `DEEPSEEK_SEARCH_COUNT` | `10` | Results requested from DeepSeek, 1–50. Billing is per request, not per result. |
|
|
130
|
-
| `DEEPSEEK_SEARCH_MAX_RESULTS` | `
|
|
131
|
-
| `DEEPSEEK_SEARCH_MIN_RERANK` | `
|
|
132
|
-
| `DEEPSEEK_SEARCH_MIN_AUTHORITY` | `
|
|
133
|
-
| `DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY` | `
|
|
130
|
+
| `DEEPSEEK_SEARCH_MAX_RESULTS` | `10` | Results returned to the model after filtering, 0–50. `0` returns no results. |
|
|
131
|
+
| `DEEPSEEK_SEARCH_MIN_RERANK` | `0` | Drop results below this relevance score. DeepSeek scores are 0–3. |
|
|
132
|
+
| `DEEPSEEK_SEARCH_MIN_AUTHORITY` | `0` | Drop known authorities below this tier. Authority is 0–4. |
|
|
133
|
+
| `DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY` | `true` | Keep results whose authority is missing or unknown. Set `false`/`0` to drop them. |
|
|
134
134
|
| `DEEPSEEK_SEARCH_BLOCKED_DOMAINS` | unset | Comma-separated; adds `-site:` operators to the query. |
|
|
135
135
|
| `DEEPSEEK_SEARCH_INCLUDE_DOMAINS` | unset | Comma-separated; restricts results with `site:` operators. |
|
|
136
136
|
| `DEEPSEEK_SEARCH_LANGUAGE` | unset | Adds a `lang:` operator, for example `zh,en`. |
|
|
@@ -100,7 +100,7 @@ A complete global config:
|
|
|
100
100
|
Use the bare package name (optionally pinned) as the `package` value:
|
|
101
101
|
|
|
102
102
|
```jsonc
|
|
103
|
-
"plugins": [{ "package": "deepseek-web-retrieval@0.
|
|
103
|
+
"plugins": [{ "package": "deepseek-web-retrieval@0.4.0" }]
|
|
104
104
|
```
|
|
105
105
|
|
|
106
106
|
**Global checkout**
|
|
@@ -173,10 +173,10 @@ Set these in the plugin's `options` object.
|
|
|
173
173
|
| --- | --- | --- |
|
|
174
174
|
| `searchEnabled` | `true` | Register the DeepSeek search provider at all. Only an explicit `false` disables it. |
|
|
175
175
|
| `count` | `10` | Results requested from DeepSeek, 1–50. Billing is per request, not per result. |
|
|
176
|
-
| `maxResults` | `
|
|
177
|
-
| `minRerank` | `
|
|
178
|
-
| `minAuthority` | `
|
|
179
|
-
| `allowUnknownAuthority` | `
|
|
176
|
+
| `maxResults` | `10` | Results returned to the model after filtering, 0–50. `0` returns no results. |
|
|
177
|
+
| `minRerank` | `0` | Drop results below this relevance score. DeepSeek scores are 0–3. |
|
|
178
|
+
| `minAuthority` | `0` | Drop known authorities below this tier. Authority is 0–4. |
|
|
179
|
+
| `allowUnknownAuthority` | `true` | Keep results whose authority is missing or unknown. Only an explicit `false` disables it. |
|
|
180
180
|
| `blockedDomains` | `[]` | Add `-site:` operators to the search query. |
|
|
181
181
|
| `includeDomains` | `[]` | Restrict results with `site:` operators. |
|
|
182
182
|
| `language` | unset | Add a `lang:` operator, for example `zh,en`. |
|
package/docs/agents/pi.md
CHANGED
|
@@ -132,10 +132,10 @@ defaults and clamping match the OpenCode adapter.
|
|
|
132
132
|
| --- | --- | --- |
|
|
133
133
|
| `DEEPSEEK_ENABLE_SEARCH` | `true` | Register the search tool. Only an explicit `false`/`0`/`no`/`off` disables it; at least one tool must stay enabled. |
|
|
134
134
|
| `DEEPSEEK_SEARCH_COUNT` | `10` | Results requested from DeepSeek, 1–50. Billing is per request, not per result. |
|
|
135
|
-
| `DEEPSEEK_SEARCH_MAX_RESULTS` | `
|
|
136
|
-
| `DEEPSEEK_SEARCH_MIN_RERANK` | `
|
|
137
|
-
| `DEEPSEEK_SEARCH_MIN_AUTHORITY` | `
|
|
138
|
-
| `DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY` | `
|
|
135
|
+
| `DEEPSEEK_SEARCH_MAX_RESULTS` | `10` | Results returned to the model after filtering, 0–50. `0` returns no results. |
|
|
136
|
+
| `DEEPSEEK_SEARCH_MIN_RERANK` | `0` | Drop results below this relevance score. DeepSeek scores are 0–3. |
|
|
137
|
+
| `DEEPSEEK_SEARCH_MIN_AUTHORITY` | `0` | Drop known authorities below this tier. Authority is 0–4. |
|
|
138
|
+
| `DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY` | `true` | Keep results whose authority is missing or unknown. Set `false`/`0` to drop them. |
|
|
139
139
|
| `DEEPSEEK_SEARCH_BLOCKED_DOMAINS` | unset | Comma-separated; adds `-site:` operators to the query. |
|
|
140
140
|
| `DEEPSEEK_SEARCH_INCLUDE_DOMAINS` | unset | Comma-separated; restricts results with `site:` operators. |
|
|
141
141
|
| `DEEPSEEK_SEARCH_LANGUAGE` | unset | Adds a `lang:` operator, for example `zh,en`. |
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# Search and fetch API defaults across vendors
|
|
2
|
+
|
|
3
|
+
This note answers one question: what are the **factory defaults** — the values applied when a
|
|
4
|
+
caller passes nothing — of the mature AI-native web-search and web-fetch APIs? It exists
|
|
5
|
+
because this repo layers its own client-side defaults on top of the DeepSeek Search/Fetch API,
|
|
6
|
+
and the original values (`maxResults=5` on an API `count` of 10, `minRerank=1.5`,
|
|
7
|
+
`minAuthority=2`, `allowUnknownAuthority=false`, `maxRetries=0`, `timeout=30s`, fetch
|
|
8
|
+
truncation at 16,000 characters, summary truncation at 1,200, response-body cap 5 MiB) were
|
|
9
|
+
challenged as arbitrary. The pages below are the benchmark against which the repo's defaults
|
|
10
|
+
are grounded; based on this survey the search-side defaults were changed on 2026-10-21 to
|
|
11
|
+
`maxResults=10`, `minRerank=0`, `minAuthority=0`, `allowUnknownAuthority=true` (filters stay
|
|
12
|
+
available as opt-ins). It records facts only; the closing section lines the repo's values up
|
|
13
|
+
against them without recommending changes.
|
|
14
|
+
|
|
15
|
+
**Research baseline:** 2026-10-21. Claims are cited to primary sources only: official vendor
|
|
16
|
+
documentation and official SDK source (GitHub repos and published npm/PyPI packages). Secondhand
|
|
17
|
+
blogs and tutorials are excluded. "Default" means the value in force when the parameter is
|
|
18
|
+
omitted — not the allowed range, and not an example value. Where no default is published, that
|
|
19
|
+
is stated as such rather than guessed.
|
|
20
|
+
|
|
21
|
+
The five questions asked of every product:
|
|
22
|
+
|
|
23
|
+
1. Search-result count default (the analogue of this repo's `maxResults`/API `count`).
|
|
24
|
+
2. Any **client-side relevance/authority filtering** default (the analogue of
|
|
25
|
+
`minRerank`/`minAuthority`/`allowUnknownAuthority`) — in particular, does anyone drop
|
|
26
|
+
results by authority in the client?
|
|
27
|
+
3. HTTP retry default at the SDK layer.
|
|
28
|
+
4. Request timeout default (SDK and API layer).
|
|
29
|
+
5. Fetched-content truncation default (character limits, byte caps).
|
|
30
|
+
|
|
31
|
+
## Tavily
|
|
32
|
+
|
|
33
|
+
API defaults from the official OpenAPI reference for `POST /search`
|
|
34
|
+
([docs](https://docs.tavily.com/documentation/api-reference/endpoint/search)):
|
|
35
|
+
|
|
36
|
+
| Parameter | Default when omitted | Source |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| `max_results` | **10** (min 0, max 20) | [API reference](https://docs.tavily.com/documentation/api-reference/endpoint/search) |
|
|
39
|
+
| `search_depth` | **`basic`** (vs `advanced`/`fast`/`ultra-fast`) | same |
|
|
40
|
+
| `chunks_per_source` | **3** (chunks of ~500 chars `basic`/`fast`, ~800 `advanced`) | same |
|
|
41
|
+
| `topic` | **`general`** | same |
|
|
42
|
+
| `include_answer` / `include_raw_content` / `include_images` | **false** | same |
|
|
43
|
+
| `auto_parameters` | **false** | same |
|
|
44
|
+
| `include_domains` / `exclude_domains` | **empty** | same |
|
|
45
|
+
| `include_domains_mode` | **`restrict`** ("`include_domains` acts as a hard filter unless set to `prefer`") | same |
|
|
46
|
+
|
|
47
|
+
No relevance score, authority tier, or any other per-result quality signal is returned or
|
|
48
|
+
filterable in the client — ranking is server-side and opaque.
|
|
49
|
+
|
|
50
|
+
SDK layer ([tavily-python, master](https://github.com/tavily-ai/tavily-python/blob/master/tavily/tavily.py)):
|
|
51
|
+
`max_results` and `search_depth` default to `None` (so the API defaults above apply); `search`
|
|
52
|
+
has `timeout: float = 60` clamped to `min(timeout, 120)` seconds; `extract` defaults to 30 s and
|
|
53
|
+
`crawl` to 150 s. The client posts through a plain `requests.Session` with no retry adapter —
|
|
54
|
+
the only retry-related code parses a `retry_after_seconds` field out of error payloads.
|
|
55
|
+
|
|
56
|
+
## Exa
|
|
57
|
+
|
|
58
|
+
API defaults from the official OpenAPI spec
|
|
59
|
+
([reference](https://exa.ai/docs/reference/search)):
|
|
60
|
+
|
|
61
|
+
| Parameter | Default when omitted | Source |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| `numResults` | **10** (max 100) | [reference](https://exa.ai/docs/reference/search); the [search quickstart](https://exa.ai/docs/search/quickstart) states it in prose: "Search returns up to 10 results by default" |
|
|
64
|
+
| `type` | **`auto`** | [reference](https://exa.ai/docs/reference/search) |
|
|
65
|
+
| `contents.text` (boolean form) | **false** — "If true, returns full page text with default settings. If false, disables text return." | same |
|
|
66
|
+
| `contents.text.verbosity` | **`compact`** | same |
|
|
67
|
+
| `contents.highlights` (boolean form) | **false** | same |
|
|
68
|
+
| `moderation` | **false** | same |
|
|
69
|
+
| `contents.livecrawlTimeout` | **10000 ms** | same |
|
|
70
|
+
| `contents.text.maxCharacters` | **no published default** (max 1,000,000); the [contents quickstart](https://exa.ai/docs/contents/quickstart) frames it as opt-in: "Full pages can be large, so use `maxCharacters` when you need a limit" | both |
|
|
71
|
+
|
|
72
|
+
Like Tavily, Exa exposes no per-result authority/score field and no client filter for one;
|
|
73
|
+
`moderation` (off by default) is content-moderation, not authority.
|
|
74
|
+
|
|
75
|
+
## Perplexity
|
|
76
|
+
|
|
77
|
+
The Sonar chat-completions API was retired on 2026-09-27; the live products are the Search API
|
|
78
|
+
and the Agent API ([migration guide](https://docs.perplexity.ai/docs/agent-api/migrate-from-sonar/overview)).
|
|
79
|
+
|
|
80
|
+
Search API (`POST /search`,
|
|
81
|
+
[reference](https://docs.perplexity.ai/api-reference/search-post); the
|
|
82
|
+
[quickstart](https://docs.perplexity.ai/docs/search/quickstart) restates it):
|
|
83
|
+
|
|
84
|
+
| Parameter | Default when omitted | Source |
|
|
85
|
+
| --- | --- | --- |
|
|
86
|
+
| `max_results` | **10** (1–20) | [quickstart](https://docs.perplexity.ai/docs/search/quickstart): "`max_results` accepts values from 1 to 20 and defaults to 10" |
|
|
87
|
+
| `search_type` | **`web`** | [reference](https://docs.perplexity.ai/api-reference/search-post) |
|
|
88
|
+
|
|
89
|
+
Agent API `web_search` tool ([tool guide](https://docs.perplexity.ai/docs/agent-api/tools/web-search),
|
|
90
|
+
[schema](https://docs.perplexity.ai/api-reference/agent-post)): `max_results` accepts 1–50 and
|
|
91
|
+
`max_tokens`/`max_tokens_per_page` cap search context, but none of the three publishes a numeric
|
|
92
|
+
default — "When omitted, the default budget applies" is all the docs say. The one published
|
|
93
|
+
tool-count default in the same schema is `image_search.max_results`: **5** (1–30)
|
|
94
|
+
([reference](https://docs.perplexity.ai/api-reference/agent-post)). The retired Sonar
|
|
95
|
+
`web_search_options.search_context_size` has no named-size successor; the
|
|
96
|
+
[migration table](https://docs.perplexity.ai/docs/agent-api/migrate-from-sonar/how-to) maps it
|
|
97
|
+
to the token budgets above, and the current docs no longer state its old default. No
|
|
98
|
+
authority/score filtering exists on any of these surfaces.
|
|
99
|
+
|
|
100
|
+
## Firecrawl
|
|
101
|
+
|
|
102
|
+
API defaults from the official OpenAPI references
|
|
103
|
+
([search](https://docs.firecrawl.dev/api-reference/endpoint/search),
|
|
104
|
+
[scrape](https://docs.firecrawl.dev/api-reference/endpoint/scrape)):
|
|
105
|
+
|
|
106
|
+
| Parameter | Default when omitted | Source |
|
|
107
|
+
| --- | --- | --- |
|
|
108
|
+
| search `limit` | **10** (1–100; per source type when multiple `sources`) | [search reference](https://docs.firecrawl.dev/api-reference/endpoint/search) |
|
|
109
|
+
| search `sources` | **`["web"]`** | same |
|
|
110
|
+
| search `timeout` | **60000 ms** | same |
|
|
111
|
+
| search `highlights` | **true** | same |
|
|
112
|
+
| scrape `timeout` | **60000 ms** (min 1 s, max 300 s) | [scrape reference](https://docs.firecrawl.dev/api-reference/endpoint/scrape) |
|
|
113
|
+
| scrape `onlyMainContent` | **true** | same |
|
|
114
|
+
| scrape `maxAge` (cache freshness window) | **172800000 ms (2 days)** | same |
|
|
115
|
+
|
|
116
|
+
No character or byte truncation default is published for scraped content. No authority/score
|
|
117
|
+
filter exists.
|
|
118
|
+
|
|
119
|
+
SDK layer (`@mendable/firecrawl-js` 4.50.0, npm tarball with registry provenance;
|
|
120
|
+
[source](https://www.npmjs.com/package/@mendable/firecrawl-js)): `maxRetries` defaults to
|
|
121
|
+
**3** (`options.maxRetries ?? 3`), retrying **only HTTP 502** with exponential backoff
|
|
122
|
+
(`backoffFactor` 0.5 s × 2^attempt); `timeoutMs` defaults to **300000 ms (5 min)**.
|
|
123
|
+
|
|
124
|
+
## Jina Reader (r.jina.ai / s.jina.ai)
|
|
125
|
+
|
|
126
|
+
Official product page ([jina.ai/reader](https://jina.ai/reader/)) and official repo
|
|
127
|
+
([jina-ai/reader](https://github.com/jina-ai/reader)):
|
|
128
|
+
|
|
129
|
+
| Behavior | Default | Source |
|
|
130
|
+
| --- | --- | --- |
|
|
131
|
+
| Search-mode result count (`s.jina.ai`) | **fixed 5** — "Reader searches the web, fetches the top 5 results, visits each URL, and applies `r.jina.ai` to it"; no count parameter is exposed | [repo README](https://github.com/jina-ai/reader/blob/main/README.md); the [product page](https://jina.ai/reader/) likewise: "it returns a list of five entries" |
|
|
132
|
+
| `x-timeout` | **no default set** — optional header, integer seconds, max 180; when absent the option stays `null` (no client-side deadline) | [README](https://github.com/jina-ai/reader/blob/main/README.md) and [`crawler-options.ts`](https://github.com/jina-ai/reader/blob/main/src/dto/crawler-options.ts) (`instance.timeout ??= null`) |
|
|
133
|
+
| `x-token-budget` | **no default** (parsed only when sent) | [`crawler-options.ts`](https://github.com/jina-ai/reader/blob/main/src/dto/crawler-options.ts) |
|
|
134
|
+
| Content truncation | none published | — |
|
|
135
|
+
|
|
136
|
+
No relevance/authority filter; no retry logic documented.
|
|
137
|
+
|
|
138
|
+
## Anthropic web_search / web_fetch server tools
|
|
139
|
+
|
|
140
|
+
Current docs live at
|
|
141
|
+
[web search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool),
|
|
142
|
+
[web fetch tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool),
|
|
143
|
+
and the [server tools guide](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools).
|
|
144
|
+
|
|
145
|
+
| Parameter | Default when omitted | Source |
|
|
146
|
+
| --- | --- | --- |
|
|
147
|
+
| `web_search.max_uses` | optional; no numeric default published ("limits the number of searches performed"; guidance: "Simple factual queries typically use 1–3 searches") | [web search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool) |
|
|
148
|
+
| `web_fetch.max_uses` | optional; **"There is currently no default limit."** | [web fetch tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool) |
|
|
149
|
+
| `web_fetch.max_content_tokens` | optional token cap; **no default value published** (doc example: 100000) — "If the fetched content exceeds this limit, the tool truncates it … applies to text content, not to binary content such as PDFs" | [web fetch tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool) |
|
|
150
|
+
| `web_fetch` URL length | hard max **250 characters** | same (error `url_too_long`) |
|
|
151
|
+
| `web_fetch` content types | text, HTML, PDF only; `robots.txt` and private addresses respected server-side | same |
|
|
152
|
+
| `web_fetch.use_cache` | **true** | same |
|
|
153
|
+
| `web_fetch.citations` | **disabled by default** | same |
|
|
154
|
+
| `response_inclusion` (both tools) | **`"full"`** | both |
|
|
155
|
+
| Result count / authority filter | **neither exists** — the model decides how many searches to run; no score or authority field is returned | both |
|
|
156
|
+
|
|
157
|
+
A widely repeated pair of numbers — "truncate to 20,000 characters" and "5 MiB" — is **not in
|
|
158
|
+
the current official docs** (checked 2026-10-21), nor in the November 2025 snapshot of the same
|
|
159
|
+
page on the Internet Archive; the published truncation mechanism is the token-based
|
|
160
|
+
`max_content_tokens` parameter above, with no published default.
|
|
161
|
+
|
|
162
|
+
SDK layer (official repos, default branch):
|
|
163
|
+
|
|
164
|
+
| SDK | Default timeout | Default max retries | Source |
|
|
165
|
+
| --- | --- | --- | --- |
|
|
166
|
+
| anthropic-sdk-typescript | **10 minutes** (`options.timeout ?? BaseAnthropic.DEFAULT_TIMEOUT`) | **2** (`options.maxRetries ?? 2`) | [`client.ts`](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/src/client.ts) |
|
|
167
|
+
| anthropic-sdk-python | **600 s total, 5 s connect** (`httpx.Timeout(timeout=10 * 60, connect=5.0)`) | **2** (`DEFAULT_MAX_RETRIES = 2`) | [`_constants.py`](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_constants.py) |
|
|
168
|
+
|
|
169
|
+
## OpenAI Responses web_search
|
|
170
|
+
|
|
171
|
+
From the official guide
|
|
172
|
+
([Web search tool](https://platform.openai.com/docs/guides/tools-web-search)):
|
|
173
|
+
|
|
174
|
+
| Parameter | Default when omitted | Source |
|
|
175
|
+
| --- | --- | --- |
|
|
176
|
+
| Result count | **not exposed** — no count parameter; the docs note the size setting "does not set an exact token count or guarantee a specific number of sources or citations" | [guide](https://platform.openai.com/docs/guides/tools-web-search) |
|
|
177
|
+
| `search_context_size` | **`medium`** — "Use `low` for simple lookups, `medium` for a balanced default, and `high` …" | [guide](https://platform.openai.com/docs/guides/tools-web-search) |
|
|
178
|
+
| `external_web_access` | **true** (live access) | [guide](https://platform.openai.com/docs/guides/tools-web-search) |
|
|
179
|
+
| `return_token_budget` | **`default`** — "Uses the standard returned-token budget … the same behavior as omitting `return_token_budget`" (numeric value unpublished) | [guide](https://platform.openai.com/docs/guides/tools-web-search) |
|
|
180
|
+
|
|
181
|
+
No relevance/authority score or filter is exposed on any web-search surface.
|
|
182
|
+
|
|
183
|
+
SDK layer (official repos, default branch):
|
|
184
|
+
|
|
185
|
+
| SDK | Default timeout | Default max retries | Source |
|
|
186
|
+
| --- | --- | --- | --- |
|
|
187
|
+
| openai-node | **600000 ms (10 min)** (`OpenAI.DEFAULT_TIMEOUT = 600000`) | **2** (`@param {number} [opts.maxRetries=2]`) | [`client.ts`](https://github.com/openai/openai-node/blob/master/src/client.ts) |
|
|
188
|
+
| openai-python | **600 s total, 5 s connect** (`httpx.Timeout(timeout=600, connect=5.0)`) | **2** (`DEFAULT_MAX_RETRIES = 2`); initial retry delay 0.5 s, max 8 s | [`_constants.py`](https://github.com/openai/openai-python/blob/main/src/openai/_constants.py) |
|
|
189
|
+
|
|
190
|
+
## Brave Search API
|
|
191
|
+
|
|
192
|
+
From the official Web Search API query documentation
|
|
193
|
+
([docs](https://api-dashboard.search.brave.com/app/documentation/web-search/query)):
|
|
194
|
+
|
|
195
|
+
| Parameter | Default when omitted | Source |
|
|
196
|
+
| --- | --- | --- |
|
|
197
|
+
| `count` | **20** — "Maximum number of results per page (max 20, default 20). The actual number of results returned may be less than count." | [docs](https://api-dashboard.search.brave.com/app/documentation/web-search/query) |
|
|
198
|
+
| `offset` | 0 (0-based, max 9) | same |
|
|
199
|
+
|
|
200
|
+
No relevance/authority filter beyond `safesearch`-style content controls; ranking is
|
|
201
|
+
server-side.
|
|
202
|
+
|
|
203
|
+
## Linkup
|
|
204
|
+
|
|
205
|
+
From the official OpenAPI reference
|
|
206
|
+
([search reference](https://docs.linkup.so/pages/documentation/endpoints/search/reference))
|
|
207
|
+
and the official Python SDK source
|
|
208
|
+
([linkup-python-sdk](https://github.com/LinkupPlatform/linkup-python-sdk/blob/main/src/linkup/_client.py)):
|
|
209
|
+
|
|
210
|
+
| Parameter | Default when omitted | Source |
|
|
211
|
+
| --- | --- | --- |
|
|
212
|
+
| `depth` | **no published default** — enum `flash`/`fast`/`standard`/`deep`; the spec's prose calls `fast` "the recommended default for most agentic applications" without declaring an omission default. The SDK makes `depth` a required argument | [reference](https://docs.linkup.so/pages/documentation/endpoints/search/reference), [`_client.py`](https://github.com/LinkupPlatform/linkup-python-sdk/blob/main/src/linkup/_client.py) |
|
|
213
|
+
| `maxResults` | **no published default** (min 1; schema example: 5) | [reference](https://docs.linkup.so/pages/documentation/endpoints/search/reference) |
|
|
214
|
+
| `includeImages` / `includeInlineCitations` / `includeSources` | **false** | same |
|
|
215
|
+
| SDK `timeout` | **None — "the request will have no timeout"** | [`_client.py`](https://github.com/LinkupPlatform/linkup-python-sdk/blob/main/src/linkup/_client.py) |
|
|
216
|
+
|
|
217
|
+
The SDK has no retry loop for transient failures (its one retry path is the x402 payment
|
|
218
|
+
handshake). No relevance/authority filter exists.
|
|
219
|
+
|
|
220
|
+
## You.com
|
|
221
|
+
|
|
222
|
+
The API documentation is still public at
|
|
223
|
+
[you.com/docs](https://you.com/docs/api-reference/search/v1-search). Defaults for
|
|
224
|
+
`POST /v1/search` ([reference](https://you.com/docs/api-reference/search/v1-search)):
|
|
225
|
+
|
|
226
|
+
| Parameter | Default when omitted | Source |
|
|
227
|
+
| --- | --- | --- |
|
|
228
|
+
| `count` | **10** — per section (`web` and `news`) | [reference](https://you.com/docs/api-reference/search/v1-search) |
|
|
229
|
+
| `safesearch` | **`moderate`** | same |
|
|
230
|
+
| `crawl_timeout` | **10 s** (1–60) | same |
|
|
231
|
+
| `livecrawl_formats` (deprecated) | **`["html"]`** | same |
|
|
232
|
+
| `extraction.highlights.total_max_tokens` | **8192 tokens** (range 1024–8192; "Omit it to get the default budget of 8192") | same |
|
|
233
|
+
| `extraction.full_page.extraction_formats` | **`["markdown"]`** | same |
|
|
234
|
+
| Result content | **snippets by default**; highlights/full-page are opt-in via `extraction` | same |
|
|
235
|
+
|
|
236
|
+
`moderate` safesearch is a content-moderation filter, not an authority filter; no
|
|
237
|
+
relevance/authority score is exposed.
|
|
238
|
+
|
|
239
|
+
## What DeepSeek itself claims
|
|
240
|
+
|
|
241
|
+
The challenge quote attributed to the DeepSeek docs — an "AI 原生的通用搜索引擎" that
|
|
242
|
+
"通过严格的识别机制进行过滤,确保向用户与 LLM 呈现权威可信的信息" — is **not present** on
|
|
243
|
+
<https://api-docs.deepseek.com/guides/search> (checked 2026-10-21, English and 中文 pages).
|
|
244
|
+
The closest positioning sentences actually on the page:
|
|
245
|
+
|
|
246
|
+
- EN: "It is powered by DeepSeek's in-house search engine."
|
|
247
|
+
([guide](https://api-docs.deepseek.com/guides/search))
|
|
248
|
+
- ZH: "该接口由 DeepSeek 自研搜索引擎提供支持。"
|
|
249
|
+
([指南](https://api-docs.deepseek.com/zh-cn/guides/search))
|
|
250
|
+
|
|
251
|
+
So the official docs claim an in-house engine but make **no published claim of server-side
|
|
252
|
+
quality filtering**. What they do publish, verbatim
|
|
253
|
+
([指南](https://api-docs.deepseek.com/zh-cn/guides/search)):
|
|
254
|
+
|
|
255
|
+
- `rerank_score`: "排序分数,0~3 分,综合考虑相关性、权威性、时效性等维度,**大于等于 1.5 分为优质结果**。"
|
|
256
|
+
- `authority`: "网页权威性,0~4(**-1 表示未知**),**大于等于 3 为极权威结果**。"
|
|
257
|
+
- Request defaults: `count` "否 / 默认值 10 / 返回条数,1~50"; `need_content` "否 / false";
|
|
258
|
+
`localization` "否 / 空"; `ori_question` optional.
|
|
259
|
+
- Response sizing: `snippet` "短摘要 … 通常为 100~200 字符"; `summary` "长摘要 … 通常为 600~800 字符".
|
|
260
|
+
|
|
261
|
+
## What this means for this repo's defaults
|
|
262
|
+
|
|
263
|
+
Fact-by-fact alignment of the repo's client-side defaults
|
|
264
|
+
(`src/core/constants.ts`) against the surveyed factory defaults. No recommendation is made
|
|
265
|
+
here; the table only lines up what the industry ships.
|
|
266
|
+
|
|
267
|
+
| Repo default | Industry factory defaults observed above |
|
|
268
|
+
| --- | --- |
|
|
269
|
+
| API `count=10`, client `maxResults=10` (post-dedup cap; `5` before 2026-10-21) | API-level count defaults: Tavily 10, Exa 10, Perplexity Search API 10, Firecrawl 10, You.com 10 (per section), Brave 20. Post-filter caps are uncommon; a fixed 5 exists at Jina (`s.jina.ai` top 5, not configurable) and Perplexity's `image_search` tool (default 5). Linkup's schema example is 5 but no default is published. OpenAI and Anthropic expose no count at all |
|
|
270
|
+
| `minRerank=0`, `minAuthority=0`, `allowUnknownAuthority=true` — no client-side filtering (previously `1.5`/`2`/`false`) | **No surveyed product filters search results client-side by relevance score or authority.** The only published thresholds for DeepSeek's own fields are the docs' quality labels (≥1.5 "优质", ≥3 "极权威") — labels, not filters. The closest shipped analogues are domain allow/block lists (Tavily, Exa, Perplexity, You.com, Anthropic, Brave) and You.com's `safesearch: moderate` default, which is content moderation, not authority |
|
|
271
|
+
| `maxRetries=0` | Official model-API SDKs: OpenAI 2, Anthropic 2 (both languages). Search-API SDKs: firecrawl-js 3 (502 only), tavily-python 0, Linkup SDK 0 |
|
|
272
|
+
| `timeout=30s` (search and fetch, 1–120 s range, covers body read) | Search/scrape API timeouts: Firecrawl 60 s (scrape max 300 s), Tavily SDK search 60 s (cap 120 s) / extract 30 s, You.com `crawl_timeout` 10 s, Linkup SDK no timeout, Jina `x-timeout` unset by default (max 180 s). Model-API SDKs: OpenAI and Anthropic 10 minutes |
|
|
273
|
+
| Fetch truncation 16,000 chars | Exa: page text **off** by default (`contents.text: false`), opt-in `maxCharacters` with no published default; DeepSeek itself: `need_content: false` by default; Anthropic `web_fetch`: token-based `max_content_tokens`, no published default (example 100000), no char/MiB figure in current docs; You.com highlights budget 8192 tokens; Firecrawl and Jina publish no truncation default |
|
|
274
|
+
| Summary truncation 1,200 chars | DeepSeek's own field doc says `summary` is "通常为 600~800 字符"; no surveyed vendor ships a client-side summary cap (they return snippets/highlights sized server-side: Exa verbosity `compact`, You.com highlights budget) |
|
|
275
|
+
| Response body cap 5 MiB | No surveyed product publishes a response-body byte cap; the only published byte-adjacent limits are Anthropic's URL length (250 chars) and content-type whitelist, and Exa's `maxCharacters` ceiling of 1,000,000 characters |
|
|
276
|
+
| Filter markers (`minRerank`/`minAuthority` matching) | Nothing to compare: no surveyed vendor returns a per-result authority tier at all — DeepSeek's `rerank_score`/`authority` response fields are the outlier, which is what makes client-side thresholds possible here and nowhere else in this survey |
|
|
277
|
+
|
|
278
|
+
## Sources
|
|
279
|
+
|
|
280
|
+
- DeepSeek: [Search & Fetch guide (EN)](https://api-docs.deepseek.com/guides/search) ·
|
|
281
|
+
[网页搜索与抓取 (ZH)](https://api-docs.deepseek.com/zh-cn/guides/search)
|
|
282
|
+
- Tavily: [search API reference](https://docs.tavily.com/documentation/api-reference/endpoint/search) ·
|
|
283
|
+
[tavily-python source](https://github.com/tavily-ai/tavily-python/blob/master/tavily/tavily.py)
|
|
284
|
+
- Exa: [search reference (OpenAPI)](https://exa.ai/docs/reference/search) ·
|
|
285
|
+
[search quickstart](https://exa.ai/docs/search/quickstart) ·
|
|
286
|
+
[contents quickstart](https://exa.ai/docs/contents/quickstart)
|
|
287
|
+
- Perplexity: [Search API quickstart](https://docs.perplexity.ai/docs/search/quickstart) ·
|
|
288
|
+
[Search API reference](https://docs.perplexity.ai/api-reference/search-post) ·
|
|
289
|
+
[Agent API web_search tool](https://docs.perplexity.ai/docs/agent-api/tools/web-search) ·
|
|
290
|
+
[Agent API schema](https://docs.perplexity.ai/api-reference/agent-post) ·
|
|
291
|
+
[Sonar migration guide](https://docs.perplexity.ai/docs/agent-api/migrate-from-sonar/how-to)
|
|
292
|
+
- Firecrawl: [search reference](https://docs.firecrawl.dev/api-reference/endpoint/search) ·
|
|
293
|
+
[scrape reference](https://docs.firecrawl.dev/api-reference/endpoint/scrape) ·
|
|
294
|
+
[npm @mendable/firecrawl-js](https://www.npmjs.com/package/@mendable/firecrawl-js)
|
|
295
|
+
- Jina: [reader product page](https://jina.ai/reader/) ·
|
|
296
|
+
[jina-ai/reader README](https://github.com/jina-ai/reader/blob/main/README.md) ·
|
|
297
|
+
[crawler-options.ts](https://github.com/jina-ai/reader/blob/main/src/dto/crawler-options.ts)
|
|
298
|
+
- Anthropic: [web search tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool) ·
|
|
299
|
+
[web fetch tool](https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-fetch-tool) ·
|
|
300
|
+
[server tools](https://platform.claude.com/docs/en/agents-and-tools/tool-use/server-tools) ·
|
|
301
|
+
[anthropic-sdk-typescript client.ts](https://github.com/anthropics/anthropic-sdk-typescript/blob/main/src/client.ts) ·
|
|
302
|
+
[anthropic-sdk-python _constants.py](https://github.com/anthropics/anthropic-sdk-python/blob/main/src/anthropic/_constants.py)
|
|
303
|
+
- OpenAI: [web search tool guide](https://platform.openai.com/docs/guides/tools-web-search) ·
|
|
304
|
+
[openai-node client.ts](https://github.com/openai/openai-node/blob/master/src/client.ts) ·
|
|
305
|
+
[openai-python _constants.py](https://github.com/openai/openai-python/blob/main/src/openai/_constants.py)
|
|
306
|
+
- Brave: [Web Search API query docs](https://api-dashboard.search.brave.com/app/documentation/web-search/query)
|
|
307
|
+
- Linkup: [search reference (OpenAPI)](https://docs.linkup.so/pages/documentation/endpoints/search/reference) ·
|
|
308
|
+
[linkup-python-sdk _client.py](https://github.com/LinkupPlatform/linkup-python-sdk/blob/main/src/linkup/_client.py)
|
|
309
|
+
- You.com: [POST /v1/search reference](https://you.com/docs/api-reference/search/v1-search)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "deepseek-web-retrieval",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.4.0",
|
|
5
5
|
"description": "Token-efficient DeepSeek Search and Fetch for coding agents, starting with OpenCode v2.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
package/src/core/constants.ts
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
export const SEARCH_ENDPOINT = "https://api.deepseek.com/v1/tools/search"
|
|
2
2
|
export const FETCH_ENDPOINT = "https://api.deepseek.com/v1/tools/fetch"
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Search defaults are benchmarked against surveyed AI-native search APIs and
|
|
6
|
+
* DeepSeek's own factory defaults; see docs/research/search-api-defaults.md.
|
|
7
|
+
* Result caps cluster at 10 across vendors, and no surveyed vendor filters
|
|
8
|
+
* results client-side by score or authority — thresholds stay opt-in.
|
|
9
|
+
*/
|
|
4
10
|
export const DEFAULT_SEARCH_COUNT = 10
|
|
5
|
-
export const DEFAULT_MAX_RESULTS =
|
|
6
|
-
export const DEFAULT_MIN_RERANK =
|
|
7
|
-
export const DEFAULT_MIN_AUTHORITY =
|
|
11
|
+
export const DEFAULT_MAX_RESULTS = 10
|
|
12
|
+
export const DEFAULT_MIN_RERANK = 0
|
|
13
|
+
export const DEFAULT_MIN_AUTHORITY = 0
|
|
8
14
|
export const DEFAULT_MAX_SUMMARY_CHARS = 1200
|
|
9
15
|
|
|
10
16
|
export const DEFAULT_FETCH_MAX_CHARS = 16000
|
package/src/core/options.ts
CHANGED
|
@@ -40,7 +40,7 @@ export function resolveSearchOptions(input?: PluginOptions): SearchOptions {
|
|
|
40
40
|
maxResults: clampInt(input?.maxResults, DEFAULT_MAX_RESULTS, 0, 50),
|
|
41
41
|
minRerank: finiteNumber(input?.minRerank, DEFAULT_MIN_RERANK),
|
|
42
42
|
minAuthority: finiteNumber(input?.minAuthority, DEFAULT_MIN_AUTHORITY),
|
|
43
|
-
allowUnknownAuthority: input?.allowUnknownAuthority
|
|
43
|
+
allowUnknownAuthority: input?.allowUnknownAuthority !== false,
|
|
44
44
|
blockedDomains: normalizeDomains(input?.blockedDomains),
|
|
45
45
|
includeDomains: normalizeDomains(input?.includeDomains),
|
|
46
46
|
language: optionalText(input?.language),
|
package/src/mcp/config.ts
CHANGED
|
@@ -30,12 +30,9 @@ const DOMAINS_ENV = {
|
|
|
30
30
|
fetchBlockedDomains: "DEEPSEEK_FETCH_BLOCKED_DOMAINS",
|
|
31
31
|
} as const
|
|
32
32
|
|
|
33
|
-
const FLAG_ENV = {
|
|
34
|
-
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY",
|
|
35
|
-
} as const
|
|
36
|
-
|
|
37
33
|
/** Shared defaults are true; only an explicit false value disables them. */
|
|
38
34
|
const FALSE_ONLY_ENV = {
|
|
35
|
+
allowUnknownAuthority: "DEEPSEEK_SEARCH_ALLOW_UNKNOWN_AUTHORITY",
|
|
39
36
|
fetchBlockPrivateHosts: "DEEPSEEK_FETCH_BLOCK_PRIVATE_HOSTS",
|
|
40
37
|
searchEnabled: ENABLE_SEARCH_ENV,
|
|
41
38
|
fetchEnabled: ENABLE_FETCH_ENV,
|
|
@@ -58,7 +55,7 @@ export function pluginOptionsFromEnv(env: Env): PluginOptions {
|
|
|
58
55
|
putNumber(options, "maxResults", env)
|
|
59
56
|
putNumber(options, "minRerank", env)
|
|
60
57
|
putNumber(options, "minAuthority", env)
|
|
61
|
-
|
|
58
|
+
putFalseOnly(options, "allowUnknownAuthority", env)
|
|
62
59
|
putDomains(options, "blockedDomains", env)
|
|
63
60
|
putDomains(options, "includeDomains", env)
|
|
64
61
|
putText(options, "language", env)
|
|
@@ -95,10 +92,6 @@ function putText(target: Record<string, unknown>, key: keyof typeof TEXT_ENV, en
|
|
|
95
92
|
if (trimmed) target[key] = trimmed
|
|
96
93
|
}
|
|
97
94
|
|
|
98
|
-
function putBoolean(target: Record<string, unknown>, key: keyof typeof FLAG_ENV, env: Env): void {
|
|
99
|
-
if (isTrueValue(env[FLAG_ENV[key]])) target[key] = true
|
|
100
|
-
}
|
|
101
|
-
|
|
102
95
|
function putFalseOnly(target: Record<string, unknown>, key: keyof typeof FALSE_ONLY_ENV, env: Env): void {
|
|
103
96
|
if (isFalseValue(env[FALSE_ONLY_ENV[key]])) target[key] = false
|
|
104
97
|
}
|
|
@@ -113,11 +106,6 @@ function putDomains(target: Record<string, unknown>, key: keyof typeof DOMAINS_E
|
|
|
113
106
|
if (domains.length > 0) target[key] = domains
|
|
114
107
|
}
|
|
115
108
|
|
|
116
|
-
function isTrueValue(value: string | undefined): boolean {
|
|
117
|
-
const trimmed = value?.trim().toLowerCase()
|
|
118
|
-
return trimmed === "true" || trimmed === "1" || trimmed === "yes" || trimmed === "on"
|
|
119
|
-
}
|
|
120
|
-
|
|
121
109
|
function isFalseValue(value: string | undefined): boolean {
|
|
122
110
|
const trimmed = value?.trim().toLowerCase()
|
|
123
111
|
return trimmed === "false" || trimmed === "0" || trimmed === "no" || trimmed === "off"
|