@route_33/opencode 0.4.6 → 0.4.7-rc.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,119 +1,105 @@
1
1
  # @route_33/opencode
2
2
 
3
- An opencode provider plugin for the [route33.ai](https://route33.ai) AI gateway: model discovery, cost/limit metadata, and a key-setup wizard in the TUI.
3
+ The Route 33 plugin for OpenCode: sign in with your browser, assign the budget for
4
+ usage, and use the route_33 models — no API keys to paste, ever.
4
5
 
5
6
  ## Install
6
7
 
7
- ```bash
8
- opencode plugin @route_33/opencode
9
- ```
10
-
11
- The installer patches both configs: the server plugin into `opencode.json` and the key-setup wizard (TUI plugin) into `tui.json`. To install manually instead, declare both entries yourself:
12
-
13
- ```jsonc
14
- // opencode.json — server plugin (model discovery, cost/limit enrichment, auth)
15
- {
16
- "plugin": ["@route_33/opencode"]
17
- }
18
- ```
8
+ **OpenCode v2 (recommended):**
19
9
 
20
- ```jsonc
21
- // tui.json — TUI plugin (the key-setup wizard)
22
- {
23
- "plugin": ["@route_33/opencode"]
24
- }
10
+ ```sh
11
+ opencode plugin add @route_33/opencode
25
12
  ```
26
13
 
27
- This plugin never writes your `opencode.json` or `opencode.jsonc`: opencode has no TUI-plugin auto-discovery, so without a `tui.json` entry the wizard simply never appears — the server plugin works regardless. The only files the plugin ever writes inside your repo are an optional `.opencode/route33.key` (git-ignored automatically) and your own `.opencode/route33-overrides.json` (yours to commit or ignore).
28
-
29
- ## Auth
30
-
31
- Run `opencode auth login` and choose `route_33`, or set the `ROUTE33_API_KEY` environment variable. Without a key, the TUI wizard offers to save one: per-project inside a git workspace, global otherwise. A globally stored key applies only outside git workspaces — inside a workspace, keys resolve from the environment, the workspace config, or `.opencode/route33.key` (per-project keys are the metering boundary). Skipping the project-key wizard snoozes it for 7 days — "Skip" for that workspace only, "Skip for all workspaces" everywhere (both live in opencode's TUI kv store; remove `project-key-prompt.dismissed-at*` from `~/.local/state/opencode/kv.json` to re-arm sooner). `ROUTE33_BASE_URL` overrides the default gateway URL; `ROUTE33_TUI_PROMPT=0` disables the wizard.
32
-
33
- Your key is never written into the resolved provider configuration: authentication is attached per request at fetch time, so `opencode debug config` output contains no credential material. One inert exception: the options carry the non-secret marker `__route33_fetch_shim_auth__` as `apiKey`, because the native per-model SDKs used for `anthropic/`, `openai/`, and `mistralai/` models (`@ai-sdk/anthropic`, `@ai-sdk/openai`, `@ai-sdk/mistral`) refuse to construct a request without one — the marker satisfies that null check, never authenticates anything (the gateway reads only the request-time `Authorization` header, which the fetch shim injects), and no vendor env var (`ANTHROPIC_API_KEY` etc.) is needed or consulted. The marker is skipped by key resolution and never overrides an `apiKey` you authored yourself; it is visible in config dumps precisely because it is not a secret.
34
-
35
- ## Model catalog
36
-
37
- The catalog is discovered dynamically. The plugin calls `GET {baseURL}/models` with your resolved API key, caches the response on disk, and injects only the models that key can see. The refresh ladder is:
38
-
39
- 1. Return the fresh on-disk cache if it has not expired.
40
- 2. Fetch live from the gateway and update the cache.
41
- 3. If the live fetch fails, return the stale cache.
42
- 4. If there is no cache and no live response, preserve existing generated entries and inject no replacement models.
14
+ Installs globally — one `plugins` entry in the config's `opencode.json`
15
+ loads every part (the server and TUI parts are auto-discovered from the
16
+ package exports; no `tui.json` exists on v2).
43
17
 
44
- The plugin does not embed or serve a static catalog. The on-disk cache is keyed by gateway URL **and** API key, so the same key pointed at a different gateway (`ROUTE33_BASE_URL`, e.g. a local cluster) never shares a cache with production. Catalog cache envelopes are versioned; cache files from older plugin versions are ignored after an upgrade and repopulated from the gateway.
18
+ **OpenCode v1:**
45
19
 
46
- If discovery yields no catalog, the plugin logs exactly one warning:
47
-
48
- ```
49
- route33: no model catalog available — 0 models injected (reason). route33 is unusable without a catalog: resolve an API key (opencode auth login / ROUTE33_API_KEY) — the key dictates which models are available.
20
+ ```sh
21
+ opencode plugin @route_33/opencode # project scope (default)
22
+ opencode plugin @route_33/opencode --global # global scope
50
23
  ```
51
24
 
52
- Set `ROUTE33_DISCOVERY=0` to opt out of discovery entirely. This is logged at `info` and injects zero models without the warning.
53
-
54
- ## Metadata provenance
55
-
56
- Models are decorated with metadata from the route33 gateway broadcast; `models.dev` is used only as a backfill source.
57
-
58
- - **Cost**: the gateway's broadcast pricing wins; `models.dev` fills in when the broadcast carries no pricing.
59
- - **Limits**: the gateway's broadcast `limits` win; `models.dev` fills in when the gateway broadcasts none. Limits are omitted entirely when neither source knows them; the plugin never fabricates them.
60
- - **Modalities**: gateway `modalities.input` / `modalities.output` are passed through to opencode. Invalid modality values and malformed modality objects are omitted per model.
61
- - **Attachment**: gateway `attachment` wins whenever present. `models.dev` supplies it only when the gateway omits the field.
62
- - **Capabilities**: the broadcast `reasoning` and `tool_support` flags win (`tool_support` is mapped to `tool_call`); `models.dev` always backfills any capability flag left undefined.
63
- - **Variants**: R33 broadcast variants are passed verbatim (for example, `kimi-k3`'s `max` `reasoningEffort` variant).
64
-
65
- The normative broadcast contract is [docs/gateway-limits-variants-broadcast.md](docs/gateway-limits-variants-broadcast.md).
25
+ Installs at the nearest definition and registers the plugin twice: the
26
+ server part in `opencode.json` and the TUI part in `tui.json` — both files
27
+ are load-bearing on v1, which is why the installer writes both.
66
28
 
67
- ## Managed model entries
29
+ Either way, restart OpenCode afterwards — plugins load at startup. Prefer
30
+ config? Declare the plugin directly in `opencode.json(c)`:
68
31
 
69
- Gateway-discovered `provider.route_33.models` entries are fully managed: every startup rebuilds the map from the current broadcast, then deep-merges your overrides on top. The ownership rule is the whole design — *in the broadcast (or in your overrides) ⇒ kept; anything else ⇒ dropped and logged* — so retired gateway models disappear automatically and no bookkeeping file is needed. (Versions ≤0.4.3 kept a `.opencode/route33-generated.json` ledger for this; the plugin deletes that obsolete file on first run.)
32
+ ```jsonc
33
+ { "plugin": ["@route_33/opencode"] }
34
+ ```
70
35
 
71
- Keep customizations in `.opencode/route33-overrides.json`, because the installed OpenCode `ProviderConfig` does not allow unknown provider-level keys such as `modelOverrides`. Overrides deep-merge onto matching generated entries and can add custom models:
36
+ ## First run
72
37
 
73
- ```json
74
- {
75
- "models": {
76
- "openai/gpt-5.5": { "variants": { "fast": { "temperature": 0 } } },
77
- "custom/internal": { "name": "Internal model" }
78
- }
79
- }
80
- ```
38
+ With `ROUTE33_API_KEY` unset and `ROUTE33_AUTOCONNECT` not `0`, the wizard
39
+ auto-starts at launch and blocks the TUI on both OpenCode versions — the
40
+ prompt stays locked behind a setup mode until a budget is assigned, with
41
+ Enter resuming setup; route_33 model requests are also refused
42
+ server-side with the same guidance where the lock is unavailable:
81
43
 
82
- If the gateway fetch fails with no usable cache, regeneration is skipped entirely: existing entries are never pruned on zero information.
44
+ 1. The sign-in dialog offers the Route 33 link — press `o` to open it in
45
+ your browser (or `c` to copy it) — and continues by itself once
46
+ you've signed in.
47
+ 2. The budget picker follows in OpenCode — one of your Route 33 projects,
48
+ or your personal key.
49
+ 3. The route_33 models appear. Pick one and prompt away.
83
50
 
84
- `ROUTE33_ENRICH_CAPS` has been removed; capability backfill from `models.dev` is now always on.
51
+ ## Commands
85
52
 
86
- ## Model-reference tolerance
53
+ | Command | Effect |
54
+ | ------------- | -------------------------------------------------------------------- |
55
+ | `/r33` | Show the assigned budget, the active key, and its rotation state |
56
+ | `/r33 rotate` | Rotate the key immediately |
57
+ | `/r33 reset` | Clear the assigned budget — connect again to pick a different option |
87
58
 
88
- Model references in your config that differ from the served ID only by digit-boundary dots versus dashes in the tail resolve automatically. For example, `anthropic/claude-opus-4.8` resolves to the served `anthropic/claude-opus-4-8` and is injected with the served wire ID. Arbitrary renames, such as `gpt5.5` for `openai/gpt-5.5`, do not resolve.
59
+ A browser is required for every sign-in; restarts afterwards sign in silently.
89
60
 
90
- ## Environment variables
61
+ ## Keys
91
62
 
92
- | Variable | Effect |
93
- |---|---|
94
- | `ROUTE33_API_KEY` | Gateway API key; highest precedence. See Auth. |
95
- | `ROUTE33_BASE_URL` | Override the default gateway base URL. See Auth. |
96
- | `ROUTE33_TUI_PROMPT` | Set to `0` to disable the key-setup wizard. See Auth. |
97
- | `ROUTE33_DISCOVERY` | Set to `0` to disable dynamic catalog discovery. |
98
- | `ROUTE33_STRICT` | Set to `0` to downgrade unknown-model reference errors to a warning plus a stub entry. |
99
- | `ROUTE33_CACHE_DIR` | Override the directory used for the on-disk catalog cache. |
63
+ One key per workspace: each project folder uses its own Route 33 key, and
64
+ every request carries the key of its own workspace — connecting another
65
+ folder never changes who this one bills for. Keys are short-lived and rotate
66
+ automatically; nothing secret is ever written to your project, logs, or
67
+ terminal.
100
68
 
101
- The plugin reads only these variables. `ROUTE33_ENRICH_CAPS` is no longer supported.
69
+ ## Direct key mode
102
70
 
103
- ## Exhaustion retry
71
+ Set `ROUTE33_API_KEY` to a gateway key and the wizard is bypassed entirely —
72
+ no sign-in, no attribution pick, no browser, no per-workspace keys. This is
73
+ the right choice for autonomous, headless, or remote sessions where no human
74
+ is present or the machine has no browser. Key rotation is your responsibility.
104
75
 
105
- Starting with v0.4.6, the plugin wraps live chat/compat requests in an exhaustion retry layer. It triggers only on an HTTP `429` whose error code is `PROVIDER_LANES_EXHAUSTED` (all provider lanes exhausted). It reads the gateway's `Retry-After` response header and falls back to a client-side schedule of `5·2^(n−1)` seconds capped at 1200 when the header is missing. It waits through the delay while respecting the request's abort signal, then re-issues the identical request. It keeps retrying indefinitely until the request succeeds or the user cancels it.
76
+ ```sh
77
+ export ROUTE33_API_KEY=r33_sk_...
78
+ ```
106
79
 
107
- Non-exhaustion errors (network failures, 4xx responses from the gateway other than the exhaustion code, etc.) are passed through untouched.
80
+ ## Auto-connect
108
81
 
109
- Each wait is logged with the attempt number, waited seconds, and the gateway's `correlationId`:
82
+ The First-run wizard auto-starts at OpenCode launch for unconnected
83
+ folders. Suppress it with `ROUTE33_AUTOCONNECT=0` and connect manually
84
+ instead — `/r33` or `/connect`. On remote or headless machines, use
85
+ `ROUTE33_API_KEY` instead of the wizard.
110
86
 
111
- ```
112
- route33: exhausted; waiting <seconds>s before retry <attempt> (correlationId=<correlationId>)
113
- ```
87
+ ## Troubleshooting
114
88
 
115
- The provider option `headerTimeout` is set to `1_500_000` ms (25 minutes). This is higher than opencode's own 300-second fetch default so that scheduled waits are not aborted while waiting for a lane to cool down. It is safe because the gateway caps provider hangs at 120 s TTFB and 240 s first-event timeouts, so the connection is never silent for anywhere near 25 minutes.
89
+ | Symptom | What to do |
90
+ | --------------------------------------------- | -------------------------------------------------------------------------------- |
91
+ | No route_33 models after start | `/connect` → Route 33 — the silent sign-in expired; sign in once and they return |
92
+ | "This Route 33 build has no OAuth client id" | Update the plugin to a released build, or set `ROUTE33_CLIENT_ID` and restart |
93
+ | "needs a Git worktree" | Open a Git repository (or `git init`) in the folder, then connect again |
94
+ | Sign-in link never appears / SSH-only machine | Sign-in needs a browser on the same machine — there is no device-flow fallback |
116
95
 
117
- ## License
96
+ ## Configuration
118
97
 
119
- Proprietary — "SEE LICENSE IN LICENSE". Install and use as-is via npm; copying, modification, and redistribution are not permitted. Provided AS-IS, without warranty or liability.
98
+ | Variable | Purpose | Default |
99
+ | --------------------- | -------------------------------------------- | -------------------------------- |
100
+ | `ROUTE33_API_KEY` | Pre-shared gateway key (bypasses the wizard) | not set (wizard mode) |
101
+ | `ROUTE33_AUTOCONNECT` | Opt out of the auto-start wizard | `1` (auto-start enabled) |
102
+ | `ROUTE33_CLIENT_ID` | OAuth client identifier | included in released builds |
103
+ | `ROUTE33_AUTH_ISSUER` | OAuth issuer | `https://auth.route33.ai` |
104
+ | `ROUTE33_API_BASE` | Management API base | `https://mapi.route33.ai/api/v1` |
105
+ | `ROUTE33_BASE_URL` | Gateway models base | `https://api.route33.ai/v1` |