opencode-actualyze 2.0.0 → 2.0.1

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
@@ -2,26 +2,29 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/opencode-actualyze)](https://www.npmjs.com/package/opencode-actualyze)
4
4
  [![Release](https://github.com/actualyze-ai/opencode-actualyze/actions/workflows/release.yml/badge.svg)](https://github.com/actualyze-ai/opencode-actualyze/actions/workflows/release.yml)
5
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/license/MIT)
6
6
 
7
7
  Actualyze's plugin for [OpenCode](https://opencode.ai) adds
8
- [Actualyze](https://actualyze.ai) as a provider. It also finds the models any
9
- OpenAI-compatible server actually serves and gives OpenCode what it needs to
10
- use them: context and output limits, tool support, input modalities,
11
- reasoning-effort variants, and prices where the server reports them. It has
12
- probes for Actualyze, Ollama, oMLX, vLLM, TGI, SGLang, LM Studio, KoboldCpp,
13
- llama.cpp, and LocalAI. This README calls the plugin scout, after its model
14
- browser, Model Scout.
15
-
16
- Version 2 is for OpenCode 2 and is tested against OpenCode 2.0.32. If you are
17
- still on OpenCode 1, see [Using OpenCode 1](#using-opencode-1). If you used
18
- `opencode-model-scout`, see
8
+ [Actualyze](https://actualyze.ai) as a provider. Connect an Actualyze API key
9
+ and your team's models appear in OpenCode's model picker, with no provider
10
+ config. The plugin fills in each model's context and output limits, its tool
11
+ and reasoning support, its input types, and its prices from Actualyze's
12
+ catalog. The `/actualyze` command shows the key in use, whether the catalog
13
+ answered for it, the model list, and links into the Actualyze app.
14
+
15
+ It also works with other OpenAI-compatible servers: it detects the models a
16
+ server serves and populates their catalog entries the same way. Probes read
17
+ the metadata of eight servers: Actualyze, Ollama, oMLX, vLLM, TGI, SGLang,
18
+ LM Studio, and KoboldCpp. The Ollama probe also covers llama.cpp and LocalAI.
19
+ The Model Scout browser, `/modelscout`, lists every discovered model and
20
+ where each value came from.
21
+
22
+ The plugin requires OpenCode 2 and is tested against OpenCode 2.1.3. If you
23
+ used `opencode-model-scout`, see
19
24
  [Moving from opencode-model-scout](#moving-from-opencode-model-scout).
20
25
 
21
26
  ## Quick Start
22
27
 
23
- ### With Actualyze
24
-
25
28
  Actualyze needs no provider config. The plugin adds an `actualyze` provider
26
29
  for `https://app.actualyze.ai/openai/v1`, and it appears as soon as OpenCode
27
30
  has your API key.
@@ -48,12 +51,251 @@ has your API key.
48
51
 
49
52
  3. The Actualyze models appear in the model picker once discovery finishes.
50
53
  `/actualyze` shows whether the catalog answered for your key and, if it
51
- did not, what to do next. See [Actualyze](#actualyze) for other
52
- environments and details.
54
+ did not, what to do next.
55
+
56
+ For a server other than Actualyze, see
57
+ [Other OpenAI-Compatible Servers](#other-openai-compatible-servers).
58
+
59
+ ## Actualyze
60
+
61
+ Actualyze serves its model catalog through an OpenAI-compatible endpoint, and
62
+ its `/v1/models` entries can carry each model's full metadata.
63
+
64
+ ### The built-in provider
65
+
66
+ The plugin adds this provider to OpenCode's catalog:
67
+
68
+ | Field | Value |
69
+ | ------------------ | ------------------------------------------ |
70
+ | ID | `actualyze` |
71
+ | Name | Actualyze |
72
+ | `package` | `@opencode/ai/providers/openai-compatible` |
73
+ | `settings.baseURL` | `https://app.actualyze.ai/openai/v1` |
74
+ | `settings.probe` | `actualyze` |
75
+
76
+ It also registers an Actualyze integration, which is what `/connect` and
77
+ `opencode auth login actualyze` offer. The integration takes a stored API key
78
+ or the `ACTUALYZE_API_KEY` environment variable of the background service.
79
+ Discovery and chat both use that key. The integration's ID is `actualyze`,
80
+ the same as the provider's, so a `providers.actualyze` config entry and
81
+ `opencode auth login actualyze` both reach the integration the provider reads
82
+ its key from.
83
+
84
+ Until the integration has a key, OpenCode hides the provider, so without an
85
+ Actualyze key the built-in provider adds nothing to the model picker.
86
+
87
+ ### Another Actualyze environment
88
+
89
+ To use a different deployment, set only its base URL. Your config is merged
90
+ over the built-in provider field by field, so the name, package, probe, and
91
+ key handling stay as they are:
92
+
93
+ ```json
94
+ {
95
+ "providers": {
96
+ "actualyze": {
97
+ "settings": {
98
+ "baseURL": "https://actualyze.example.com/openai/v1"
99
+ }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ Any `providers.actualyze` entry in your config makes OpenCode list the
106
+ provider even without a key. Discovery then runs without credentials, and
107
+ `/modelscout` and `/actualyze` show the endpoint's error until you add one.
108
+ Add the key with `/actualyze`, `/connect`, or `opencode auth login actualyze`
109
+ as usual: the entry does not create a second Actualyze integration. A
110
+ `settings.apiKey` in the entry also works, without connecting the
111
+ integration. A connected key takes precedence over `settings.apiKey` for both
112
+ discovery and chat, so the two always use the same key.
113
+
114
+ ### When another source defines `actualyze`
115
+
116
+ A models.dev catalog or a plugin listed before this one can define an
117
+ `actualyze` provider of its own. Then:
118
+
119
+ - The plugin leaves that provider as it is and does not add its own.
120
+ - The plugin registers the `actualyze` integration only when no source has
121
+ registered one, so `/connect` lists Actualyze once.
122
+ - A provider defined with `"activation": "auto"` and no integration of its
123
+ own reads its key from that `actualyze` integration, so OpenCode hides it
124
+ until a key is connected there.
125
+ - The plugin does not discover that provider, because OpenCode already knows
126
+ its ID, and `/actualyze` reads `○ Not managed by Model Scout`. Add
127
+ `"probe": "actualyze"` to its `settings` in your config to opt in.
128
+
129
+ ### What the plugin reads from Actualyze
130
+
131
+ - **Which entries.** In auto mode, one entry whose `owned_by` is exactly
132
+ `actualyze` selects the probe, even in a catalog that mixes owners, and the
133
+ probe checks only the entries Actualyze owns. The rest are listed and
134
+ enriched from models.dev as usual. With `"probe": "actualyze"`, the
135
+ built-in provider's setting, the probe checks every listed model.
136
+ - **List first.** A checked entry that Actualyze owns and that carries the
137
+ full metadata (the `context_window` key and a `capabilities` object) is
138
+ read straight from `/v1/models`. For every other checked entry the probe
139
+ requests `GET /v1/models/{id}`, and it keeps the answer only when Actualyze
140
+ owns that model.
141
+ - **Fields.** `context_window` and `max_output_tokens` become the limits.
142
+ Capability flags (`vision`, `tool_use`, `thinking`, `thinking_adaptive`,
143
+ `temperature`, `document`, `audio`, `video`) are three-valued: `true` and
144
+ `false` are definitive, `null` means unknown. `modalities.input` is used
145
+ for input modalities when present. `created` becomes the release time.
146
+ - **Cost.** `cost.input`, `cost.output`, `cost.cache_read`, and
147
+ `cost.cache_write` are USD per million tokens. The plugin writes a missing
148
+ cache price as `0` in OpenCode's `cost`, and `/modelscout` shows it as not
149
+ reported. A model without `cost` gets no prices.
150
+ - **No effort variants.** Actualyze's chat endpoint does not pass
151
+ `reasoning_effort` on to the upstream model, so reasoning models from
152
+ Actualyze get no `low`/`medium`/`high` variants.
153
+
154
+ ## `/actualyze` Command
155
+
156
+ `/actualyze` takes you from no key to a working Actualyze catalog without
157
+ leaving OpenCode. Open it with `/actualyze`, pick **Actualyze** from the
158
+ command palette, or press `a` in `/modelscout`.
159
+
160
+ The header shows the Actualyze wordmark and the endpoint: its host for an
161
+ https endpoint, such as `app.actualyze.ai` for the built-in provider, and
162
+ `http://host:port` for an http one. When
163
+ `providers.actualyze.settings.baseURL` points anywhere other than the
164
+ built-in endpoint, the header adds a `custom endpoint` badge, and every app
165
+ link uses that endpoint's origin. The line under the header says where
166
+ things stand, and names the key in use: the connection's label in quotes,
167
+ `ACTUALYZE_API_KEY` for the environment variable, or `settings.apiKey`.
168
+
169
+ An Actualyze inference key can read the model catalog and nothing about the
170
+ account: no identity, usage, spend, or budget. So `/actualyze` reports
171
+ "Catalog accessible" when the model list answered for the key, and never
172
+ claims that chat works. A read-only key, for example, lists models and is
173
+ refused on every chat request.
174
+
175
+ ### States
176
+
177
+ | Status line | What it means | What to do |
178
+ | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
179
+ | `○ Loading…` | `/actualyze` is reading OpenCode's model lists and the plugin's catalog. | Wait. |
180
+ | `▲ OpenCode's model lists did not load` | OpenCode did not answer with its provider and model lists. The error is shown below the status line. | `r` reads them again. |
181
+ | `○ Not connected` | OpenCode has no Actualyze key. | Create a key in the app, then press `k` and paste it. The card lists the steps. |
182
+ | `○ Saving key…` | You submitted a key and OpenCode has not confirmed it yet. | Wait. Closing the dialog does not undo a completed save. |
183
+ | `▲ Save not confirmed` | Saving failed or took longer than 15 seconds. OpenCode may have stored the key anyway. | Check with `c` before trying again with `k`. |
184
+ | `○ Checking the current connection…` | The key is saved and the plugin has no result for it yet. After 20 seconds the line reads "Still checking the current connection…". | Wait. No inference request is sent. |
185
+ | `○ Checking the connection…` | A key is connected and the plugin is still resolving it. | Wait. |
186
+ | `○ Loading models…` | The first model list for this key is on its way. | Wait. |
187
+ | `● Catalog accessible · key "Work" · 11 models · checked 2 min ago` | The model list answered. The count is chat models, as in `/modelscout`; the filter row reports hidden embeddings. | Browse them; `enter` on a model opens the model picker with it highlighted. |
188
+ | `▲ No models for this key` | The catalog answered with an empty list: the key works, but its team has no model access yet. | Ask a workspace admin. `y` copies the Catalog link. |
189
+ | `▲ Key rejected (401)` | Actualyze answers this way for a revoked or expired key, a key without the inference scope, or a key from another Actualyze environment. | `k` for another key, `y` to copy the API Keys link, `c` for connections. |
190
+ | `▲ Access denied (403)` | Actualyze refused the model list request for this key. | Check the key's permissions and model access with your administrator, or use `k` for another key. |
191
+ | `▲ Budget or entitlement blocked (402)` | Actualyze did not allow the model list request. The key cannot read a balance or reset date. | `y` copies the Budgets link; that page may need an admin role. |
192
+ | `▲ Catalog rate limited (429)` | The model list is rate limited. This is a catalog limit, not an inference quota. The footer shows the wait: `retry (42 s) r`. | Retry with `r` once the wait ends; otherwise the plugin checks again on its next scheduled refresh, or when settings or the key change. |
193
+ | `▲ Could not reach the endpoint` | The connection failed. The header shows the endpoint. | Check the network, VPN, proxy, and `providers.actualyze.settings.baseURL`, then retry with `r`. |
194
+ | `▲ Endpoint did not answer in time` | The model list request timed out. | Check the network or the endpoint, then retry with `r`. |
195
+ | `▲ Actualyze server error (503)` | Actualyze failed to list its models. | Retry with `r`. |
196
+ | `▲ No model list at this endpoint (404)` | The base URL points at the wrong path. | Make `settings.baseURL` end in `/openai/v1`. |
197
+ | `▲ Unexpected answer (…)` | Another HTTP status, or an answer that is not a model list. | Check `settings.baseURL`. |
198
+ | `▲ Discovery was interrupted` or `▲ Discovery failed` | The check did not finish. | It runs again on the next refresh; `r` retries now. |
199
+ | `▲ Discovery status unavailable` | The plugin's server half did not answer, so only the connection OpenCode reports is known. | `k` and `c` still work; `r` reads the catalog again. |
200
+ | `○ Not managed by Model Scout` | Another plugin or a models.dev catalog defines the `actualyze` provider, so the plugin does not discover it. | Add `"probe": "actualyze"` to `providers.actualyze.settings` to opt in. |
201
+
202
+ The glyph carries the state's color; the words stay in the theme's text
203
+ color. When the line is too narrow, the age goes first and then the key
204
+ label, whole, so the line never ends in a cut word. Each card under the
205
+ status line starts with a title and gives the details below it.
206
+
207
+ After a failure, a key that had a good catalog before keeps it: the card sits
208
+ above the models from the last good check. When the key comes from
209
+ `settings.apiKey` or `ACTUALYZE_API_KEY`, the failure card says so, and adds
210
+ that a key connected with `k` takes precedence. When the provider's
211
+ `headers` carry the key (`Authorization` or `X-Actualyze-Api-Key`), a notice
212
+ says that discovery uses those headers, not the connected key.
213
+
214
+ When `providers.actualyze.settings.probe` names no probe, the status line
215
+ adds `▲ unknown probe` once the catalog is accessible, and a notice names the
216
+ value and lists the accepted ones. Remove the setting, or set it to
217
+ `actualyze`, so the probe reads the models' limits, prices, and
218
+ capabilities.
219
+
220
+ ### Keys in `/actualyze`
221
+
222
+ | Key | Action |
223
+ | ----- | ----------------------------------------------------------------------------------- |
224
+ | `k` | Connect a key: "connect key" without a connection, "another key" with one |
225
+ | `c` | Open OpenCode's connections; pick Actualyze there to switch, rename, or remove keys |
226
+ | `l` | Open the [links screen](#links) |
227
+ | `y` | On a card, copy the link it names; in the model list, copy `provider/model` |
228
+ | `r` | Check the catalog again; during a wait the hint is dimmed and reads "retry (N s)" |
229
+ | `b` | Open `/modelscout` |
230
+ | `?` | List the keys |
231
+ | `esc` | Close |
232
+
233
+ While a card fills the dialog, only the keys it offers, `?`, and `esc` work.
234
+ The footer lists the card's keys in one order: the key action, retry, copy
235
+ link, links, connections, all providers, then keys. When the footer runs out
236
+ of room it leaves out the hints that do not fit and keeps any later one that
237
+ does; the card then lists the left-out keys in an action line at its end, in
238
+ the same order, so every key shows once. `?` lists them all. A card longer
239
+ than the dialog shows `↓ N more` and scrolls with `↑`, `↓`, `pgup`, `pgdn`,
240
+ `home`, and `end`; the footer adds `scroll ↑↓` after the card's keys when
241
+ there is room for all of them.
53
242
 
54
- ### With another OpenAI-compatible server
243
+ Once the catalog is accessible, the model list works like `/modelscout`
244
+ limited to Actualyze, without a provider header or provider filter. `r`
245
+ refreshes Actualyze; there is no `R`. The footer shows `k` and `l` after the
246
+ model keys and, when there is room, `c` and `b` at its end; `?` lists all
247
+ four.
248
+
249
+ `k` works only when the provider reads its key from the `actualyze`
250
+ integration and that integration offers a plain key method. Otherwise the
251
+ card points to `c`. The plugin never deletes a key; removing one happens in
252
+ OpenCode's connections.
253
+
254
+ ### Entering a key
255
+
256
+ `k` opens OpenCode's prompt titled **Actualyze API key**. The key is visible
257
+ while you type, because OpenCode's prompt does not mask input. Press `enter`
258
+ to submit. The plugin trims the key, hands it once to OpenCode to store under
259
+ the Actualyze integration, and drops it; it never stores, logs, or shows the
260
+ key itself. `/actualyze` then comes back, shows "Saving key…", and checks the
261
+ catalog with the new key.
262
+
263
+ Pressing `esc` in the prompt cancels and closes `/actualyze`. Submitting an
264
+ empty prompt returns to `/actualyze` unchanged. If the plugin reloads while
265
+ the prompt is open, the prompt closes and nothing is saved; enter the key
266
+ again with `/actualyze`. A key submitted after the plugin reloaded, or after
267
+ the project changed, is not saved either, and a toast says so. If you close
268
+ `/actualyze` while OpenCode is still saving and the save is never confirmed,
269
+ a toast says "OpenCode did not confirm the Actualyze key was saved".
270
+
271
+ ### Links
272
+
273
+ `l` lists Actualyze app pages on the provider's origin:
274
+
275
+ | Link | Path |
276
+ | --------------- | ------------------------------------ |
277
+ | API Keys | `/account/settings?tab=security` |
278
+ | Catalog | `/control/catalog?tab=consume` |
279
+ | Budgets | `/management/budgets` |
280
+ | Usage | `/observability?tab=inference` |
281
+ | Troubleshooting | `/observability?tab=troubleshooting` |
282
+
283
+ `↑`, `↓`, `home`, and `end` choose a link, `enter` or `y` copies it the same
284
+ way `/modelscout` copies (see [Copying](#copying)), and `backspace` or `l`
285
+ returns. After a failure the matching link is selected first: API Keys for
286
+ 401 and 403, Budgets for 402, and Troubleshooting for the rest. Budgets may
287
+ need an admin role in Actualyze. The plugin cannot open a web browser, so
288
+ copy the link and paste it into one. When `settings.baseURL` is not an http
289
+ or https URL, there are no links, and the header says so.
55
290
 
56
- 1. Install the plugin as above.
291
+ ## Other OpenAI-Compatible Servers
292
+
293
+ Besides Actualyze, the plugin discovers the models of any OpenAI-compatible
294
+ server you configure as a provider and fills in their catalog entries.
295
+
296
+ ### Quick start with another server
297
+
298
+ 1. Install the plugin as in the [Quick Start](#quick-start).
57
299
 
58
300
  2. Add a provider with `settings.probe` to `~/.config/opencode/opencode.json`:
59
301
 
@@ -77,7 +319,7 @@ has your API key.
77
319
  usually within a few seconds and without a restart. Run `/modelscout` to
78
320
  see what was found and where each value came from.
79
321
 
80
- ## The Problem
322
+ ### The problem it solves
81
323
 
82
324
  An OpenAI-compatible `/v1/models` endpoint reports model IDs and little else.
83
325
  OpenCode sees `qwen3:30b-a3b` or `gemma3-12b-it` and has no idea whether the
@@ -86,17 +328,17 @@ is. Without that, OpenCode falls back to generic defaults, and the model
86
328
  picker never shows models you did not type into your config by hand.
87
329
 
88
330
  Most inference servers do publish this metadata, each through its own API.
89
- Scout asks those APIs, fills the remaining gaps from the
331
+ The plugin asks those APIs, fills the remaining gaps from the
90
332
  [models.dev](https://models.dev) data OpenCode already has, and adds every
91
333
  served model to the catalog.
92
334
 
93
- ## How It Works
335
+ ### How discovery works
94
336
 
95
337
  The plugin has two halves. The server half runs inside OpenCode's background
96
338
  service and does the discovery. The TUI half adds two commands:
97
- [`/modelscout`](#modelscout-command), a browser of every discovered model,
98
- and [`/actualyze`](#actualyze-command), which connects an Actualyze key and
99
- explains the state of its catalog.
339
+ [`/actualyze`](#actualyze-command), which connects an Actualyze key and
340
+ explains the state of its catalog, and [`/modelscout`](#modelscout-command),
341
+ a browser of every discovered model.
100
342
 
101
343
  For each provider it targets (see
102
344
  [Which providers are discovered](#which-providers-are-discovered)), the server
@@ -122,79 +364,9 @@ Discovery never runs during plugin setup, so it does not slow OpenCode's
122
364
  startup. Inventories stored by an earlier run are served right away, before
123
365
  any network request.
124
366
 
125
- ## Installation
367
+ ### Configuration
126
368
 
127
- ```bash
128
- opencode plugin add opencode-actualyze
129
- ```
130
-
131
- This installs the package and adds it to your global OpenCode configuration.
132
- `opencode plugin remove opencode-actualyze` takes it out again.
133
-
134
- To configure it by hand, list it in the `plugins` array of `opencode.json`:
135
-
136
- ```json
137
- {
138
- "plugins": ["opencode-actualyze"]
139
- }
140
- ```
141
-
142
- To pass [plugin options](#plugin-options), use the object form:
143
-
144
- ```json
145
- {
146
- "plugins": [
147
- {
148
- "package": "opencode-actualyze",
149
- "options": { "refreshIntervalMs": 1800000 }
150
- }
151
- ]
152
- }
153
- ```
154
-
155
- The package contains a server plugin and a TUI plugin. OpenCode loads the TUI
156
- half automatically together with the server half, so there is nothing else to
157
- add for `/modelscout` and `/actualyze`.
158
-
159
- ### Running from a checkout
160
-
161
- ```bash
162
- git clone https://github.com/actualyze-ai/opencode-actualyze.git
163
- cd opencode-actualyze
164
- npm install
165
- npm run compile
166
- ```
167
-
168
- Then point `plugins` at the build output directory:
169
-
170
- ```json
171
- {
172
- "plugins": ["/absolute/path/to/opencode-actualyze/dist"]
173
- }
174
- ```
175
-
176
- OpenCode loads a local plugin directory by looking for `server.js` and
177
- `tui.js` inside it, so the entry is `dist`, not the repository root.
178
-
179
- ### The background service and environment variables
180
-
181
- OpenCode 2 runs plugins in one shared background service per user, not in the
182
- terminal where you start `opencode`. Config substitutions such as
183
- `{env:LOCAL_LLM_KEY}` therefore read the service's environment, and a variable
184
- exported in your shell is not visible to them. Set it on the service and
185
- restart it:
186
-
187
- ```bash
188
- opencode service set env LOCAL_LLM_KEY <value>
189
- opencode service restart
190
- ```
191
-
192
- Alternatively, read the key from a file with `{file:~/path/to/key}`. A
193
- relative `{file:}` path resolves against the directory of the config file.
194
-
195
- ## Configuration
196
-
197
- ### Which providers are discovered
369
+ #### Which providers are discovered
198
370
 
199
371
  A provider is a discovery target when it has `settings.baseURL` and one of
200
372
  these holds:
@@ -203,23 +375,24 @@ these holds:
203
375
  - **It is a plain provider from your config.** Its package is the
204
376
  openai-compatible package, it has no `canonical`, and its ID is not one
205
377
  OpenCode already knows from models.dev, from a built-in provider, or from a
206
- plugin listed before scout. Such a provider is discovered without a probe:
207
- scout lists its models and fills metadata from models.dev and heuristics.
378
+ plugin listed before this one. Such a provider is discovered without a
379
+ probe: the plugin lists its models and fills metadata from models.dev and
380
+ heuristics.
208
381
 
209
382
  Everything else needs `settings.probe`. That includes a provider whose ID
210
383
  matches a models.dev provider (for example `deepseek` or `groq`) and an alias
211
- of a catalog provider set up with `canonical`. Scout leaves those alone by
212
- default so it never floods the picker with every ID a hosted API lists.
384
+ of a catalog provider set up with `canonical`. The plugin leaves those alone
385
+ by default so it never floods the picker with every ID a hosted API lists.
213
386
 
214
387
  #### Built-in local providers
215
388
 
216
- Scout never probes the provider IDs `ollama`, `lmstudio`, `vllm`, and
389
+ The plugin never probes the provider IDs `ollama`, `lmstudio`, `vllm`, and
217
390
  `opencode`, even with `settings.probe` set. OpenCode 2 has its own discovery
218
391
  for Ollama, LM Studio, and vLLM on their default local ports under those IDs,
219
392
  and the built-in `opencode` provider hides paid models on purpose when you
220
393
  have no key.
221
394
 
222
- To get scout's probes for a local server, configure it under your own
395
+ To get the plugin's probes for a local server, configure it under your own
223
396
  provider ID, such as `my-ollama`. If that provider points at the same port as
224
397
  a built-in one, its models are listed twice, once per provider. Disable the
225
398
  built-in provider plugin to avoid that:
@@ -233,30 +406,30 @@ built-in provider plugin to avoid that:
233
406
  The other built-ins are `-opencode.provider.lmstudio` and
234
407
  `-opencode.provider.vllm`.
235
408
 
236
- ### Provider settings
237
-
238
- | Field | Description |
239
- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
240
- | `package` | `@opencode/ai/providers/openai-compatible`. Scout also accepts `aisdk:@ai-sdk/openai-compatible` and `@ai-sdk/openai-compatible`. The package matters for auto-eligibility and for reasoning-effort variants. |
241
- | `settings.baseURL` | Server URL, with or without a trailing `/v1`. Required. |
242
- | `settings.apiKey` | Sent as `Authorization: Bearer <key>` on discovery requests when the provider has no connected key. A key connected in OpenCode (stored or from the environment) takes precedence, as it does for chat. |
243
- | `settings.probe` | `auto` or a probe ID from the table below. |
244
- | `headers` | Sent with every discovery and probe request. An `Authorization` header here replaces the one built from the API key. |
245
-
246
- | `settings.probe` | Effect |
247
- | ---------------- | ------------------------------------------------------------------------------------------------------- |
248
- | `auto` | Fingerprint the server and run the matching probe. If nothing matches, models are still listed. |
249
- | `actualyze` | Actualyze probe. `atlas` is accepted as a deprecated alias. |
250
- | `ollama` | Ollama probe; also the right choice for llama.cpp and LocalAI. |
251
- | `omlx` | oMLX probe. |
252
- | `vllm` | vLLM probe. |
253
- | `tgi` | Text Generation Inference probe. |
254
- | `sglang` | SGLang probe. |
255
- | `lmstudio` | LM Studio probe. |
256
- | `koboldcpp` | KoboldCpp probe. |
257
- | anything else | Opts the provider in, but no probe runs. `/modelscout` shows the probe as unresolved for that provider. |
258
-
259
- ### Examples
409
+ #### Provider settings
410
+
411
+ | Field | Description |
412
+ | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
413
+ | `package` | `@opencode/ai/providers/openai-compatible`. The plugin also accepts `aisdk:@ai-sdk/openai-compatible` and `@ai-sdk/openai-compatible`. The package matters for auto-eligibility and for reasoning-effort variants. |
414
+ | `settings.baseURL` | The OpenAI-compatible API root OpenCode sends chat requests to, usually ending in `/v1`. Required. Discovery finds the model list with or without the trailing `/v1`. |
415
+ | `settings.apiKey` | Sent as `Authorization: Bearer <key>` on discovery requests when the provider has no connected key. A key connected in OpenCode (stored or from the environment) takes precedence, as it does for chat. |
416
+ | `settings.probe` | `auto` or a probe ID from the table below. |
417
+ | `headers` | Sent with every discovery and probe request. An `Authorization` header here replaces the one built from the API key. |
418
+
419
+ | `settings.probe` | Effect |
420
+ | ---------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
421
+ | `auto` | Fingerprint the server and run the matching probe. If nothing matches, models are still listed. |
422
+ | `actualyze` | Actualyze probe. |
423
+ | `ollama` | Ollama probe; also the right choice for llama.cpp and LocalAI. |
424
+ | `omlx` | oMLX probe. |
425
+ | `vllm` | vLLM probe. |
426
+ | `tgi` | Text Generation Inference probe. |
427
+ | `sglang` | SGLang probe. |
428
+ | `lmstudio` | LM Studio probe. |
429
+ | `koboldcpp` | KoboldCpp probe. |
430
+ | anything else | Opts the provider in, but no probe runs. `/modelscout` and `/actualyze` flag the value as an unknown probe and list the accepted ones. |
431
+
432
+ #### Examples
260
433
 
261
434
  Several local servers next to each other:
262
435
 
@@ -264,7 +437,7 @@ Several local servers next to each other:
264
437
  {
265
438
  "providers": {
266
439
  "studio-omlx": {
267
- "name": "oMLX",
440
+ "name": "Studio oMLX",
268
441
  "package": "@opencode/ai/providers/openai-compatible",
269
442
  "settings": {
270
443
  "baseURL": "http://localhost:8000/v1",
@@ -273,7 +446,7 @@ Several local servers next to each other:
273
446
  }
274
447
  },
275
448
  "my-ollama": {
276
- "name": "Ollama (scout)",
449
+ "name": "GPU box Ollama",
277
450
  "package": "@opencode/ai/providers/openai-compatible",
278
451
  "settings": {
279
452
  "baseURL": "http://gpu-box.local:11434/v1",
@@ -300,6 +473,7 @@ A gateway that needs an extra header:
300
473
  {
301
474
  "providers": {
302
475
  "team-gateway": {
476
+ "name": "Team gateway",
303
477
  "package": "@opencode/ai/providers/openai-compatible",
304
478
  "headers": { "X-Team": "research" },
305
479
  "settings": {
@@ -312,46 +486,35 @@ A gateway that needs an extra header:
312
486
  }
313
487
  ```
314
488
 
315
- ### Plugin options
489
+ ### What the plugin sets on each model
316
490
 
317
- Pass these through the object form of the `plugins` entry.
318
-
319
- | Option | Description | Default |
320
- | ------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
321
- | `timeoutMs` | Time budget for one provider's discovery: model list, fingerprinting, and probe together. | `15000`. Values are clamped to 1000 through 60000. |
322
- | `refreshIntervalMs` | How often each provider is rediscovered in the background. `0` or a negative value turns periodic refresh off. | `600000` (10 minutes). Positive values are clamped to 60000 through 86400000. |
323
-
324
- Values that are not numbers are ignored and the default applies.
325
-
326
- ## What Scout Sets on Each Model
491
+ The plugin adds the models a server lists that are not already declared for
492
+ that provider. For each one it writes:
327
493
 
328
- Scout adds the models a server lists that are not already declared for that
329
- provider. For each one it writes:
494
+ | Field | Value |
495
+ | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
496
+ | `name` | A readable name derived from the model ID. |
497
+ | `family` | From the probe, otherwise from a models.dev match. |
498
+ | `limit.context` | From the probe, otherwise OpenCode's default of 200000. |
499
+ | `limit.output` | From the probe, capped at the context window when the probe reports one too. When no source reports it, `0`: OpenCode treats that as unknown and asks for up to 32,000 output tokens, fewer when the prompt leaves less room in the window. |
500
+ | `capabilities.tools` | From the probe, including an explicit `false`; otherwise from models.dev; otherwise `true`. |
501
+ | `capabilities.input` | `text`, plus `image`, `pdf`, `audio`, and `video` where the probe or models.dev reports them. A model with unknown image support stays text-only. |
502
+ | `capabilities.output` | `["text"]`. |
503
+ | `variants` | `low`, `medium`, and `high`, each setting `reasoningEffort`, for reasoning models on the openai-compatible package. Reasoning comes from the probe or from a models.dev match that has effort variants. Actualyze models get none. |
504
+ | `cost` | Prices the probe reports, in USD per million tokens. A missing cache price becomes `0`. Without reported prices, `cost` is empty. |
505
+ | `time.released` | The Actualyze `created` time; `0` for other servers. |
506
+ | `enabled` | `false` for embedding models, which keeps them out of the picker. `/modelscout` lists them when its type filter includes embeddings. |
330
507
 
331
- | Field | Value |
332
- | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
333
- | `name` | A readable name derived from the model ID. |
334
- | `family` | From the probe, otherwise from a models.dev match. |
335
- | `limit.context` | From the probe, otherwise OpenCode's default of 200000. |
336
- | `limit.output` | From the probe, capped at the context limit. When no source reports it, `0`, which OpenCode reads as "unknown" and sizes the output budget to the room the prompt leaves in the context window. |
337
- | `capabilities.tools` | From the probe, including an explicit `false`; otherwise from models.dev; otherwise `true`. |
338
- | `capabilities.input` | `text`, plus `image`, `pdf`, `audio`, and `video` where the probe or models.dev reports them. A model with unknown image support stays text-only. |
339
- | `capabilities.output` | `["text"]`. |
340
- | `variants` | `low`, `medium`, and `high`, each setting `reasoningEffort`, for reasoning models on the openai-compatible package. Reasoning comes from the probe or from a models.dev match that has effort variants. Actualyze models get none. |
341
- | `cost` | Prices the probe reports, in USD per million tokens. A missing cache price becomes `0`. Without reported prices, `cost` is empty. |
342
- | `time.released` | The Actualyze `created` time; `0` for other servers. |
343
- | `enabled` | `false` for embedding models, which keeps them out of the picker. `/modelscout` lists them when its type filter includes embeddings. |
508
+ A model counts as an embedding model when the probe says so, or, when the
509
+ probe reports no model type, when its ID contains `embed`. The plugin does
510
+ not set parameter size, quantization, file size, or temperature support on
511
+ the model; `/modelscout` shows them in its details.
344
512
 
345
- A model counts as an embedding model when the probe says so or, without probe
346
- data, when its ID contains `embed`. Scout does not set parameter size,
347
- quantization, file size, or temperature support on the model;
348
- `/modelscout` shows them in its details.
349
-
350
- ### Declared models are never modified
513
+ #### Declared models are never modified
351
514
 
352
515
  A model ID that already exists for the provider, because you declared it in
353
516
  config or because it comes from the provider's models.dev entry, is left
354
- exactly as it is. Scout adds the other served models around it.
517
+ exactly as it is. The plugin adds the other served models around it.
355
518
 
356
519
  ```json
357
520
  {
@@ -377,7 +540,7 @@ Here `qwen3:30b` keeps your name and limits, and every other model the server
377
540
  serves is added with discovered metadata. In `/modelscout`, the Evidence
378
541
  screen for `qwen3:30b` gives its origin as declared in your config.
379
542
 
380
- ## Supported Servers
543
+ ### Supported servers
381
544
 
382
545
  | Server | Probe | Status | What it reports |
383
546
  | ------------- | ----------- | -------- | --------------------------------------------------------------------------------------- |
@@ -397,10 +560,10 @@ is API-compatible according to its source code but has not been run against a
397
560
  live instance. An Untested probe was written from the server's API
398
561
  documentation, and reports from people running those servers are welcome.
399
562
 
400
- With `"probe": "auto"`, scout identifies the server in this order:
563
+ With `"probe": "auto"`, the plugin identifies the server in this order:
401
564
 
402
- 1. Any model entry whose `owned_by` is exactly `actualyze` (or `atlas`, from
403
- older deployments) selects the Actualyze probe.
565
+ 1. Any model entry whose `owned_by` is exactly `actualyze` selects the
566
+ Actualyze probe.
404
567
  2. Every entry reporting the same known owner selects that server: `omlx`,
405
568
  `vllm`, `sglang`, `llamacpp`, `koboldcpp`, or `library` for Ollama.
406
569
  3. Entries with `aliases`, `tags`, or `status` fields point to llama.cpp.
@@ -410,129 +573,44 @@ With `"probe": "auto"`, scout identifies the server in this order:
410
573
  An Ollama server whose models do not all report the owner `library` is not
411
574
  detected. Set `"probe": "ollama"` for it.
412
575
 
413
- ## Actualyze
414
-
415
- Actualyze serves its model catalog through an OpenAI-compatible endpoint, and
416
- each `/v1/models` entry carries the platform's full metadata.
417
-
418
- ### The built-in provider
419
-
420
- Scout adds this provider to OpenCode's catalog:
421
-
422
- | Field | Value |
423
- | ------------------ | ------------------------------------------ |
424
- | ID | `actualyze` |
425
- | Name | Actualyze |
426
- | `package` | `@opencode/ai/providers/openai-compatible` |
427
- | `settings.baseURL` | `https://app.actualyze.ai/openai/v1` |
428
- | `settings.probe` | `actualyze` |
429
-
430
- It also registers an Actualyze integration, which is what `/connect` and
431
- `opencode auth login actualyze` offer. The integration takes a stored API key
432
- or the `ACTUALYZE_API_KEY` environment variable of the background service.
433
- Discovery and chat both use that key. The integration's ID is `actualyze`,
434
- the same as the provider's, so a `providers.actualyze` config entry and
435
- `opencode auth login actualyze` both reach the integration the provider reads
436
- its key from.
437
-
438
- Until the integration has a key, OpenCode hides the provider, so installing
439
- the plugin without Actualyze changes nothing in the model picker.
440
-
441
- ### Another Actualyze environment
442
-
443
- To use a different deployment, set only its base URL. Your config is merged
444
- over the built-in provider field by field, so the name, package, probe, and
445
- key handling stay as they are:
446
-
447
- ```json
448
- {
449
- "providers": {
450
- "actualyze": {
451
- "settings": {
452
- "baseURL": "https://actualyze.example.com/openai/v1"
453
- }
454
- }
455
- }
456
- }
457
- ```
458
-
459
- Any `providers.actualyze` entry in your config makes OpenCode list the
460
- provider even without a key. Discovery then runs without credentials, and
461
- `/modelscout` and `/actualyze` show the endpoint's error until you add one.
462
- Add the key with `/actualyze`, `/connect`, or `opencode auth login actualyze`
463
- as usual: the entry does not create a second Actualyze integration. A `settings.apiKey` in the entry also
464
- works, without connecting the integration. A connected key takes precedence
465
- over `settings.apiKey` for both discovery and chat, so the two always use the
466
- same key.
467
-
468
- If a models.dev catalog or another plugin already defines an `actualyze`
469
- provider, scout leaves that provider as it is and does not add its own. When
470
- an `actualyze` integration also exists, as a catalog registers one with its
471
- provider, scout does not register its own, so `/connect` lists Actualyze once.
472
- Otherwise scout still registers the `actualyze` integration. A provider that
473
- another plugin defined with `"activation": "auto"` and no integration of its
474
- own then depends on that integration: OpenCode hides it until a key is
475
- connected there. Scout does not discover such a provider by default, because
476
- its ID is one OpenCode already knows; add `"probe": "actualyze"` to its
477
- `settings` in your config to opt in.
478
-
479
- ### How the probe reads Actualyze
480
-
481
- - **Detection.** In auto mode, one entry with `owned_by` set exactly to
482
- `actualyze` or `atlas` is enough to select the probe, even in a catalog
483
- that mixes owners. The probe then reads only the Actualyze-owned entries;
484
- the rest are listed and enriched from models.dev as usual. With
485
- `"probe": "actualyze"` every listed model is treated as an Actualyze model.
486
- `"probe": "atlas"` still works as a deprecated alias.
487
- - **List first.** The probe reads metadata straight from the `/v1/models`
488
- entries. It requests `GET /v1/models/{id}` only for owned entries that lack
489
- the full metadata, which happens on older deployments.
490
- - **Fields.** `context_window` and `max_output_tokens` become the limits.
491
- Capability flags (`vision`, `tool_use`, `thinking`, `thinking_adaptive`,
492
- `temperature`, `document`, `audio`, `video`) are three-valued: `true` and
493
- `false` are definitive, `null` means unknown. `modalities.input` is used
494
- for input modalities when present. `created` becomes the release time.
495
- - **Cost.** `cost.input`, `cost.output`, `cost.cache_read`, and
496
- `cost.cache_write` are USD per million tokens. OpenCode's `cost` records a
497
- missing cache price as `0`, and `/modelscout` shows it as unknown. A model
498
- without `cost` gets no prices.
499
- - **No effort variants.** Actualyze's chat endpoint does not pass
500
- `reasoning_effort` on to the upstream model, so reasoning models from
501
- Actualyze get no `low`/`medium`/`high` variants.
502
-
503
576
  ## `/modelscout` Command
504
577
 
505
578
  Type `/modelscout`, or pick **Model Scout** from the command palette. It opens
506
- a browser of the models scout's providers serve, without sending anything to
507
- a model. The dialog appears at once and fills in when OpenCode's model lists
508
- and scout's discovery catalog arrive. It updates in place when a discovery
509
- run starts or settles and when OpenCode's model catalog changes.
510
-
511
- The list covers every provider scout discovers, plus any OpenCode provider
512
- that looks like a discovery target: one with `settings.baseURL` and either
513
- `settings.probe` or the openai-compatible package. Providers are sorted by
514
- name, and models within each provider by name until you change the sort.
579
+ a browser of the models the plugin's providers serve, without sending
580
+ anything to a model. The dialog appears at once and fills in when OpenCode's
581
+ model lists and the plugin's discovery catalog arrive. It updates in place
582
+ when a discovery run starts or settles and when OpenCode's model catalog
583
+ changes.
584
+
585
+ The list covers every provider the plugin discovers, plus any OpenCode
586
+ provider that looks like a discovery target: one with `settings.baseURL` and
587
+ either `settings.probe` or the openai-compatible package. Providers are
588
+ sorted by name, and models within each provider by name until you change the
589
+ sort.
515
590
 
516
591
  ### Reading the list
517
592
 
518
593
  ```
519
- ▾ Actualyze 4 models ● ready
520
- Claude Haiku 4.5 200K T I R $1/$5
521
- ● Claude Sonnet 4.5 200K T I R $3/$15
522
- GPT OSS 120B 131K T · R $0.15/$0.60
523
- Mock Tiered Pro 400K T I R $3/$15+
524
- ▾ Studio oMLX 2 models ● ready
594
+ ▾ Actualyze 4 models ● ready
595
+ Claude Haiku 4.5 200K T I R $1/$5
596
+ ● Claude Sonnet 4.5 200K T I R $3/$15
597
+ GPT 5 400K T I R $1.25/$10.00
598
+ GPT OSS 120B 131K T · R $0.15/$0.60
599
+ ▾ Studio oMLX 2 models ● ready
525
600
  Gemma 3 12B ~200K · I ·
526
601
  Qwen3 Coder 30B 262K t · ·
527
- ▸ Team gateway 3 models ▲ key rejected
602
+ ▸ Team gateway 3 models ▲ key rejected
528
603
  ```
529
604
 
530
605
  - **Provider headers** show the model count, as `visible/total` while search
531
606
  or filters hide some, and the discovery status: `● ready`, `○ checking`
532
- while discovery runs, `○ resolving` while scout looks up which key to use,
533
- `○ waiting` until discovery has a result for the current key, or a failure
534
- such as `▲ key rejected`, `▲ rate limited`, or `▲ unreachable`. A failing
535
- provider keeps the models from its last good discovery.
607
+ while discovery runs, `○ resolving` while the plugin looks up which key to
608
+ use, `○ waiting` until discovery has a result for the current key, or a
609
+ failure such as `▲ key rejected`, `▲ rate limited`, or `▲ unreachable`. A
610
+ failing provider keeps the models from its last good discovery.
611
+ `▲ unknown probe` means `settings.probe` names no probe: the models are
612
+ listed, but no probe fills in their limits, prices, or capabilities. A
613
+ failure shows in its place until it clears.
536
614
  - **`●`** before a model name marks the model the prompt uses now. A colored
537
615
  band marks the selected row; while the search box has focus, a `▌` marks
538
616
  it instead.
@@ -540,15 +618,18 @@ name, and models within each provider by name until you change the sort.
540
618
  reported one and OpenCode uses its default of 200,000 tokens.
541
619
  - **`T I R`** stand for tool calls, image input, and reasoning. An uppercase
542
620
  letter is reported by the server, your config, or OpenCode. A lowercase
543
- letter is assumed from an OpenCode default or inferred from models.dev or
544
- the model name. `·` means not reported or not supported.
621
+ letter is assumed from an OpenCode default or inferred from a models.dev
622
+ match. `·` means not reported or not supported.
545
623
  - **Prices** are USD per million tokens, input/output, and `?` marks an
546
624
  unknown side. When one side shows cents, so does the other. A trailing `+`
547
625
  means the price rises above a context size; the details list every tier.
626
+ Only models declared with tiered prices in your config or a models.dev
627
+ entry have tiers.
548
628
 
549
629
  The title line counts providers and models and says how many providers need
550
- attention. Embedding models are hidden by default, and the filter line says
551
- how many, for example `1 embedding hidden`.
630
+ attention: a failed discovery or an unknown probe. Embedding models are
631
+ hidden by default, and the filter line says how many, for example
632
+ `1 embedding hidden`.
552
633
 
553
634
  At 120 columns and wider, a preview of the selected row's details sits
554
635
  beside the list. The preview does not scroll: when it is cut off, its last
@@ -557,9 +638,9 @@ selected model sits under the list instead (facts that do not fit are
557
638
  counted as `+N`). At any width, `i` opens the details on their own screen,
558
639
  across the whole dialog. Details and the key list that run longer than the
559
640
  dialog scroll (the key list by whole entries), with `↑ N more` and
560
- `↓ N more` at the edges. Resizing the terminal switches between the two layouts without
561
- closing the dialog. The dialog takes at most `rows - 4` rows, so it leaves
562
- room above and below it.
641
+ `↓ N more` at the edges. Resizing the terminal switches between the two
642
+ layouts without closing the dialog. The dialog takes at most `rows - 4`
643
+ rows, so it leaves room above and below it.
563
644
 
564
645
  The first open selects the prompt's current model, or the first chat model
565
646
  when the current one is not listed. Search, filters, sort, collapsed
@@ -595,8 +676,10 @@ While the search box has focus, every key you type goes into the search.
595
676
  Keys held with `ctrl`, `alt`, or `cmd` always go to OpenCode.
596
677
 
597
678
  The footer shows the keys of the current view and dims the ones that do not
598
- apply to the selection. In a narrow dialog it drops hints from the right,
599
- but `keys ?` and `close esc` always stay.
679
+ apply to the selection. When the dialog is too narrow for every hint, the
680
+ footer leaves out the ones that do not fit and keeps the rest in their usual
681
+ order. `close esc` always stays, and `keys ?` stays except while you type a
682
+ search or read the key list.
600
683
 
601
684
  ### Search, filters, and sort
602
685
 
@@ -628,22 +711,25 @@ prices and every context tier), and the capabilities, grouped as supported,
628
711
  assumed, inferred, not supported, and not reported. Then come the provider
629
712
  and its endpoint, the family, parameter count, quantization, and size. A
630
713
  value no source reported says so in words: "Not reported; OpenCode uses
631
- 200,000" for the context, and "Not reported; OpenCode fits output to the
632
- remaining context" for the output limit.
714
+ 200,000" for the context, and "Not reported; OpenCode asks for up to 32,000,
715
+ fewer if the prompt leaves less room" for the output limit.
633
716
 
634
717
  Provider details give the discovery status and when it was last checked,
635
- and after a failure what went wrong and what to do about it. They also show
636
- the server type (the probe, or that it was detected automatically), the
637
- number of chat and embedding models, how many models your config declares
638
- and scout leaves unchanged, which key discovery uses (a connected key,
639
- `settings.apiKey`, the provider's headers, or none), and when `r` can run
640
- again.
718
+ and after a failure what went wrong and what to do about it. For an unknown
719
+ probe they name the configured value and list the values `settings.probe`
720
+ accepts, for example
721
+ `Unknown probe "my-probe"; use auto or one of: actualyze, ollama, omlx, …`.
722
+ They also show the server type (the probe, or that it was detected
723
+ automatically), the number of chat and embedding models, how many models
724
+ your config declares and the plugin leaves unchanged, which key discovery
725
+ uses (a connected key, `settings.apiKey`, the provider's headers, or none),
726
+ and when `r` can run again.
641
727
 
642
728
  ### Evidence
643
729
 
644
730
  `d` shows where each value comes from. For a model it is a table of every
645
731
  field with its value and source, followed by the model's origin (discovered
646
- by scout, declared in your config, or known to OpenCode only), the
732
+ by the plugin, declared in your config, or known to OpenCode only), the
647
733
  configured and resolved probe, the endpoint origin, and any conflicts
648
734
  between sources. For a provider it lists the model-list and probe attempts,
649
735
  the probe, the endpoint, the key source, the last good and last attempted
@@ -657,7 +743,7 @@ status and retry time.
657
743
  | `server list` | The server's model list |
658
744
  | `models.dev` | A models.dev match |
659
745
  | `heuristic` | Inferred from the model ID |
660
- | `scout default` | Scout's default, such as text input |
746
+ | `scout default` | The plugin's default, such as text input |
661
747
  | `OpenCode default` | OpenCode's default value, not an observation |
662
748
  | `OpenCode` | OpenCode's model list, for a provider without discovery |
663
749
 
@@ -666,17 +752,17 @@ Endpoint origins never include credentials, paths, or query strings.
666
752
  ### Choosing a model
667
753
 
668
754
  `enter` on a model, or `m`, opens OpenCode's model picker in place of the
669
- browser with its search filled in, so the model is the highlighted first
670
- result. Press `enter` again to select it; for a model with effort variants,
671
- OpenCode may then ask which one. The choice happens in the picker because
672
- plugins cannot set the prompt's model.
755
+ browser with its search filled in, so the model is usually the highlighted
756
+ first result. Press `enter` again to select it; for a model with effort
757
+ variants, OpenCode may then ask which one. The choice happens in the picker
758
+ because plugins cannot set the prompt's model.
673
759
 
674
760
  The search is the provider's name and the model's name as the picker shows
675
761
  them, for example `Actualyze GPT OSS 120B`. The picker matches provider names
676
762
  only while at least one integration has a connection, so without one the
677
- search is the model's name alone. If the picker's search field
678
- does not appear within a second, or you press a key before scout fills it
679
- in, the picker stays open without a search, as it would from `/models`.
763
+ search is the model's name alone. If the picker's search field does not
764
+ appear within a second, or you press a key before the plugin fills it in,
765
+ the picker stays open without a search, as it would from `/models`.
680
766
 
681
767
  `enter` and `m` are unavailable for embedding models, for a model OpenCode
682
768
  does not list yet, for a deprecated model, which the picker leaves out, and
@@ -700,15 +786,16 @@ The picker orders its results, so check the highlighted row before you press
700
786
 
701
787
  `y` copies `provider/model`, the form `opencode run --model` takes, and `Y`
702
788
  copies the raw model ID. The text goes to the terminal through the OSC 52
703
- escape sequence, and the notice line says `Copy sent to terminal`. Terminals
704
- do not confirm OSC 52, and some ignore it or need it turned on. When OpenCode
705
- reports that the terminal does not support OSC 52, the browser shows the text
706
- in full under the notice for 30 seconds instead, so you can select it.
789
+ escape sequence, and the notice line says `Copy sent to terminal: <text>`.
790
+ Terminals do not confirm OSC 52, and some ignore it or need it turned on.
791
+ When OpenCode reports that the terminal does not support OSC 52, the browser
792
+ shows the text in full under the notice for 30 seconds instead, so you can
793
+ select it.
707
794
 
708
795
  ### Refreshing
709
796
 
710
- `r` asks scout's server half to rediscover the selected provider, and `R`
711
- every provider. Discovery for one provider and key starts at most once a
797
+ `r` asks the plugin's server half to rediscover the selected provider, and
798
+ `R` every provider. Discovery for one provider and key starts at most once a
712
799
  minute, and never before a time the server asked for with `Retry-After` or
713
800
  `X-RateLimit-Reset` (at most one hour ahead). A refresh inside that window
714
801
  is skipped with a countdown, for example
@@ -717,9 +804,11 @@ the provider's details show the same wait.
717
804
 
718
805
  ### Other states
719
806
 
720
- - **Loading.** The dialog says it is reading models from OpenCode and scout.
721
- - **OpenCode's lists did not load.** The error is shown, and `r` reads them
722
- again.
807
+ - **Loading.** The dialog reads
808
+ `○ Reading models from OpenCode and scout…`.
809
+ - **OpenCode's lists did not load.** The dialog reads
810
+ `▲ Could not load models from OpenCode.` with the error, and `r` reads the
811
+ lists again.
723
812
  - **No providers.** A card explains how to connect Actualyze (`a`) or add
724
813
  another OpenAI-compatible server.
725
814
  - **No matches.** `x` clears search and filters, and `f` changes the
@@ -727,10 +816,10 @@ the provider's details show the same wait.
727
816
  - **A provider without models.** A note under its header says whether
728
817
  discovery is still checking, the model list failed, the server returned no
729
818
  models (`r` refreshes), or only hidden embedding models matched.
730
- - **Scout's server half does not answer.** If the catalog request fails or
731
- times out after 3 seconds, the browser shows OpenCode's own model list
819
+ - **The plugin's server half does not answer.** If the catalog request fails
820
+ or times out after 3 seconds, the browser shows OpenCode's own model list
732
821
  with a notice such as
733
- `▲ Discovery details unavailable: scout's server half did not answer.`
822
+ `▲ Discovery details unavailable: scout's server half did not answer. Showing OpenCode's model list.`
734
823
  Discovery status, failure details, evidence sources, and refresh are
735
824
  missing in that mode.
736
825
  - **The server half fails to load.** OpenCode does not load the TUI half
@@ -738,151 +827,111 @@ the provider's details show the same wait.
738
827
  - **The browser cannot be built.** The command shows a plain, scrollable list
739
828
  of the same models and reports the error in a toast.
740
829
 
741
- ## `/actualyze` Command
830
+ ## Installation
742
831
 
743
- `/actualyze` takes you from no key to a working Actualyze catalog without
744
- leaving OpenCode. Open it with `/actualyze`, pick **Actualyze** from the
745
- command palette, or press `a` in `/modelscout`.
832
+ ```bash
833
+ opencode plugin add opencode-actualyze
834
+ ```
746
835
 
747
- The header shows the Actualyze wordmark and the endpoint's host,
748
- `app.actualyze.ai` for the built-in provider. When
749
- `providers.actualyze.settings.baseURL` points anywhere else, the header adds
750
- a `custom endpoint` badge, and every app link uses that endpoint's origin.
751
- The line under the header says where things stand, and names the key in
752
- use: the connection's label in quotes, `ACTUALYZE_API_KEY` for the
753
- environment variable, or `settings.apiKey`.
836
+ This installs the package and adds it to your global OpenCode configuration.
837
+ `opencode plugin update opencode-actualyze` updates it, and
838
+ `opencode plugin remove opencode-actualyze` takes it out again.
754
839
 
755
- An Actualyze inference key can read the model catalog and nothing about the
756
- account: no identity, usage, spend, or budget. So `/actualyze` reports
757
- "Catalog accessible" when the model list answered for the key, and never
758
- claims that chat works. A read-only key, for example, lists models and is
759
- refused on every chat request.
840
+ To configure it by hand, list it in the `plugins` array of `opencode.json`:
760
841
 
761
- ### States
842
+ ```json
843
+ {
844
+ "plugins": ["opencode-actualyze"]
845
+ }
846
+ ```
762
847
 
763
- | Status line | What it means | What to do |
764
- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
765
- | `○ Not connected` | OpenCode has no Actualyze key. | Create a key in the app, then press `k` and paste it. The card lists the steps. |
766
- | `○ Saving key…` | You submitted a key and OpenCode has not confirmed it yet. | Wait. Closing the dialog does not undo a completed save. |
767
- | `▲ Save not confirmed` | Saving failed or took longer than 15 seconds. OpenCode may have stored the key anyway. | Check with `c` before trying again with `k`. |
768
- | `○ Checking the current connection…` | The key is saved and scout has no result for it yet. After 20 seconds the line reads "Still checking the current connection…". | Wait. No inference request is sent. |
769
- | `○ Checking the connection…` | A key is connected and scout is still resolving it. | Wait. |
770
- | `○ Loading models…` | The first model list for this key is on its way. | Wait. |
771
- | `● Catalog accessible · key "Work" · 11 models · checked 2 min ago` | The model list answered. The count is chat models, as in `/modelscout`; the filter row reports hidden embeddings. | Browse them; `enter` on a model opens the model picker with it highlighted. |
772
- | `▲ No models for this key` | The catalog answered with an empty list: the key works, but its team has no model access yet. | Ask a workspace admin. `y` copies the Catalog link. |
773
- | `▲ Key rejected (401)` | Actualyze answers this way for a revoked or expired key, a key without the inference scope, or a key from another Actualyze environment. | `k` for another key, `y` to copy the API Keys link, `c` for connections. |
774
- | `▲ Access denied (403)` | Actualyze refused the model list request for this key. | Check the key's permissions and model access with your administrator, or use `k` for another key. |
775
- | `▲ Budget or entitlement blocked (402)` | Actualyze did not allow the model list request. The key cannot read a balance or reset date. | `y` copies the Budgets link; that page may need an admin role. |
776
- | `▲ Catalog rate limited (429)` | The model list is rate limited. This is a catalog limit, not an inference quota. The footer shows the wait: `retry (42 s) r`. | Retry with `r` once the wait ends; otherwise Model Scout checks again on its next scheduled refresh, or when settings or the key change. |
777
- | `▲ Could not reach the endpoint` | The connection failed. The header shows the endpoint. | Check the network, VPN, proxy, and `providers.actualyze.settings.baseURL`, then retry with `r`. |
778
- | `▲ Endpoint did not answer in time` | The model list request timed out. | Check the network or the endpoint, then retry with `r`. |
779
- | `▲ Actualyze server error (503)` | Actualyze failed to list its models. | Retry with `r`. |
780
- | `▲ No model list at this endpoint (404)` | The base URL points at the wrong path. | Make `settings.baseURL` end in `/openai/v1`. |
781
- | `▲ Unexpected answer (…)` | Another HTTP status, or an answer that is not a model list. | Check `settings.baseURL`. |
782
- | `▲ Discovery was interrupted` or `▲ Discovery failed` | The check did not finish. | It runs again on the next refresh; `r` retries now. |
783
- | `▲ Discovery status unavailable` | Scout's server half did not answer, so only the connection OpenCode reports is known. | `k` and `c` still work; `r` reads the catalog again. |
784
- | `○ Not managed by Model Scout` | Another plugin or a models.dev catalog defines the `actualyze` provider, so scout does not discover it. | Add `"probe": "actualyze"` to `providers.actualyze.settings` to opt in. |
848
+ To pass [plugin options](#plugin-options), use the object form:
785
849
 
786
- The glyph carries the state's color; the words stay in the theme's text
787
- color. When the line is too narrow, the age goes first and then the key
788
- label, whole, so the line never ends in a cut word. Each card under the
789
- status line starts with a title and gives the details below it.
850
+ ```json
851
+ {
852
+ "plugins": [
853
+ {
854
+ "package": "opencode-actualyze",
855
+ "options": { "refreshIntervalMs": 1800000 }
856
+ }
857
+ ]
858
+ }
859
+ ```
790
860
 
791
- After a failure, a key that had a good catalog before keeps it: the card sits
792
- above the models from the last good check. When the key comes from
793
- `settings.apiKey` or `ACTUALYZE_API_KEY`, the failure card says so, and adds
794
- that a key connected with `k` takes precedence. When the provider's `headers` carry
795
- the key (`Authorization` or `X-Actualyze-Api-Key`), a notice says that
796
- discovery uses those headers, not the connected key.
861
+ The package contains a server plugin and a TUI plugin. OpenCode loads the TUI
862
+ half automatically together with the server half, so there is nothing else to
863
+ add for `/actualyze` and `/modelscout`.
797
864
 
798
- ### Keys in `/actualyze`
865
+ ### Plugin options
799
866
 
800
- | Key | Action |
801
- | ----- | ----------------------------------------------------------------------------------- |
802
- | `k` | Connect a key: "connect key" without a connection, "another key" with one |
803
- | `c` | Open OpenCode's connections; pick Actualyze there to switch, rename, or remove keys |
804
- | `l` | Open the [links screen](#links) |
805
- | `y` | On a card, copy the link it names; in the model list, copy `provider/model` |
806
- | `r` | Check the catalog again; during a wait the hint is dimmed and reads "retry (N s)" |
807
- | `b` | Open `/modelscout` |
808
- | `?` | List the keys |
809
- | `esc` | Close |
867
+ Pass these through the object form of the `plugins` entry.
810
868
 
811
- While a card fills the dialog, only the keys it offers, `?`, and `esc` work.
812
- The footer lists the card's keys in one order: the key action, retry, copy
813
- link, links, connections, all providers, then keys. When the footer runs out
814
- of room it leaves out the hints that do not fit and keeps any later one that
815
- does; the card then lists the left-out keys in an action line at its end, in
816
- the same order, so every key shows once. `?` lists them all. A card longer
817
- than the dialog shows `↓ N more` and scrolls with `↑`, `↓`, `pgup`, `pgdn`,
818
- `home`, and `end`; the footer adds `scroll ↑↓` after the card's keys when
819
- there is room for all of them.
869
+ | Option | Description | Default |
870
+ | ------------------- | -------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
871
+ | `timeoutMs` | Time budget for one provider's discovery: model list, fingerprinting, and probe together. | `15000`. Values are clamped to 1000 through 60000. |
872
+ | `refreshIntervalMs` | How often each provider is rediscovered in the background. `0` or a negative value turns periodic refresh off. | `600000` (10 minutes). Positive values are clamped to 60000 through 86400000. |
820
873
 
821
- Once the catalog is accessible, the model list works like `/modelscout`
822
- limited to Actualyze, without a provider header or provider filter. `r`
823
- refreshes Actualyze; there is no `R`. The footer shows `k` and `l` when
824
- there is room, and `?` lists `k`, `l`, `c`, and `b`.
874
+ Values that are not numbers are ignored and the default applies.
825
875
 
826
- `k` works only when the provider reads its key from the `actualyze`
827
- integration and that integration offers a plain key method. Otherwise the
828
- card points to `c`. Model Scout never deletes a key; removing one happens in
829
- OpenCode's connections.
876
+ ### Running from a checkout
830
877
 
831
- ### Entering a key
878
+ Building needs Node.js 22.18 or a later 22.x release, or Node.js 24 or later.
832
879
 
833
- `k` opens OpenCode's prompt titled **Actualyze API key**. The key is visible
834
- while you type, because OpenCode's prompt does not mask input. Press `enter`
835
- to submit. Model Scout trims the key, hands it once to OpenCode to store
836
- under the Actualyze integration, and drops it; it never stores, logs, or
837
- shows the key itself. `/actualyze` then comes back, shows "Saving key…",
838
- and checks the catalog with the new key.
880
+ ```bash
881
+ git clone https://github.com/actualyze-ai/opencode-actualyze.git
882
+ cd opencode-actualyze
883
+ npm install
884
+ npm run compile
885
+ ```
839
886
 
840
- Pressing `esc` in the prompt cancels and closes `/actualyze`. Submitting an
841
- empty prompt returns to `/actualyze` unchanged. If Model Scout reloads while
842
- the prompt is open, the prompt closes and nothing is saved; enter the key
843
- again with `/actualyze`. A key submitted after Model Scout reloaded, or after
844
- the project changed, is not saved either, and a toast says so. If you close
845
- `/actualyze` while OpenCode is still saving and the save is never confirmed,
846
- a toast says "OpenCode did not confirm the Actualyze key was saved".
887
+ Then point `plugins` at the build output directory:
847
888
 
848
- ### Links
889
+ ```json
890
+ {
891
+ "plugins": ["/absolute/path/to/opencode-actualyze/dist"]
892
+ }
893
+ ```
849
894
 
850
- `l` lists Actualyze app pages on the provider's origin:
895
+ OpenCode loads a local plugin directory by looking for `server.js` and
896
+ `tui.js` inside it, so the entry is `dist`, not the repository root.
851
897
 
852
- | Link | Path |
853
- | --------------- | ------------------------------------ |
854
- | API Keys | `/account/settings?tab=security` |
855
- | Catalog | `/control/catalog?tab=consume` |
856
- | Budgets | `/management/budgets` |
857
- | Usage | `/observability?tab=inference` |
858
- | Troubleshooting | `/observability?tab=troubleshooting` |
898
+ ### The background service and environment variables
859
899
 
860
- `↑`, `↓`, `home`, and `end` choose a link, `enter` or `y` copies it the same
861
- way `/modelscout` copies (see [Copying](#copying)), and `backspace` or `l`
862
- returns. After a failure the matching link is selected first: API Keys for
863
- 401 and 403, Budgets for 402, and Troubleshooting for the rest. Budgets may
864
- need an admin role in Actualyze. Model Scout cannot open a browser, so copy
865
- the link and paste it into one. When `settings.baseURL` is not an http or
866
- https URL, there are no links, and the header says so.
900
+ OpenCode 2 runs plugins in one shared background service per user, not in the
901
+ terminal where you start `opencode`. Config substitutions such as
902
+ `{env:LOCAL_LLM_KEY}` therefore read the service's environment, and a variable
903
+ exported in your shell is not visible to them. Set it on the service and
904
+ restart it:
905
+
906
+ ```bash
907
+ opencode service set env LOCAL_LLM_KEY <value>
908
+ opencode service restart
909
+ ```
910
+
911
+ Alternatively, read the key from a file with `{file:~/path/to/key}`. A
912
+ relative `{file:}` path resolves against the directory of the config file.
867
913
 
868
914
  ## Caching and Refresh
869
915
 
870
916
  - **Stored inventories.** Each successful discovery is saved in OpenCode's
871
917
  plugin storage, keyed by a hash of the provider ID, normalized base URL,
872
918
  probe selection, API key, and headers. Unless discovery used
873
- `settings.apiKey`, the key also covers the connected key scout used, or
874
- its absence. The stored data holds model IDs and metadata, never keys or
875
- headers. Scout keeps the 128 most recent entries.
876
- - **Startup.** A provider gets its stored models once scout has looked up
877
- the key that project uses (the connected key, else `settings.apiKey`) and
878
- found the inventory discovered with it. That lookup runs right after the
879
- plugin loads and makes no network request.
880
- - **Background refresh.** Scout rediscovers when the plugin loads, when
881
- configuration, providers, plugins, integrations, or credentials change, on
882
- the `refreshIntervalMs` schedule, and on `r` or `R` in `/modelscout` and
883
- `r` in `/actualyze`. Discovery for one provider and credential starts at
884
- most once a minute. Projects open at the same time share one discovery run
885
- per identical provider and credential.
919
+ `settings.apiKey`, the key also covers the connected key the plugin used,
920
+ or its absence. The stored data holds model IDs and metadata, never keys
921
+ or headers. The plugin keeps the 128 most recent entries.
922
+ - **Startup.** A provider gets its stored models once the plugin has looked
923
+ up the key that project uses (the connected key, else `settings.apiKey`)
924
+ and found the inventory discovered with it. That lookup runs right after
925
+ the plugin loads and makes no network request.
926
+ - **Background refresh.** The plugin checks its providers when it loads;
927
+ when configuration, providers, plugins, integrations, or credentials
928
+ change; and every `refreshIntervalMs`. A check starts discovery only for a
929
+ provider that has no inventory for its current endpoint and key, or, with
930
+ periodic refresh on, whose inventory is about `refreshIntervalMs` old. `r`
931
+ or `R` in `/modelscout` and `r` in `/actualyze` start discovery at once.
932
+ Discovery for one provider and credential starts at most once a minute.
933
+ Projects open at the same time share one discovery run per identical
934
+ provider and credential.
886
935
  - **Retry times.** When the model list answers 429 or 503 with
887
936
  `Retry-After`, or 429 with `X-RateLimit-Reset`, no discovery with that
888
937
  credential starts before that time, at most one hour ahead. Another key
@@ -894,9 +943,9 @@ https URL, there are no links, and the header says so.
894
943
  removes that provider's discovered models until rediscovery finishes.
895
944
  - **Account switches.** When the active account for a provider changes, for
896
945
  example with `opencode auth switch`, its discovered models are removed at
897
- once and replaced by the inventory for the new credential, which scout
898
- discovers unless it already holds a fresh one. Models from one account
899
- never show under another.
946
+ once and replaced by the inventory for the new credential, which the
947
+ plugin discovers unless it already holds a fresh one. Models from one
948
+ account never show under another.
900
949
 
901
950
  ## Troubleshooting
902
951
 
@@ -913,81 +962,53 @@ https URL, there are no links, and the header says so.
913
962
  `"probe": "auto"` to its `settings` is the reliable opt-in, except for the
914
963
  IDs `ollama`, `lmstudio`, `vllm`, and `opencode`, which are never probed.
915
964
  - **The API key is empty.** `{env:...}` resolves in the background service.
916
- Set the variable with `opencode service set env` and restart the service, or
917
- use `{file:...}`.
918
- - **Models are listed twice.** A scout provider and a built-in local provider
919
- point at the same server. Disable the built-in one with
965
+ Set the variable with `opencode service set env` and restart the service,
966
+ or use `{file:...}`.
967
+ - **Models are listed twice.** A provider the plugin discovers and a built-in
968
+ local provider point at the same server. Disable the built-in one with
920
969
  `-opencode.provider.<name>` in `plugins`.
921
970
  - **The output limit is 0.** No source reported one. OpenCode treats `0` as
922
- unknown and sizes the output to the remaining context.
971
+ unknown and asks for up to 32,000 output tokens, fewer when the prompt
972
+ leaves less room.
923
973
 
924
974
  ## Moving from opencode-model-scout
925
975
 
926
- `opencode-model-scout` continues as `opencode-actualyze`, which is both the
927
- new package name and the new plugin ID. The `/modelscout` and `/actualyze`
928
- commands keep their names. Version 2 needs OpenCode 2; every published
929
- `opencode-model-scout` release is for OpenCode 1, so if you stay on OpenCode
930
- 1, see [Using OpenCode 1](#using-opencode-1) instead.
931
-
932
- On OpenCode 2, replace the package in your OpenCode configuration. `remove`
933
- takes the entry exactly as it is configured, including a version pin such as
934
- `opencode-model-scout@1.6.0`:
976
+ `opencode-actualyze` is the successor of `opencode-model-scout` and requires
977
+ OpenCode 2. Remove the old package from your configuration and add the new
978
+ one. `remove` takes the entry exactly as it is configured, including any
979
+ version pin:
935
980
 
936
981
  ```bash
937
982
  opencode plugin remove opencode-model-scout
938
983
  opencode plugin add opencode-actualyze
939
984
  ```
940
985
 
941
- To do it by hand, change `opencode-model-scout` to `opencode-actualyze` in
942
- the `plugins` array of `opencode.json`, including the `package` field of an
943
- entry in object form. An entry that points at a checkout of
986
+ To do it by hand, replace the `opencode-model-scout` entry in the `plugins`
987
+ array of `opencode.json` with `opencode-actualyze`; in object form, change
988
+ its `package` field. An entry that points at a checkout of
944
989
  `opencode-model-scout` should point at the `dist` directory of an
945
990
  `opencode-actualyze` checkout instead (see
946
- [Running from a checkout](#running-from-a-checkout)). Remove the old entry
947
- rather than keeping both: each one loads as a separate plugin.
948
-
949
- Anything that names the plugin by its ID needs the new ID. That includes a
950
- client of the plugin's RPC contract, which `opencode-actualyze/rpc` exports
951
- with the new ID.
952
-
953
- Saved discovery state starts fresh. OpenCode keeps scout's stored
954
- inventories under the plugin ID, so after the switch the discovered models
955
- appear once the first discovery finishes, usually within a few seconds.
956
-
957
- ## Using OpenCode 1
958
-
959
- Version 2 of this plugin does not load in OpenCode 1, and an unpinned install
960
- on OpenCode 1 picks up version 2 and fails. Pin the last 1.x release instead:
961
-
962
- ```bash
963
- opencode plugin opencode-actualyze@1.7.0
964
- ```
965
-
966
- Or add it by hand to both config files, `opencode.json`:
967
-
968
- ```json
969
- {
970
- "plugin": ["opencode-actualyze@1.7.0"]
971
- }
972
- ```
973
-
974
- and `tui.json`:
975
-
976
- ```json
977
- {
978
- "$schema": "https://opencode.ai/tui.json",
979
- "plugin": ["opencode-actualyze@1.7.0"]
980
- }
981
- ```
982
-
983
- The 1.x documentation is the
984
- [README in the 1.7.0 package](https://unpkg.com/opencode-actualyze@1.7.0/README.md).
985
-
986
- Coming from `opencode-model-scout` on OpenCode 1, replace its entry (for
987
- example `opencode-model-scout@1.6.0`) with `opencode-actualyze@1.7.0` in both
988
- `opencode.json` and `tui.json`, and remove the old entry so only one loads.
989
- In 1.7.0 the dialog is `/actualyze` instead of `/modelscout`, and a provider
990
- that set `"probe": "atlas"` needs `"probe": "actualyze"`.
991
+ [Running from a checkout](#running-from-a-checkout)). Keep only one of the
992
+ two: each entry loads as a separate plugin.
993
+
994
+ What changes:
995
+
996
+ - **Plugin ID.** The plugin ID is now `opencode-actualyze`, so anything that
997
+ names the plugin by its ID needs the new one. That includes a client of
998
+ the plugin's RPC contract, which `opencode-actualyze/rpc` exports. Saved
999
+ discovery state starts fresh, because OpenCode keeps it under the plugin
1000
+ ID; the discovered models appear again once the first discovery finishes,
1001
+ usually within a few seconds.
1002
+ - **Commands.** The `/modelscout` browser keeps its name, and `/actualyze`
1003
+ is added.
1004
+ - **Probe values.** A `settings.probe` value the plugin does not recognize
1005
+ shows a warning in `/modelscout` and `/actualyze` that lists the accepted
1006
+ values.
1007
+ - **Actualyze providers.** A provider entry that points at
1008
+ `https://app.actualyze.ai/openai/v1` can be removed, because the built-in
1009
+ `actualyze` provider covers it. Its models then appear under the
1010
+ `actualyze` provider; connect your key with `/actualyze` or
1011
+ `opencode auth login actualyze`.
991
1012
 
992
1013
  ## Contributing
993
1014
 
@@ -996,4 +1017,5 @@ the live harness and TUI scenarios, and how to add a probe.
996
1017
 
997
1018
  ## License
998
1019
 
999
- MIT. Based on [opencode-lmstudio](https://github.com/agustif/opencode-lmstudio).
1020
+ MIT. Based on
1021
+ [opencode-lmstudio](https://github.com/agustif/opencode-lmstudio).