opencode-qoder-bridge 0.1.9 → 0.1.11

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/README.md CHANGED
@@ -1,351 +1,459 @@
1
- # opencode-qoder-bridge
2
-
3
- An [opencode](https://opencode.ai) plugin that bridges **Qoder AI** models into your terminal via the official [`@qoder-ai/qoder-agent-sdk`](https://www.npmjs.com/package/@qoder-ai/qoder-agent-sdk).
4
-
5
- A ground-up rewrite focused on reliability, performance, and first-class usage/cost visibility.
6
-
7
- > [!IMPORTANT]
8
- > This is an independent community project. It is not affiliated with,
9
- > endorsed by, or sponsored by Qoder or OpenCode. Use of the Qoder SDK and
10
- > services is subject to the [Qoder Product Service Terms](https://qoder.com/product-service).
11
-
12
- ## Highlights
13
-
14
- - **Official SDK, no vendoring** — depends on `@qoder-ai/qoder-agent-sdk` directly. No patched SDK copies, no CLI compat-wrapper scripts.
15
- - **Correct streaming** — native AI SDK v3 stream-part translation (`content_block_start/delta/stop`, `message_delta`, assistant fallback), reasoning blocks, and tool-call handoff to opencode.
16
- - **Usage & cost tracking** — every completed turn is recorded to a local ledger (`~/.config/opencode-qoder-bridge/usage.json`) with per-model cost and token totals. Query it via the `qoder_usage` tool or the `opencode-qoder-bridge` statusline binary.
17
- - **Live quota** — `qoder_usage` also pulls live account quota via the SDK's `getUsageInfo()` (cached 60s).
18
- - **Reliable lifecycle** — proper abort propagation, idempotent cleanup, and external-abort vs. internal-error distinction so cancellations don't surface as errors.
19
- - **Image input** — multimodal prompts are passed through the SDK's async-iterable path (base64, data URLs, `file://`, `~/`, and absolute paths).
20
-
21
- ## Quick start
22
-
23
- 1. Use Node.js 22.22.2 or newer, or Node.js 24.15.0 or newer.
24
-
25
- 2. Install OpenCode and this plugin:
26
-
27
- ```bash
28
- npm install -g opencode-ai
29
- npm install opencode-qoder-bridge
30
- ```
31
-
32
- 3. Authenticate with a Qoder PAT (recommended):
33
-
34
- ```bash
35
- export QODER_PERSONAL_ACCESS_TOKEN="pt-..."
36
- ```
37
-
38
- Or use the Qoder CLI login flow:
39
-
40
- ```bash
41
- qoder login
42
- ```
43
-
1
+ # opencode-qoder-bridge
2
+
3
+ An [opencode](https://opencode.ai) plugin that bridges **Qoder AI** models into your terminal via the official [`@qoder-ai/qoder-agent-sdk`](https://www.npmjs.com/package/@qoder-ai/qoder-agent-sdk).
4
+
5
+ A ground-up rewrite focused on reliability, performance, and first-class usage/cost visibility.
6
+
7
+ > [!IMPORTANT]
8
+ > This is an independent community project. It is not affiliated with,
9
+ > endorsed by, or sponsored by Qoder or OpenCode. Use of the Qoder SDK and
10
+ > services is subject to the [Qoder Product Service Terms](https://qoder.com/product-service).
11
+
12
+ ## Highlights
13
+
14
+ - **Official SDK, no vendoring** — depends on `@qoder-ai/qoder-agent-sdk` directly. No patched SDK copies, no CLI compat-wrapper scripts.
15
+ - **Correct streaming** — native AI SDK v3 stream-part translation (`content_block_start/delta/stop`, `message_delta`, assistant fallback), reasoning blocks, and tool-call handoff to opencode.
16
+ - **Usage & cost tracking** — every completed turn is recorded to a local ledger (`~/.config/opencode-qoder-bridge/usage.json`) with per-model cost and token totals. Query it via the `qoder_usage` tool or the `opencode-qoder-bridge` statusline binary.
17
+ - **Live quota** — `qoder_usage` also pulls live account quota via the SDK's `getUsageInfo()` (cached 60s).
18
+ - **Reliable lifecycle** — proper abort propagation, idempotent cleanup, and external-abort vs. internal-error distinction so cancellations don't surface as errors.
19
+ - **Image input** — multimodal prompts are passed through the SDK's async-iterable path (base64, data URLs, `file://`, `~/`, and absolute paths).
20
+
21
+ ## Quick start
22
+
23
+ 1. Use Node.js 22.22.2 or newer, or Node.js 24.15.0 or newer.
24
+
25
+ 2. Install OpenCode and this plugin:
26
+
27
+ ```bash
28
+ npm install -g opencode-ai
29
+ npm install opencode-qoder-bridge
30
+ ```
31
+
32
+ 3. Authenticate with a Qoder PAT (recommended):
33
+
34
+ ```bash
35
+ export QODER_PERSONAL_ACCESS_TOKEN="pt-..."
36
+ ```
37
+
38
+ Or use the Qoder CLI login flow:
39
+
40
+ ```bash
41
+ qoder login
42
+ ```
43
+
44
44
  PAT authentication uses the SDK's worker runtime when available and does not
45
45
  require a local `qoder login`. CLI authentication remains supported.
46
46
 
47
- ## Install
48
-
49
- For a published npm installation, add this to
50
- `~/.config/opencode/opencode.json`:
51
-
52
- ```json
53
- {
54
- "plugin": ["opencode-qoder-bridge"]
55
- }
56
- ```
57
-
58
- For a local checkout or an unpublished package, point OpenCode at the built
59
- plugin entry directly:
60
-
61
- ```json
62
- {
63
- "plugin": [
64
- "file:///absolute/path/to/opencode-qoder-bridge/dist/index.js"
65
- ]
66
- }
67
- ```
68
-
69
- opencode installs published npm plugins automatically on startup. A bare package
70
- name must exist in the npm registry; installing an unpublished package only in
71
- `~/.config/opencode/node_modules` is not enough for current opencode releases.
72
- Once loaded, the plugin injects the `qoder` provider and all models — no manual
73
- `provider` block required.
74
-
75
- ## Usage
47
+ With npm 12, dependency install scripts may be blocked by the consuming
48
+ project's script-approval policy. To download SDK `1.0.31`'s bundled Worker
49
+ runtime, approve and rebuild it from that project:
76
50
 
77
51
  ```bash
78
- opencode run -m qoder/lite "say hello" # free model
79
- opencode run -m qoder/auto "explain async/await"
80
- opencode -m qoder/performance # interactive
52
+ npm install-scripts approve @qoder-ai/qoder-agent-sdk@1.0.31
53
+ npm rebuild @qoder-ai/qoder-agent-sdk
81
54
  ```
82
55
 
83
- ### Usage & cost
84
-
85
- Run `qoder-usage` in a terminal for the live report, or add the statusline
86
- binary to your OpenCode statusline config:
87
-
88
- ```bash
89
- opencode-qoder-bridge
90
- # qoder: cost $0.0123 · turns 1 · tok 1500 · last performance
91
- ```
92
-
93
- The package also exports a TUI entry at `opencode-qoder-bridge/tui`. It shows
94
- live Qoder credits only while the current session's selected provider is
95
- `qoder`; it stays hidden and does not query quota for other providers. The
96
- sidebar shows OpenCode's session spend with four-decimal precision and derives
97
- fractional session Credits from Qoder's cent-denominated reference cost
98
- (`session.cost * 100`). The value is marked with `~` because Qoder's personal
99
- SDK exposes only a rounded whole-account quota, not its per-request Credits Log.
100
- The authoritative account balance still comes from SDK `userQuota`, refreshing
101
- after each completed Qoder turn and every 30 seconds while active.
102
-
103
- OpenCode 1.18.5 loads server plugins and TUI plugins independently. On its
104
- first load, the bridge safely adds its bundled TUI entry to the global
105
- `tui.json`, preserving existing settings. Restart OpenCode once after initial
106
- installation so the TUI loader can activate it. The resulting entry is
107
- equivalent to:
108
-
109
- ```json
110
- {
111
- "$schema": "https://opencode.ai/tui.json",
112
- "plugin": ["file:///path/to/opencode-qoder-bridge/dist/tui.js"]
113
- }
114
- ```
115
-
116
- The ledger accumulates across sessions. Delete `~/.config/opencode-qoder-bridge/usage.json` to reset it.
117
-
118
- ## Models
119
-
120
- The bridge discovers the available catalog at startup through the SDK's
121
- `getAvailableModels()` API. Availability is account-, region-, rollout-, and
122
- SDK-version-dependent. A permanent allowlist is intentionally not embedded
123
- here because the catalog is account- and scene-dependent.
124
-
125
- The following is the current model snapshot returned by `qodercli --list-models`
126
- on 2026-08-30:
127
-
128
- | Model |
129
- |-------|
130
- | `Qwen3.8-Max` |
131
- | `Qwen3.8-Flash` |
132
- | `Qwen3.7-Max` |
133
- | `Qwen3.7-Plus` |
134
-
135
- This is an account-, region-, plan-, CLI-version-, and rollout-dependent
136
- snapshot. The CLI command reports display names only; the bridge's SDK catalog
137
- is authoritative for model IDs, capabilities, context limits, and pricing.
138
- Run `qodercli --list-models` and restart OpenCode to refresh the local view.
139
-
140
- Run `opencode models qoder` to inspect the models currently registered with
141
- OpenCode. The `qoder_models` tool also exposes capabilities, context limits,
142
- and price multipliers to the agent. Model discovery is cached and refreshed in
143
- the background so network or authentication latency does not block startup.
144
-
145
- ## Configuration
146
-
147
- Bridge opencode MCP servers into the SDK by passing provider options:
148
-
149
- ```json
150
- {
151
- "provider": {
152
- "qoder": {
153
- "options": {
154
- "extraArgs": { "--experimental-mcp-load": null }
155
- }
156
- }
157
- }
158
- }
159
- ```
160
-
161
- Flag names may be written with or without the leading `--`.
162
-
163
- `config.mcp` servers are bridged into the SDK's `mcpServers` automatically.
164
- Chat turns have a 30-minute bridge timeout by default; set `options.timeoutMs`
165
- to a positive value to use a shorter or longer bounded timeout (up to 24 hours).
166
- Values in `options.env` override inherited process variables rather than
167
- replacing the complete child environment.
168
-
169
- ### Persistent sessions and permissions
170
-
171
- Session persistence is opt-in. Give a provider configuration a stable
172
- `sessionKey` and enable `sessionPersistence`:
56
+ If you use a separately installed `qoder` CLI or intentionally set
57
+ `QODER_SKIP_DOWNLOAD=1`, this step is not required; the bridge can use that
58
+ runtime fallback instead.
59
+
60
+ ## Install
61
+
62
+ For a published npm installation, add this to
63
+ `~/.config/opencode/opencode.json`:
64
+
65
+ ```json
66
+ {
67
+ "plugin": ["opencode-qoder-bridge"]
68
+ }
69
+ ```
70
+
71
+ For a local checkout or an unpublished package, point OpenCode at the built
72
+ plugin entry directly:
73
+
74
+ ```json
75
+ {
76
+ "plugin": [
77
+ "file:///absolute/path/to/opencode-qoder-bridge/dist/index.js"
78
+ ]
79
+ }
80
+ ```
81
+
82
+ opencode installs published npm plugins automatically on startup. A bare package
83
+ name must exist in the npm registry; installing an unpublished package only in
84
+ `~/.config/opencode/node_modules` is not enough for current opencode releases.
85
+ Once loaded, the plugin injects the `qoder` provider and all models — no manual
86
+ `provider` block required.
87
+
88
+ ## Usage
89
+
90
+ ```bash
91
+ opencode run -m qoder/lite "say hello" # free model
92
+ opencode run -m qoder/auto "explain async/await"
93
+ opencode -m qoder/performance # interactive
94
+ ```
95
+
96
+ ### Usage & cost
97
+
98
+ Run `qoder-usage` in a terminal for the live report, or add the statusline
99
+ binary to your OpenCode statusline config:
100
+
101
+ ```bash
102
+ opencode-qoder-bridge
103
+ # qoder: cost $0.0123 · turns 1 · tok 1500 · last performance
104
+ ```
105
+
106
+ The package also exports a TUI entry at `opencode-qoder-bridge/tui`. It shows
107
+ live Qoder credits only while the current session's selected provider is
108
+ `qoder`; it stays hidden and does not query quota for other providers. The
109
+ sidebar shows OpenCode's session spend with four-decimal precision and derives
110
+ fractional session Credits from Qoder's cent-denominated reference cost
111
+ (`session.cost * 100`). The value is marked with `~` because Qoder's personal
112
+ SDK exposes only a rounded whole-account quota, not its per-request Credits Log.
113
+ The authoritative account balance still comes from SDK `userQuota`, refreshing
114
+ after each completed Qoder turn and every 30 seconds while active.
115
+
116
+ OpenCode loads server plugins and TUI plugins independently. On its first
117
+ load, the bridge safely adds its bundled TUI entry to the global
118
+ `~/.config/opencode/tui.json`, preserving existing settings. Restart OpenCode
119
+ once after initial installation so the TUI loader can activate it. The regular
120
+ TUI loads these commands; OpenCode's `--mini` interface does not load external
121
+ TUI plugins in current releases. The resulting entry is equivalent to:
122
+
123
+ ```json
124
+ {
125
+ "$schema": "https://opencode.ai/tui.json",
126
+ "plugin": ["file:///path/to/opencode-qoder-bridge/dist/tui.js"]
127
+ }
128
+ ```
129
+
130
+ The ledger accumulates across sessions. Delete `~/.config/opencode-qoder-bridge/usage.json` to reset it.
131
+
132
+ ## Models
133
+
134
+ The bridge discovers the available catalog at startup through the SDK's
135
+ `getAvailableModels()` API. Availability is account-, region-, rollout-, and
136
+ SDK-version-dependent. A permanent allowlist is intentionally not embedded
137
+ here because the catalog is account- and scene-dependent.
138
+
139
+ There is intentionally no static model table here. Model availability is
140
+ account-, region-, plan-, scene-, SDK-version-, and rollout-dependent, and the
141
+ SDK's live catalog is authoritative for selectable IDs, capabilities, context
142
+ limits, and pricing.
143
+
144
+ Run `opencode models qoder` to inspect the models currently registered with
145
+ OpenCode. The `qoder_models` tool also exposes capabilities, context limits,
146
+ and price multipliers to the agent. On each plugin startup, the bridge performs
147
+ bounded live discovery automatically; if Qoder is unavailable, it uses the
148
+ last catalog for the same credential/deployment context and the built-ins.
149
+
150
+ ## Configuration
151
+
152
+ Bridge opencode MCP servers into the SDK by passing provider options:
153
+
154
+ ```json
155
+ {
156
+ "provider": {
157
+ "qoder": {
158
+ "options": {
159
+ "extraArgs": { "--experimental-mcp-load": null }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ ```
165
+
166
+ Flag names may be written with or without the leading `--`.
167
+
168
+ `config.mcp` servers are bridged into the SDK's `mcpServers` automatically.
169
+ Chat turns have a 30-minute bridge timeout by default; set `options.timeoutMs`
170
+ to a positive value to use a shorter or longer bounded timeout (up to 24 hours).
171
+ Values in `options.env` override inherited process variables rather than
172
+ replacing the complete child environment.
173
+
174
+ ### Persistent sessions and permissions
175
+
176
+ Session persistence is opt-in. Give a provider configuration a stable
177
+ `sessionKey` and enable `sessionPersistence`:
178
+
179
+ ```json
180
+ {
181
+ "provider": {
182
+ "qoder": {
183
+ "options": {
184
+ "sessionPersistence": true,
185
+ "sessionKey": "my-project-main"
186
+ }
187
+ }
188
+ }
189
+ }
190
+ ```
191
+
192
+ Mappings are stored in
193
+ `~/.config/opencode-qoder-bridge/sessions.json` with restrictive file
194
+ permissions and are scoped to the configured working directory. The plugin
195
+ uses OpenCode's project directory when available; set `options.cwd` when
196
+ loading the provider directly. Use the `qoder_session_reset` tool to forget
197
+ the mapping. A new session is created automatically if the mapping does not
198
+ exist; existing sessions are resumed through the Qoder SDK.
199
+
200
+ Qoder-native and bridged MCP tools remain provider-owned. If OpenCode supplies
201
+ a function with a colliding native name, the bridge derives a Qoder deny rule
202
+ to avoid executing the same operation in both runtimes.
203
+
204
+ The bridge uses the SDK's safer permission policy by default. To explicitly
205
+ allow all Qoder tools in a trusted local environment, configure for example:
206
+
207
+ ```json
208
+ {
209
+ "provider": {
210
+ "qoder": {
211
+ "options": {
212
+ "permissionMode": "default",
213
+ "allowedTools": ["Read", "Glob", "Grep"]
214
+ }
215
+ }
216
+ }
217
+ }
218
+ ```
219
+
220
+ Available permission modes are `default`, `acceptEdits`, and
221
+ `bypassPermissions`. Only explicitly configure `bypassPermissions` when the
222
+ host environment is trusted.
223
+
224
+ Image inputs may reference `file://`, `~/`, or absolute local paths. Only pass
225
+ paths from trusted callers: the bridge bounds image size but does not sandbox
226
+ or restrict readable local files to the project directory. A current turn is
227
+ limited to 64 images and 40 MiB of decoded image data; excess attachments are
228
+ reported as omitted text.
229
+
230
+ ### Plan Mode
231
+
232
+ Plan Mode instructs Qoder to analyze and plan changes without modifying files
233
+ or running action tools. It operates independently from tool permissions,
234
+ preserving your configured `permissionMode`:
235
+
236
+ ```json
237
+ {
238
+ "provider": {
239
+ "qoder": {
240
+ "options": {
241
+ "planMode": true
242
+ }
243
+ }
244
+ }
245
+ }
246
+ ```
247
+
248
+ The plugin automatically registers the following local TUI slash commands in
249
+ OpenCode. No manual `opencode.json` edits are required; restart OpenCode after
250
+ installing or updating the plugin, then select the command from the `/`
251
+ autocomplete list:
252
+
253
+ The implementations remain registered, but the TUI marks commands as hidden
254
+ when their prerequisites are absent; it does not disable or delete them. With
255
+ the default configuration, only `/qoder_usage` and `/qoder_models` appear.
256
+ Session commands appear when session persistence, `sessionKey`, or `sessionId`
257
+ is configured. MCP commands appear when at least one MCP server is configured.
258
+ `/qoder_plan_mode` remains hidden because it currently provides guidance only.
259
+
260
+ | Command | Arguments | Purpose |
261
+ |---------|-----------|---------|
262
+ | `/qoder_usage` | none | Show live quota and local cost/token totals. |
263
+ | `/qoder_models` | none | List available Qoder models and capabilities. |
264
+ | `/qoder_sessions` | optional directory and/or limit | List recent Qoder sessions. |
265
+ | `/qoder_session_reset` | optional key, or `all` | Reset persisted session mappings. |
266
+ | `/qoder_session_fork` | optional session ID, directory, title, cutoff | Create an independent session branch. |
267
+ | `/qoder_mcp_status` | none | Inspect MCP connection and OAuth status. |
268
+ | `/qoder_mcp_auth` | server, then optional callback URL | Start or complete MCP OAuth. |
269
+ | `/qoder_plan_mode` | none | Show Plan Mode status and configuration guidance. |
270
+
271
+ These commands execute in the TUI and show their result in a modal box. They do
272
+ not create an LLM turn or consume model tokens. Commands that accept arguments
273
+ open a local input box first. The same names are also registered as tools for
274
+ agent use, which is a separate model-driven path.
275
+
276
+ ### Proxy & Network Routing
277
+
278
+ Pass an outbound proxy URL directly to the Qoder runtime without mutating host
279
+ environment variables (supports `http://`, `https://`, `socks5://`, and `socks://`):
280
+
281
+ ```json
282
+ {
283
+ "provider": {
284
+ "qoder": {
285
+ "options": {
286
+ "proxy": "http://127.0.0.1:8888"
287
+ }
288
+ }
289
+ }
290
+ }
291
+ ```
292
+
293
+ If `proxy` is omitted, the bridge automatically falls back to `HTTPS_PROXY` or
294
+ `HTTP_PROXY` from your environment.
295
+
296
+ ### Memory
297
+
298
+ Memory is opt-in. Native mode lets Qoder consume project/user memory and run
299
+ turn-completion generation while keeping generated content under Qoder's own
300
+ memory controls:
173
301
 
174
302
  ```json
175
303
  {
176
304
  "provider": {
177
305
  "qoder": {
178
306
  "options": {
179
- "sessionPersistence": true,
180
- "sessionKey": "my-project-main"
181
- }
182
- }
183
- }
184
- }
185
- ```
186
-
187
- Mappings are stored in
188
- `~/.config/opencode-qoder-bridge/sessions.json` with restrictive file
189
- permissions and are scoped to the configured working directory. The plugin
190
- uses OpenCode's project directory when available; set `options.cwd` when
191
- loading the provider directly. Use the `qoder_session_reset` tool to forget
192
- the mapping. A new session is created automatically if the mapping does not
193
- exist; existing sessions are resumed through the Qoder SDK.
194
-
195
- Qoder-native and bridged MCP tools remain provider-owned. If OpenCode supplies
196
- a function with a colliding native name, the bridge derives a Qoder deny rule
197
- to avoid executing the same operation in both runtimes.
198
-
199
- The bridge uses the SDK's safer permission policy by default. To explicitly
200
- allow all Qoder tools in a trusted local environment, configure for example:
201
-
202
- ```json
203
- {
204
- "provider": {
205
- "qoder": {
206
- "options": {
207
- "permissionMode": "default",
208
- "allowedTools": ["Read", "Glob", "Grep"]
307
+ "memory": {
308
+ "mode": "native",
309
+ "projectScope": true,
310
+ "userScope": false
311
+ }
209
312
  }
210
313
  }
211
314
  }
212
315
  }
213
316
  ```
214
317
 
215
- Available permission modes are `default`, `acceptEdits`, and
216
- `bypassPermissions`. Only explicitly configure `bypassPermissions` when the
217
- host environment is trusted.
218
-
219
- Image inputs may reference `file://`, `~/`, or absolute local paths. Only pass
220
- paths from trusted callers: the bridge bounds image size but does not sandbox
221
- or restrict readable local files to the project directory. A current turn is
222
- limited to 64 images and 40 MiB of decoded image data; excess attachments are
223
- reported as omitted text.
318
+ The bridge waits up to 10 seconds for Qoder's memory/evolution background work
319
+ after a successful turn, then closes the query. A slow or failed background
320
+ operation is logged in debug mode and does not fail the user turn.
224
321
 
225
- ### Plan Mode
322
+ ### Security Scan
226
323
 
227
- Plan Mode instructs Qoder to analyze and plan changes without modifying files
228
- or running action tools. It operates independently from tool permissions,
229
- preserving your configured `permissionMode`:
324
+ Security checks are opt-in and disabled unless explicitly configured:
230
325
 
231
326
  ```json
232
327
  {
233
328
  "provider": {
234
329
  "qoder": {
235
330
  "options": {
236
- "planMode": true
331
+ "securityScan": {
332
+ "l1StaticCheck": true,
333
+ "l2LightweightScan": true,
334
+ "l3DeepScan": false
335
+ }
237
336
  }
238
337
  }
239
338
  }
240
339
  }
241
340
  ```
242
341
 
243
- Run `/qoder_plan_mode` in OpenCode for quick guidance.
342
+ L1 runs after supported edits; L2/L3 enable repository scans. These checks do
343
+ not replace the bridge's permission policy and may consume additional Qoder
344
+ credits.
244
345
 
245
- ### Proxy & Network Routing
346
+ ### MCP OAuth and session forks
246
347
 
247
- Pass an outbound proxy URL directly to the Qoder runtime without mutating host
248
- environment variables (supports `http://`, `https://`, `socks5://`, and `socks://`):
348
+ Use `qoder_mcp_status` to inspect configured server state. For a server with
349
+ `needs-auth`, run `qoder_mcp_auth` without `callbackUrl`, open the returned
350
+ authorization URL, then run it again with the complete OAuth callback URL.
351
+ The bridge keeps the initialized SDK query alive for this two-step flow and
352
+ expires it after ten minutes.
249
353
 
250
- ```json
251
- {
252
- "provider": {
253
- "qoder": {
254
- "options": {
255
- "proxy": "http://127.0.0.1:8888"
256
- }
257
- }
258
- }
259
- }
260
- ```
261
-
262
- If `proxy` is omitted, the bridge automatically falls back to `HTTPS_PROXY` or
263
- `HTTP_PROXY` from your environment.
354
+ Use `qoder_session_fork` to create an independent local transcript branch.
355
+ The active provider mapping is intentionally unchanged; continue the returned
356
+ session ID explicitly when you want to work on the fork.
264
357
 
265
358
  ### Skill Evolution
266
-
267
- Enable autonomous turn-completion skill analysis and recommendations:
268
-
269
- ```json
270
- {
271
- "provider": {
272
- "qoder": {
273
- "options": {
274
- "evolution": {
275
- "skill": { "mode": "native" }
276
- }
277
- }
278
- }
279
- }
280
- }
281
- ```
282
-
283
- ### Available Tools
284
-
285
- The plugin registers several built-in OpenCode tools:
286
-
287
- - `qoder_usage` — Live account balance, quota percentages, and local cost ledger totals.
288
- - `qoder_models` — List known Qoder models, context limits, vision/reasoning flags, and multipliers.
289
- - `qoder_sessions` — List recent Qoder sessions, session IDs, branches, and timestamps via SDK `listSessions()`.
290
- - `qoder_session_reset` — Forget the persisted Qoder session mapping for the active project.
359
+
360
+ Enable autonomous turn-completion skill analysis and recommendations:
361
+
362
+ ```json
363
+ {
364
+ "provider": {
365
+ "qoder": {
366
+ "options": {
367
+ "evolution": {
368
+ "skill": { "mode": "native" }
369
+ }
370
+ }
371
+ }
372
+ }
373
+ }
374
+ ```
375
+
376
+ ### Available Tools
377
+
378
+ The plugin registers several built-in OpenCode tools:
379
+
380
+ - `qoder_usage` — Live account balance, quota percentages, and local cost ledger totals.
381
+ - `qoder_models` — List known Qoder models, context limits, vision/reasoning flags, and multipliers.
382
+ - `qoder_sessions` — List recent Qoder sessions, session IDs, branches, and timestamps via SDK `listSessions()`.
383
+ - `qoder_session_reset` — Forget the persisted Qoder session mapping for the active project.
384
+ - `qoder_session_fork` — Fork a local Qoder transcript without changing the active mapping.
385
+ - `qoder_mcp_status` — Show MCP connection, tool-count, and OAuth state.
386
+ - `qoder_mcp_auth` — Start or complete active MCP OAuth authentication.
291
387
  - `qoder_plan_mode` — View Plan Mode status and configuration guidance.
292
-
293
- ## Troubleshooting
294
-
295
- | Problem | Solution |
296
- |---------|----------|
297
- | Auth prompt at startup | Run `qoder login`, then restart opencode |
298
- | `qodercli not found` | Authenticate with `qoder login` or set `QODER_PERSONAL_ACCESS_TOKEN`; the SDK can use its bundled runtime, while an installed CLI is preferred when available |
299
- | Model not found | Verify the model ID matches the table above |
300
- | Missing models in the model list | Run `/qoder_models`; the bridge refreshes the live catalog at startup and falls back to the last cached catalog plus the built-ins (`lite`, `auto`, `performance`) when offline. If your account serves models in a different Qoder scene, set `QODER_SCENE` before launching opencode |
301
-
302
- ### How model discovery works
303
-
304
- At startup the bridge immediately exposes cached/built-in models, then
305
- refreshes the live catalog from Qoder (`fetchStrategy: "live"` — the CLI
306
- re-queries the server and falls back to its local cache if the server returns
307
- nothing). Each successful catalog snapshot replaces previously discovered
308
- dynamic IDs, so retired models do not remain selectable. A failed refresh
309
- keeps the last known catalog and the built-ins.
310
-
311
- ## Development
312
-
313
- ```bash
314
- npm install
315
- npm run build # compile to dist/
316
- npm run typecheck # type-check only
388
+
389
+ ## Troubleshooting
390
+
391
+ | Problem | Solution |
392
+ |---------|----------|
393
+ | Auth prompt at startup | Run `qoder login`, then restart opencode |
394
+ | Qoder runtime unavailable | Authenticate with `qoder login` or set `QODER_PERSONAL_ACCESS_TOKEN`; the bridge uses the SDK's bundled Worker runtime for model discovery and can fall back to an installed CLI automatically |
395
+ | Model not found | Run `opencode models qoder` or `/qoder_models`; model IDs are account- and scene-specific |
396
+ | Missing models in the model list | Restart OpenCode; the bridge performs a live catalog lookup automatically and falls back to the last scoped catalog plus the built-ins (`lite`, `auto`, `performance`) when offline. If your account serves models in a different Qoder scene, set `QODER_SCENE` before launching OpenCode |
397
+
398
+ The SDK package `1.0.31` bundles qodercli `1.1.38`. If the bridge discovers a
399
+ separately installed qodercli first, update that CLI through its normal Qoder
400
+ CLI installer too so the MCP OAuth and oversized-image compaction fixes are
401
+ active on that path.
402
+
403
+ ### How model discovery works
404
+
405
+ At startup the bridge performs a bounded live catalog discovery from Qoder
406
+ before returning the provider configuration (`fetchStrategy: "live"` — the
407
+ bundled Worker runtime re-queries the server, with an automatic installed-CLI
408
+ fallback when necessary). Each successful catalog snapshot replaces
409
+ previously discovered dynamic IDs, so retired models do not remain selectable.
410
+ A failed, empty, or slow refresh falls back to the last scoped catalog and the
411
+ built-ins; no `qodercli --list-models` command or manual model configuration is
412
+ required. The startup wait is bounded to 10 seconds, after which OpenCode
413
+ continues with the available cache/fallbacks.
414
+
415
+ ## Development
416
+
417
+ ```bash
418
+ npm install
419
+ npm run build # compile to dist/
420
+ npm run typecheck # type-check only
317
421
  npm test # build and run the test suite
422
+ npm run test:stress # deterministic stress suite; live abort stress is opt-in
318
423
  npm run test:e2e # authenticated real-CLI test; requires QODER_E2E=1
319
- npm run check # full pre-publish verification
320
- ```
321
-
322
- ### Diagnostics
323
-
324
- Set `QODER_BRIDGE_DEBUG=1` before launching opencode to emit detailed bridge
325
- logs (model fallbacks, stream aborts, background catalog refreshes, ledger and
326
- session-store I/O failures). Warnings that need attention are always printed.
327
-
328
- State files (usage ledger, session mapping, model cache) live under
329
- `~/.config/opencode-qoder-bridge` by default; override with
330
- `QODER_BRIDGE_STATE_DIR`, or relocate via `XDG_CONFIG_HOME`.
331
-
424
+ npm run check # full pre-publish verification
425
+ ```
426
+
427
+ ### Diagnostics
428
+
429
+ Set `QODER_BRIDGE_DEBUG=1` before launching opencode to emit detailed bridge
430
+ logs (model fallbacks, stream aborts, live catalog discovery, ledger and
431
+ session-store I/O failures). Warnings that need attention are always printed.
432
+
433
+ State files (usage ledger, session mapping, model cache) live under
434
+ `~/.config/opencode-qoder-bridge` by default; override with
435
+ `QODER_BRIDGE_STATE_DIR`, or relocate via `XDG_CONFIG_HOME`.
436
+
332
437
  The end-to-end test is intentionally opt-in because it starts Qoder and may
333
438
  consume account quota. Run it only after `qoder login`:
334
-
335
- ```bash
439
+
440
+ ```bash
336
441
  QODER_E2E=1 npm run test:e2e
337
442
  ```
338
443
 
339
- ## Security
340
-
341
- Report suspected vulnerabilities privately as described in
342
- [SECURITY.md](./SECURITY.md). Do not include Qoder credentials, npm tokens, or
343
- private prompt content in reports.
344
-
345
- Maintainer release instructions are in [RELEASING.md](./RELEASING.md).
346
- Release history is recorded in [CHANGELOG.md](./CHANGELOG.md).
347
-
348
- ## License
349
-
350
- The bridge source is MIT licensed; see [LICENSE](./LICENSE). Dependencies retain
351
- their own licenses and terms; see [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).
444
+ To include the live concurrent-abort probe in the stress suite, set
445
+ `QODER_STRESS_E2E=1` as well as a valid Qoder credential.
446
+
447
+ ## Security
448
+
449
+ Report suspected vulnerabilities privately as described in
450
+ [SECURITY.md](./SECURITY.md). Do not include Qoder credentials, npm tokens, or
451
+ private prompt content in reports.
452
+
453
+ Maintainer release instructions are in [RELEASING.md](./RELEASING.md).
454
+ Release history is recorded in [CHANGELOG.md](./CHANGELOG.md).
455
+
456
+ ## License
457
+
458
+ The bridge source is MIT licensed; see [LICENSE](./LICENSE). Dependencies retain
459
+ their own licenses and terms; see [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md).