deepseek-web-retrieval 0.2.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 +204 -1
- package/README.md +55 -28
- package/dist/cli.js +4224 -184
- package/docs/adr/0001-refuse-drift-between-plan-and-apply.md +29 -0
- package/docs/agents/codex.md +193 -0
- package/docs/agents/domain.md +51 -0
- package/docs/agents/issue-tracker.md +45 -0
- package/docs/{opencode-v2.md → agents/opencode-v2.md} +34 -11
- package/docs/{pi.md → agents/pi.md} +39 -11
- package/docs/agents/triage-labels.md +15 -0
- package/docs/design/installer-design.md +184 -0
- package/docs/hosts.jsonc +59 -33
- package/docs/integration.md +45 -52
- package/docs/research/control-matrix.md +257 -0
- package/docs/{mcp-compatibility.md → research/mcp-compatibility.md} +39 -108
- package/docs/research/search-api-defaults.md +309 -0
- package/package.json +5 -3
- package/src/core/auth.ts +1 -1
- package/src/core/client.ts +42 -249
- package/src/core/constants.ts +14 -3
- package/src/core/descriptions.ts +19 -0
- package/src/core/format.ts +31 -1
- package/src/core/jsonc.ts +16 -0
- package/src/core/options.ts +3 -4
- package/src/core/search.ts +5 -7
- package/src/core/transport.ts +253 -0
- package/src/core/types.ts +13 -11
- package/src/installer/apply.ts +176 -0
- package/src/installer/cli.ts +215 -0
- package/src/installer/detect.ts +85 -0
- package/src/installer/formats/index.ts +58 -0
- package/src/installer/formats/json.ts +151 -0
- package/src/installer/formats/rules.ts +62 -0
- package/src/installer/formats/toml.ts +163 -0
- package/src/installer/formats/value.ts +57 -0
- package/src/installer/hosts/codex.ts +128 -0
- package/src/installer/hosts/index.ts +134 -0
- package/src/installer/hosts/opencode.ts +118 -0
- package/src/installer/hosts/pi.ts +115 -0
- package/src/installer/hosts/shared.ts +31 -0
- package/src/installer/paths.ts +18 -0
- package/src/installer/render.ts +62 -0
- package/src/installer/revert.ts +61 -0
- package/src/installer/rulesContent.ts +32 -0
- package/src/installer/state.ts +63 -0
- package/src/installer/types.ts +126 -0
- package/src/installer/uninstall.ts +33 -0
- package/src/mcp/auth.ts +2 -1
- package/src/mcp/cli.ts +21 -5
- package/src/mcp/config.ts +63 -32
- package/src/mcp/server.ts +81 -65
- package/src/opencode/auth.ts +3 -2
- package/src/opencode/plugin.ts +93 -56
- package/src/mcp/format.ts +0 -31
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Refuse drift between plan and apply
|
|
2
|
+
|
|
3
|
+
The installer's plan previews the previous value each `set` op replaces, and the
|
|
4
|
+
install record must snapshot exactly that value for uninstall to restore. We
|
|
5
|
+
decided that apply re-verifies the current value at every `set` path still
|
|
6
|
+
equals the plan-time `previous`, refuses with guidance when it does not
|
|
7
|
+
("config changed since the plan was rendered — re-run"), and records the
|
|
8
|
+
plan-time snapshot — so the preview, the secret guard, and the record all
|
|
9
|
+
describe one snapshot taken once, at plan time.
|
|
10
|
+
|
|
11
|
+
## Considered Options
|
|
12
|
+
|
|
13
|
+
- **Inherit the plan-time snapshot silently.** Single source, but apply would
|
|
14
|
+
overwrite an edit made between plan review and `--apply` without the user's
|
|
15
|
+
knowledge — violating the installer's first principle.
|
|
16
|
+
- **Keep re-deriving `previous` at write time** (previous status quo). The
|
|
17
|
+
preview and the record can disagree, and the secret guard, which checks the
|
|
18
|
+
plan-time value, no longer covers what is actually recorded.
|
|
19
|
+
|
|
20
|
+
## Consequences
|
|
21
|
+
|
|
22
|
+
A legitimate user edit between plan and apply costs one re-run of `init`. In
|
|
23
|
+
exchange, "never overwrite user configuration without the user's knowledge"
|
|
24
|
+
holds unconditionally, including the window between plan review and apply.
|
|
25
|
+
|
|
26
|
+
The record's snapshots are re-derived at apply time rather than copied from the
|
|
27
|
+
plan; because the drift check runs immediately before, the two are provably
|
|
28
|
+
equal, so the record does describe the plan-time snapshot without a separate
|
|
29
|
+
copy step.
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# Codex
|
|
2
|
+
|
|
3
|
+
Codex adapter for [DeepSeek Web Retrieval](../../README.md).
|
|
4
|
+
|
|
5
|
+
Integration mechanism: MCP server over stdio, registered in Codex's `~/.codex/config.toml`.
|
|
6
|
+
Codex negotiates MCP revision `2025-06-18` (with `mcp_2026_07_28` behind a feature flag); the
|
|
7
|
+
server also accepts clients from `2024-11-05` through `2026-07-28`, so the same build works
|
|
8
|
+
for other MCP hosts (see [the compatibility research](../research/mcp-compatibility.md)).
|
|
9
|
+
|
|
10
|
+
When registered, it adds:
|
|
11
|
+
|
|
12
|
+
- A `deepseek_web_search` tool backed by DeepSeek Search
|
|
13
|
+
- A `deepseek_fetch` tool backed by DeepSeek Fetch
|
|
14
|
+
|
|
15
|
+
The tools appear in Codex as `mcp__deepseek__deepseek_web_search` and
|
|
16
|
+
`mcp__deepseek__deepseek_fetch`. Codex's built-in `web_search` tool is not replaced; see
|
|
17
|
+
[Control tiers](#control-tiers) for routing it away.
|
|
18
|
+
|
|
19
|
+
For shared search/fetch limits, retries, and privacy behavior, see
|
|
20
|
+
[General behavior](../../README.md#general-behavior).
|
|
21
|
+
|
|
22
|
+
## Requirements
|
|
23
|
+
|
|
24
|
+
- Codex 0.163.0 or newer
|
|
25
|
+
- Node.js 20 or newer (`npx` runs the server)
|
|
26
|
+
- A DeepSeek account with access to `/v1/tools/search` and `/v1/tools/fetch`
|
|
27
|
+
- A funded DeepSeek account; Search and Fetch are billed per successful request
|
|
28
|
+
- `DEEPSEEK_API_KEY` set in the shell that launches Codex
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
The quickest option is the installer CLI:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npx deepseek-web-retrieval init --host codex --scope global \
|
|
36
|
+
--search <tier> --fetch <tier>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
It prints the full plan — every file, old value → new value, and notes about existing
|
|
40
|
+
MCP servers — and writes nothing until you pass `--apply`. `uninstall` restores exactly
|
|
41
|
+
what the plan applied (snapshots, merged entries, created files). Codex's config lives in
|
|
42
|
+
`~/.codex/config.toml` at the user level only, so the server registration and kill switch
|
|
43
|
+
are written there even for `--scope project`; the rules file follows the scope.
|
|
44
|
+
|
|
45
|
+
### Manual install
|
|
46
|
+
|
|
47
|
+
Add the server to `~/.codex/config.toml`:
|
|
48
|
+
|
|
49
|
+
```toml
|
|
50
|
+
[mcp_servers.deepseek]
|
|
51
|
+
command = "npx"
|
|
52
|
+
args = ["-y", "deepseek-web-retrieval"]
|
|
53
|
+
env_vars = ["DEEPSEEK_API_KEY"]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
> [!NOTE]
|
|
57
|
+
> `env_vars` is load-bearing. Codex stdio children do not inherit the parent
|
|
58
|
+
> environment — only `HOME`, `PATH`, and a few system variables — so the key must be
|
|
59
|
+
> forwarded explicitly and set in the shell that launches Codex. Literal values can go
|
|
60
|
+
> in an `env` table instead if you prefer them in the file.
|
|
61
|
+
|
|
62
|
+
To disable one capability, set it in the `env` table:
|
|
63
|
+
|
|
64
|
+
```toml
|
|
65
|
+
[mcp_servers.deepseek.env]
|
|
66
|
+
DEEPSEEK_ENABLE_SEARCH = "false" # or DEEPSEEK_ENABLE_FETCH; at least one must stay on
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Local checkout
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
git clone https://github.com/gwokhou/deepseek-web-retrieval.git
|
|
73
|
+
cd deepseek-web-retrieval && bun install && bun run build
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[mcp_servers.deepseek]
|
|
78
|
+
command = "node"
|
|
79
|
+
args = ["/absolute/path/to/deepseek-web-retrieval/dist/cli.js"]
|
|
80
|
+
env_vars = ["DEEPSEEK_API_KEY"]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Control tiers
|
|
84
|
+
|
|
85
|
+
Codex ships a built-in `web_search` tool (default `cached` mode, an OpenAI index) and no
|
|
86
|
+
built-in fetch tool, so the tiers differ per capability:
|
|
87
|
+
|
|
88
|
+
| Capability | Optional | Preferred | Forced |
|
|
89
|
+
| --- | --- | --- | --- |
|
|
90
|
+
| Search | Tools registered; the built-in `web_search` stays available | Plus an AGENTS.md rules block steering the model to `mcp__deepseek__deepseek_web_search` | Exclusion: `web_search = "disabled"` at the top level of config.toml |
|
|
91
|
+
| Fetch | Tools registered | Plus the rules block | De-facto: no built-in fetch tool exists |
|
|
92
|
+
|
|
93
|
+
The installer maps each tier to these artifacts. `AGENTS.md` rules land in
|
|
94
|
+
`~/.codex/AGENTS.md` (user) or `./AGENTS.md` (project); Codex reads both plus every
|
|
95
|
+
`AGENTS.md` from the project root to the cwd.
|
|
96
|
+
|
|
97
|
+
> [!WARNING]
|
|
98
|
+
> The `[tools] web_search = <bool>` form parses but is a **silent no-op** at 0.163.0 —
|
|
99
|
+
> only the top-level `web_search` key controls the tool. The installer refuses to plan
|
|
100
|
+
> when it finds the trap in your config.
|
|
101
|
+
|
|
102
|
+
## Authentication
|
|
103
|
+
|
|
104
|
+
`DEEPSEEK_API_KEY` is the only source; MCP has no host credential store. It is forwarded
|
|
105
|
+
to the server via `env_vars` and read per request, sent only to `api.deepseek.com` as a
|
|
106
|
+
Bearer token. Without it the server exits at startup with a message on stderr.
|
|
107
|
+
|
|
108
|
+
## Usage
|
|
109
|
+
|
|
110
|
+
Ask naturally:
|
|
111
|
+
|
|
112
|
+
```text
|
|
113
|
+
Search the web for the latest Codex MCP config changes and cite the sources.
|
|
114
|
+
Fetch https://developers.openai.com/codex/mcp and summarize the config keys.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The model calls `mcp__deepseek__deepseek_web_search` or `mcp__deepseek__deepseek_fetch`.
|
|
118
|
+
|
|
119
|
+
## Configuration
|
|
120
|
+
|
|
121
|
+
Set these in the server's `env` table. Values map onto the shared option pipeline, so
|
|
122
|
+
defaults and clamping match the other adapters. `DEEPSEEK_API_KEY` goes in `env_vars`.
|
|
123
|
+
|
|
124
|
+
### Search
|
|
125
|
+
|
|
126
|
+
| Env variable | Default | Description |
|
|
127
|
+
| --- | --- | --- |
|
|
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
|
+
| `DEEPSEEK_SEARCH_COUNT` | `10` | Results requested from DeepSeek, 1–50. Billing is per request, not per result. |
|
|
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
|
+
| `DEEPSEEK_SEARCH_BLOCKED_DOMAINS` | unset | Comma-separated; adds `-site:` operators to the query. |
|
|
135
|
+
| `DEEPSEEK_SEARCH_INCLUDE_DOMAINS` | unset | Comma-separated; restricts results with `site:` operators. |
|
|
136
|
+
| `DEEPSEEK_SEARCH_LANGUAGE` | unset | Adds a `lang:` operator, for example `zh,en`. |
|
|
137
|
+
| `DEEPSEEK_SEARCH_MAX_SUMMARY_CHARS` | `1200` | Per-result summary cap, 0–1,000,000. |
|
|
138
|
+
| `DEEPSEEK_SEARCH_TIMEOUT_MS` | `30000` | Search timeout, 1,000–120,000 ms. |
|
|
139
|
+
|
|
140
|
+
### Fetch
|
|
141
|
+
|
|
142
|
+
| Env variable | Default | Description |
|
|
143
|
+
| --- | --- | --- |
|
|
144
|
+
| `DEEPSEEK_ENABLE_FETCH` | `true` | Register the fetch tool. Same false-only semantics as `DEEPSEEK_ENABLE_SEARCH`. |
|
|
145
|
+
| `DEEPSEEK_FETCH_MAX_CHARS` | `16000` | Maximum characters returned, including the title, 0–1,000,000. |
|
|
146
|
+
| `DEEPSEEK_FETCH_TIMEOUT_MS` | `30000` | Fetch timeout, 1,000–120,000 ms. |
|
|
147
|
+
| `DEEPSEEK_FETCH_ALLOWED_DOMAINS` | unset | If set, only these hosts and subdomains may be fetched. |
|
|
148
|
+
| `DEEPSEEK_FETCH_BLOCKED_DOMAINS` | unset | Always block these hosts and subdomains. Blocked wins over allowed. |
|
|
149
|
+
| `DEEPSEEK_FETCH_BLOCK_PRIVATE_HOSTS` | `true` | Reject localhost, private IPs, `.local`, `.internal`, and similar hosts. |
|
|
150
|
+
|
|
151
|
+
### Credentials and retries
|
|
152
|
+
|
|
153
|
+
| Env variable | Default | Description |
|
|
154
|
+
| --- | --- | --- |
|
|
155
|
+
| `DEEPSEEK_API_KEY` | required | DeepSeek API key, forwarded via `env_vars`. The server refuses to start without it. |
|
|
156
|
+
| `DEEPSEEK_MAX_RETRIES` | `0` | Retries for 408, 425, 429, and 5xx responses, 0–5. |
|
|
157
|
+
| `DEEPSEEK_RETRY_BASE_DELAY_MS` | `250` | Base delay for exponential backoff. `Retry-After` is honored up to 10 seconds. |
|
|
158
|
+
|
|
159
|
+
## Troubleshooting
|
|
160
|
+
|
|
161
|
+
| Error or symptom | What to do |
|
|
162
|
+
| --- | --- |
|
|
163
|
+
| Server fails to start or `HTTP 401` from the tools | `DEEPSEEK_API_KEY` must be set in the shell that launches Codex and forwarded via `env_vars`; stdio children do not inherit the environment. |
|
|
164
|
+
| Both tools missing after startup | At least one of `DEEPSEEK_ENABLE_SEARCH`/`DEEPSEEK_ENABLE_FETCH` must stay enabled; the server exits when both are false. |
|
|
165
|
+
| Search still uses the built-in tool under the forced tier | The kill switch is the top-level `web_search = "disabled"` key; the `[tools] web_search` form is a no-op at 0.163.0. |
|
|
166
|
+
| Tool results look like raw JSON | When a result has `structuredContent`, Codex replaces the content blocks with the serialized JSON — expected behavior. |
|
|
167
|
+
| Tools time out around 60 s | Raise `tool_timeout_sec` for the server entry if you raise `DEEPSEEK_*_TIMEOUT_MS` beyond it. |
|
|
168
|
+
| Routing not exclusive | Other `[mcp_servers.*]` entries stay registered and are noted in the plan. Under a forced tier, an entry that looks web-capable makes `init` refuse — Codex has no per-server kill switch, so remove the server or restrict its tools via `disabled_tools` by hand. |
|
|
169
|
+
| `HTTP 402`, `HTTP 429` | Top up the DeepSeek account; wait, reduce concurrency, or set `DEEPSEEK_MAX_RETRIES`. |
|
|
170
|
+
| Fetch fails on localhost or an internal URL | Use a local fetch tool; DeepSeek cannot reach private networks. |
|
|
171
|
+
|
|
172
|
+
## Compatibility
|
|
173
|
+
|
|
174
|
+
| Component | Version |
|
|
175
|
+
| --- | --- |
|
|
176
|
+
| Codex | locked in [`docs/hosts.jsonc`](../hosts.jsonc) |
|
|
177
|
+
| MCP revision | `2025-06-18` negotiated (`mcp_2026_07_28` behind a flag); server accepts `2024-11-05`–`2026-07-28` |
|
|
178
|
+
| MCP SDK | `@modelcontextprotocol/server` 2.3.1 |
|
|
179
|
+
| Runtime | Node.js 20+ (stdio) |
|
|
180
|
+
| DeepSeek API | `/v1/tools/search`, `/v1/tools/fetch` |
|
|
181
|
+
|
|
182
|
+
Tested with Codex 0.163.0 on Linux over stdio.
|
|
183
|
+
|
|
184
|
+
## Uninstall
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
npx deepseek-web-retrieval uninstall --host codex --scope global
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
This restores the previous `web_search` value, removes the `mcp_servers.deepseek` table
|
|
191
|
+
and the rules block, and deletes files the installer created. Manually, remove the
|
|
192
|
+
`[mcp_servers.deepseek]` table, any `deepseek-web-retrieval` rules block in your
|
|
193
|
+
`AGENTS.md`, and the top-level `web_search` key if it was only set for the forced tier.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Domain Docs
|
|
2
|
+
|
|
3
|
+
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
|
|
4
|
+
|
|
5
|
+
## Before exploring, read these
|
|
6
|
+
|
|
7
|
+
- **`CONTEXT.md`** at the repo root, or
|
|
8
|
+
- **`CONTEXT-MAP.md`** at the repo root if it exists: it points at one `CONTEXT.md` per context. Read each one relevant to the topic.
|
|
9
|
+
- **`docs/adr/`**: read ADRs that touch the area you're about to work in. In multi-context repos, also check `src/<context>/docs/adr/` for context-scoped decisions.
|
|
10
|
+
|
|
11
|
+
If any of these files don't exist, **proceed silently**. Don't flag their absence; don't suggest creating them upfront. The `/domain-modeling` skill (reached via `/grill-with-docs` and `/improve-codebase-architecture`) creates them lazily when terms or decisions actually get resolved.
|
|
12
|
+
|
|
13
|
+
## File structure
|
|
14
|
+
|
|
15
|
+
Single-context repo (most repos):
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/
|
|
19
|
+
├── CONTEXT.md
|
|
20
|
+
├── docs/adr/
|
|
21
|
+
│ ├── 0001-event-sourced-orders.md
|
|
22
|
+
│ └── 0002-postgres-for-write-model.md
|
|
23
|
+
└── src/
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Multi-context repo (presence of `CONTEXT-MAP.md` at the root):
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/
|
|
30
|
+
├── CONTEXT-MAP.md
|
|
31
|
+
├── docs/adr/ ← system-wide decisions
|
|
32
|
+
└── src/
|
|
33
|
+
├── ordering/
|
|
34
|
+
│ ├── CONTEXT.md
|
|
35
|
+
│ └── docs/adr/ ← context-specific decisions
|
|
36
|
+
└── billing/
|
|
37
|
+
├── CONTEXT.md
|
|
38
|
+
└── docs/adr/
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Use the glossary's vocabulary
|
|
42
|
+
|
|
43
|
+
When your output names a domain concept (in an issue title, a refactor proposal, a hypothesis, a test name), use the term as defined in `CONTEXT.md`. Don't drift to synonyms the glossary explicitly avoids.
|
|
44
|
+
|
|
45
|
+
If the concept you need isn't in the glossary yet, that's a signal: either you're inventing language the project doesn't use (reconsider) or there's a real gap (note it for `/domain-modeling`).
|
|
46
|
+
|
|
47
|
+
## Flag ADR conflicts
|
|
48
|
+
|
|
49
|
+
If your output contradicts an existing ADR, surface it explicitly rather than silently overriding:
|
|
50
|
+
|
|
51
|
+
> _Contradicts ADR-0007 (event-sourced orders), but worth reopening because…_
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Issue tracker: GitHub
|
|
2
|
+
|
|
3
|
+
Issues and specs for this repo live as GitHub issues. Use the `gh` CLI for all operations.
|
|
4
|
+
|
|
5
|
+
## Conventions
|
|
6
|
+
|
|
7
|
+
- **Create an issue**: `gh issue create --title "..." --body "..."`. Use a heredoc for multi-line bodies.
|
|
8
|
+
- **Read an issue**: `gh issue view <number> --comments`, filtering comments by `jq` and also fetching labels.
|
|
9
|
+
- **List issues**: `gh issue list --state open --json number,title,body,labels,comments --jq '[.[] | {number, title, body, labels: [.labels[].name], comments: [.comments[].body]}]'` with appropriate `--label` and `--state` filters.
|
|
10
|
+
- **Comment on an issue**: `gh issue comment <number> --body "..."`
|
|
11
|
+
- **Apply / remove labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
|
|
12
|
+
- **Close**: `gh issue close <number> --comment "..."`
|
|
13
|
+
|
|
14
|
+
Infer the repo from `git remote -v`; `gh` does this automatically when run inside a clone.
|
|
15
|
+
|
|
16
|
+
## Pull requests as a triage surface
|
|
17
|
+
|
|
18
|
+
**PRs as a request surface: no.** _(Set to `yes` if this repo treats external PRs as feature requests; `/triage` reads this flag.)_
|
|
19
|
+
|
|
20
|
+
When set to `yes`, PRs run through the same labels and states as issues, using the `gh pr` equivalents:
|
|
21
|
+
|
|
22
|
+
- **Read a PR**: `gh pr view <number> --comments` and `gh pr diff <number>` for the diff.
|
|
23
|
+
- **List external PRs for triage**: `gh pr list --state open --json number,title,body,labels,author,authorAssociation,comments` then keep only `authorAssociation` of `CONTRIBUTOR`, `FIRST_TIME_CONTRIBUTOR`, or `NONE` (drop `OWNER`/`MEMBER`/`COLLABORATOR`).
|
|
24
|
+
- **Comment / label / close**: `gh pr comment`, `gh pr edit --add-label`/`--remove-label`, `gh pr close`.
|
|
25
|
+
|
|
26
|
+
GitHub shares one number space across issues and PRs, so a bare `#42` may be either: resolve with `gh pr view 42` and fall back to `gh issue view 42`.
|
|
27
|
+
|
|
28
|
+
## When a skill says "publish to the issue tracker"
|
|
29
|
+
|
|
30
|
+
Create a GitHub issue.
|
|
31
|
+
|
|
32
|
+
## When a skill says "fetch the relevant ticket"
|
|
33
|
+
|
|
34
|
+
Run `gh issue view <number> --comments`.
|
|
35
|
+
|
|
36
|
+
## Wayfinding operations
|
|
37
|
+
|
|
38
|
+
Used by `/wayfinder`. The **map** is a single issue with **child** issues as tickets.
|
|
39
|
+
|
|
40
|
+
- **Map**: a single issue labelled `wayfinder:map`, holding the Notes / Decisions-so-far / Fog body. `gh issue create --label wayfinder:map`.
|
|
41
|
+
- **Child ticket**: an issue linked to the map as a GitHub sub-issue (`gh api` on the sub-issues endpoint). Where sub-issues aren't enabled, add the child to a task list in the map body and put `Part of #<map>` at the top of the child body. Labels: `wayfinder:<type>` (`research`/`prototype`/`grilling`/`task`). Once claimed, the ticket is assigned to the driving dev.
|
|
42
|
+
- **Blocking**: GitHub's **native issue dependencies**, the canonical, UI-visible representation. Add an edge with `gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id>`, where `<blocker-db-id>` is the blocker's numeric **database id** (`gh api repos/<owner>/<repo>/issues/<n> --jq .id`, _not_ the `#number` or `node_id`). GitHub reports `issue_dependencies_summary.blocked_by` (open blockers only, the live gate). Where dependencies aren't available, fall back to a `Blocked by: #<n>, #<n>` line at the top of the child body. A ticket is unblocked when every blocker is closed.
|
|
43
|
+
- **Frontier query**: list the map's open children (`gh issue list --state open`, scoped to the map's sub-issues / task list), drop any with an open blocker (`issue_dependencies_summary.blocked_by > 0`, or an open issue in the `Blocked by` line) or an assignee; first in map order wins.
|
|
44
|
+
- **Claim**: `gh issue edit <n> --add-assignee @me`, the session's first write.
|
|
45
|
+
- **Resolve**: `gh issue comment <n> --body "<answer>"`, then `gh issue close <n>`, then append a context pointer (gist + link) to the map's Decisions-so-far.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# OpenCode v2
|
|
2
2
|
|
|
3
|
-
OpenCode v2 adapter for [DeepSeek Web Retrieval](
|
|
3
|
+
OpenCode v2 adapter for [DeepSeek Web Retrieval](../../README.md).
|
|
4
4
|
|
|
5
5
|
Integration mechanism: OpenCode's native plugin API (`@opencode/plugin` 2.0.32+), not MCP.
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@ The built-in `webfetch` is not replaced by default. Set `fetchOverrideWebfetch`
|
|
|
14
14
|
if you want all Markdown fetches to go through DeepSeek.
|
|
15
15
|
|
|
16
16
|
For shared search/fetch limits, retries, and privacy behavior, see
|
|
17
|
-
[General behavior](
|
|
17
|
+
[General behavior](../../README.md#general-behavior).
|
|
18
18
|
|
|
19
19
|
## Requirements
|
|
20
20
|
|
|
@@ -28,7 +28,22 @@ No build step is required. OpenCode loads the TypeScript entry point directly.
|
|
|
28
28
|
|
|
29
29
|
## Install
|
|
30
30
|
|
|
31
|
-
The quickest option is the
|
|
31
|
+
The quickest option is the installer CLI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx deepseek-web-retrieval init --host opencode --scope <project|global> \
|
|
35
|
+
--search <optional|forced|off> --fetch <optional|preferred|forced|off>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
It prints the full plan — every file, old value → new value — and writes nothing until
|
|
39
|
+
you pass `--apply`. It snapshots the current `websearch.provider` before the forced tier
|
|
40
|
+
replaces it, merges `permissions` without touching yours, preserves comments in
|
|
41
|
+
`opencode.jsonc`, and `uninstall` restores everything. Search has no `preferred` tier on
|
|
42
|
+
OpenCode (the provider is host-level config, never a model choice); the CLI rejects it.
|
|
43
|
+
|
|
44
|
+
### OpenCode CLI install
|
|
45
|
+
|
|
46
|
+
The next option is the OpenCode CLI:
|
|
32
47
|
|
|
33
48
|
```bash
|
|
34
49
|
opencode plugin add github:gwokhou/deepseek-web-retrieval
|
|
@@ -82,11 +97,10 @@ A complete global config:
|
|
|
82
97
|
|
|
83
98
|
**Published npm package**
|
|
84
99
|
|
|
85
|
-
|
|
86
|
-
pinned) as the `package` value:
|
|
100
|
+
Use the bare package name (optionally pinned) as the `package` value:
|
|
87
101
|
|
|
88
102
|
```jsonc
|
|
89
|
-
"plugins": [{ "package": "deepseek-web-retrieval@0.
|
|
103
|
+
"plugins": [{ "package": "deepseek-web-retrieval@0.4.0" }]
|
|
90
104
|
```
|
|
91
105
|
|
|
92
106
|
**Global checkout**
|
|
@@ -157,11 +171,12 @@ Set these in the plugin's `options` object.
|
|
|
157
171
|
|
|
158
172
|
| Option | Default | Description |
|
|
159
173
|
| --- | --- | --- |
|
|
174
|
+
| `searchEnabled` | `true` | Register the DeepSeek search provider at all. Only an explicit `false` disables it. |
|
|
160
175
|
| `count` | `10` | Results requested from DeepSeek, 1–50. Billing is per request, not per result. |
|
|
161
|
-
| `maxResults` | `
|
|
162
|
-
| `minRerank` | `
|
|
163
|
-
| `minAuthority` | `
|
|
164
|
-
| `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. |
|
|
165
180
|
| `blockedDomains` | `[]` | Add `-site:` operators to the search query. |
|
|
166
181
|
| `includeDomains` | `[]` | Restrict results with `site:` operators. |
|
|
167
182
|
| `language` | unset | Add a `lang:` operator, for example `zh,en`. |
|
|
@@ -173,6 +188,7 @@ Set these in the plugin's `options` object.
|
|
|
173
188
|
|
|
174
189
|
| Option | Default | Description |
|
|
175
190
|
| --- | --- | --- |
|
|
191
|
+
| `fetchEnabled` | `true` | Register any DeepSeek fetch tooling (the separate tool and the webfetch override). |
|
|
176
192
|
| `fetchMaxChars` | `16000` | Maximum characters returned, including the title, 0–1,000,000. |
|
|
177
193
|
| `fetchTimeoutMs` | `30000` | Fetch timeout, 1,000–120,000 ms. |
|
|
178
194
|
| `fetchOverrideWebfetch` | `false` | Replace the built-in `webfetch`. |
|
|
@@ -208,7 +224,7 @@ Set these in the plugin's `options` object.
|
|
|
208
224
|
|
|
209
225
|
| Component | Version |
|
|
210
226
|
| --- | --- |
|
|
211
|
-
| OpenCode / plugin API | locked in [`docs/hosts.jsonc`](hosts.jsonc) |
|
|
227
|
+
| OpenCode / plugin API | locked in [`docs/hosts.jsonc`](../hosts.jsonc) |
|
|
212
228
|
| Runtime | Bun (provided by OpenCode) |
|
|
213
229
|
| DeepSeek API | `/v1/tools/search`, `/v1/tools/fetch` |
|
|
214
230
|
|
|
@@ -217,6 +233,13 @@ using both an OpenCode-stored DeepSeek credential and `DEEPSEEK_API_KEY`.
|
|
|
217
233
|
|
|
218
234
|
## Uninstall
|
|
219
235
|
|
|
236
|
+
With the installer CLI (restores the snapshotted `websearch.provider`, removes only the
|
|
237
|
+
appended permissions, and deletes files it created):
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npx deepseek-web-retrieval uninstall --host opencode --scope <project|global>
|
|
241
|
+
```
|
|
242
|
+
|
|
220
243
|
For a CLI install, remove the config entry with:
|
|
221
244
|
|
|
222
245
|
```bash
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Pi
|
|
2
2
|
|
|
3
|
-
Pi adapter for [DeepSeek Web Retrieval](
|
|
3
|
+
Pi adapter for [DeepSeek Web Retrieval](../../README.md).
|
|
4
4
|
|
|
5
5
|
Integration mechanism: MCP server over stdio, launched from Pi's `mcp.json`. Pi 1.3.0
|
|
6
6
|
negotiates MCP revision `2025-11-25`; the server also accepts clients from `2024-11-05`
|
|
7
7
|
through `2026-07-28`, so the same build works for other MCP hosts (see
|
|
8
|
-
[the compatibility research](mcp-compatibility.md)).
|
|
8
|
+
[the compatibility research](../research/mcp-compatibility.md)).
|
|
9
9
|
|
|
10
10
|
When registered, it adds:
|
|
11
11
|
|
|
@@ -16,7 +16,7 @@ The tools appear in Pi as `mcp__deepseek__deepseek_web_search` and
|
|
|
16
16
|
`mcp__deepseek__deepseek_fetch`. Pi's built-in tools are not replaced.
|
|
17
17
|
|
|
18
18
|
For shared search/fetch limits, retries, and privacy behavior, see
|
|
19
|
-
[General behavior](
|
|
19
|
+
[General behavior](../../README.md#general-behavior).
|
|
20
20
|
|
|
21
21
|
## Requirements
|
|
22
22
|
|
|
@@ -28,6 +28,25 @@ For shared search/fetch limits, retries, and privacy behavior, see
|
|
|
28
28
|
|
|
29
29
|
## Install
|
|
30
30
|
|
|
31
|
+
The quickest option is the installer CLI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npx deepseek-web-retrieval init --host pi --scope <project|global> \
|
|
35
|
+
--search <optional|preferred|forced|off> --fetch <optional|preferred|forced|off>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
It prints the full plan — every file, old value → new value, and notes about existing
|
|
39
|
+
MCP servers and the `exposure` requirement — and writes nothing until you pass `--apply`.
|
|
40
|
+
JSON edits preserve comments. `uninstall` restores exactly what the plan applied. Under a
|
|
41
|
+
forced tier, other registered MCP servers that look web-capable are disabled
|
|
42
|
+
(`enabled: false`, prior value snapshotted) so DeepSeek routing is exclusive, and
|
|
43
|
+
`uninstall` restores them. The
|
|
44
|
+
tiers follow the [control matrix](../research/control-matrix.md): Pi ships no built-in web
|
|
45
|
+
tool, so forced is de-facto for both capabilities and `off` writes
|
|
46
|
+
`DEEPSEEK_ENABLE_SEARCH`/`DEEPSEEK_ENABLE_FETCH` into the server's env block.
|
|
47
|
+
|
|
48
|
+
### Manual install
|
|
49
|
+
|
|
31
50
|
Add the server to `~/.pi/agent/mcp.json` (user) or `.pi/mcp.json` (project):
|
|
32
51
|
|
|
33
52
|
```jsonc
|
|
@@ -61,7 +80,8 @@ or a new session.
|
|
|
61
80
|
|
|
62
81
|
### Local checkout
|
|
63
82
|
|
|
64
|
-
|
|
83
|
+
To run the server from a checkout instead of the published package (for
|
|
84
|
+
development):
|
|
65
85
|
|
|
66
86
|
```bash
|
|
67
87
|
git clone https://github.com/gwokhou/deepseek-web-retrieval.git
|
|
@@ -110,11 +130,12 @@ defaults and clamping match the OpenCode adapter.
|
|
|
110
130
|
|
|
111
131
|
| Env variable | Default | Description |
|
|
112
132
|
| --- | --- | --- |
|
|
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. |
|
|
113
134
|
| `DEEPSEEK_SEARCH_COUNT` | `10` | Results requested from DeepSeek, 1–50. Billing is per request, not per result. |
|
|
114
|
-
| `DEEPSEEK_SEARCH_MAX_RESULTS` | `
|
|
115
|
-
| `DEEPSEEK_SEARCH_MIN_RERANK` | `
|
|
116
|
-
| `DEEPSEEK_SEARCH_MIN_AUTHORITY` | `
|
|
117
|
-
| `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. |
|
|
118
139
|
| `DEEPSEEK_SEARCH_BLOCKED_DOMAINS` | unset | Comma-separated; adds `-site:` operators to the query. |
|
|
119
140
|
| `DEEPSEEK_SEARCH_INCLUDE_DOMAINS` | unset | Comma-separated; restricts results with `site:` operators. |
|
|
120
141
|
| `DEEPSEEK_SEARCH_LANGUAGE` | unset | Adds a `lang:` operator, for example `zh,en`. |
|
|
@@ -124,7 +145,8 @@ defaults and clamping match the OpenCode adapter.
|
|
|
124
145
|
### Fetch
|
|
125
146
|
|
|
126
147
|
| Env variable | Default | Description |
|
|
127
|
-
| --- | --- |
|
|
148
|
+
| --- | --- |
|
|
149
|
+
| `DEEPSEEK_ENABLE_FETCH` | `true` | Register the fetch tool. Same false-only semantics as `DEEPSEEK_ENABLE_SEARCH`. |
|
|
128
150
|
| `DEEPSEEK_FETCH_MAX_CHARS` | `16000` | Maximum characters returned, including the title, 0–1,000,000. |
|
|
129
151
|
| `DEEPSEEK_FETCH_TIMEOUT_MS` | `30000` | Fetch timeout, 1,000–120,000 ms. |
|
|
130
152
|
| `DEEPSEEK_FETCH_ALLOWED_DOMAINS` | unset | If set, only these hosts and subdomains may be fetched. |
|
|
@@ -160,7 +182,7 @@ Invalid values fall back to the shared default.
|
|
|
160
182
|
|
|
161
183
|
| Component | Version |
|
|
162
184
|
| --- | --- |
|
|
163
|
-
| Pi | locked in [`docs/hosts.jsonc`](hosts.jsonc) |
|
|
185
|
+
| Pi | locked in [`docs/hosts.jsonc`](../hosts.jsonc) |
|
|
164
186
|
| MCP revision | `2025-11-25` negotiated; server accepts `2024-11-05`–`2026-07-28` |
|
|
165
187
|
| MCP SDK | `@modelcontextprotocol/server` 2.3.1 |
|
|
166
188
|
| Runtime | Node.js 20+ (stdio) |
|
|
@@ -172,7 +194,13 @@ test personas (`2024-11-05`, `2025-06-18`, `2025-11-25`, `2026-07-28`).
|
|
|
172
194
|
|
|
173
195
|
## Uninstall
|
|
174
196
|
|
|
175
|
-
|
|
197
|
+
With the installer CLI:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
npx deepseek-web-retrieval uninstall --host pi --scope <project|global>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Or remove the `deepseek` entry from `~/.pi/agent/mcp.json` or `.pi/mcp.json`, or run:
|
|
176
204
|
|
|
177
205
|
```bash
|
|
178
206
|
pi mcp remove deepseek
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Triage Labels
|
|
2
|
+
|
|
3
|
+
The skills speak in terms of five canonical triage roles. This file maps those roles to the actual label strings used in this repo's issue tracker.
|
|
4
|
+
|
|
5
|
+
| Label in mattpocock/skills | Label in our tracker | Meaning |
|
|
6
|
+
| -------------------------- | -------------------- | ---------------------------------------- |
|
|
7
|
+
| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue |
|
|
8
|
+
| `needs-info` | `needs-info` | Waiting on reporter for more information |
|
|
9
|
+
| `ready-for-agent` | `ready-for-agent` | Fully specified, ready for an AFK agent |
|
|
10
|
+
| `ready-for-human` | `ready-for-human` | Requires human implementation |
|
|
11
|
+
| `wontfix` | `wontfix` | Will not be actioned |
|
|
12
|
+
|
|
13
|
+
When a skill mentions a role (e.g. "apply the AFK-ready triage label"), use the corresponding label string from this table.
|
|
14
|
+
|
|
15
|
+
Edit the right-hand column to match whatever vocabulary you actually use.
|