You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,15 +25,15 @@ This package is based on **[FanFan4204/opencode-commandcode-provider](https://gi
25
25
- Vision vs text-only comes from the Command Code CLI catalog (`inputModalities` on every SKU). [models.dev](https://models.dev) only adds extra inputs (video/audio/pdf) when it matches.
26
26
- Reasoning effort **variants** on models that declare `reasoningEfforts`.
27
27
- Release date, family, input limits, model status, vendor context limits, and matched context-price tiers flow through the bundled catalog. V2 gets native release, family, input, status, and tier fields; V1 keeps its supported fields and base prices, with `context_over_200k` where representable.
28
-
- The provider's `supported_endpoints` metadata chooses each model's API route. Responses-capable models use `@ai-sdk/openai` on V1 and `aisdk:@ai-sdk/openai` on V2; Claude falls back to Anthropic Messages when endpoint metadata is absent. The V1 and V2 Responses mappings passed official Docker checks against a local mock stream, and a GOAT-key DeepSeek control request succeeded in OpenCode V2. Claude Sonnet 4.6 returned `MODEL_NOT_IN_PLAN` with the message “available in Pro and above plans or extra on-demand usage”; this confirms the account restriction, not successful Anthropic routing. Entitled Claude access has not been live-verified. If a model fails on an account entitled to use it, please [open an issue](https://github.com/BrainerVirus/opencode-commandcode/issues) with the model ID and OpenCode version, or submit a PR with a reproducible fix.
28
+
- The provider's `supported_endpoints` metadata chooses each model's API route. When a model advertises Messages, it uses Anthropic Messages; otherwise Chat Completions is preferred when available, and Responses is used when it is the only advertised route. This avoids malformed annotation events seen on the provider's Responses stream while preserving Responses-only models. V1 maps Responses to `@ai-sdk/openai`; V2 maps it to `aisdk:@ai-sdk/openai`. Claude Sonnet 4.6 returned `MODEL_NOT_IN_PLAN` with the message “available in Pro and above plans or extra on-demand usage”; entitled Claude access has not been live-verified. If a model fails on an account entitled to use it, please [open an issue](https://github.com/BrainerVirus/opencode-commandcode/issues) with the model ID and OpenCode version, or submit a PR with a reproducible fix.
29
29
- Quiet OpenCode startup (diagnostics go to `startup.json`, not stdout).
30
30
31
31
## How it works
32
32
33
33
For published plugin versions, the six-hour CI schedule extracts the latest `command-code` npm bundle and refreshes callable models plus endpoint metadata, even when the CLI version is unchanged. It opens a catalog PR only when generated artifacts change; at startup the plugin loads those artifacts and registers them with OpenCode — never the other way around.
34
34
35
35
-**Extract + filter** — model entries (ids, names, reasoning, `inputModalities`, limits) are evaluated out of the minified CLI bundle (`src/catalog.ts`), then intersected with the callable IDs reported by the provider API.
36
-
-**Metadata + costs merge** — vendor context length tightens only a fallback context limit, while `supported_endpoints` selects Chat Completions, Responses, or Messages per model; missing endpoint metadata preserves the last known route data. models.dev contributes release date, family, input limit, status, modalities, and cost tiers when present. Tier rows are accepted only when their base prices match this Command Code catalog. Base costs use CLI bundle → official Command Code docs → free SKUs (`$0`) → [models.dev](https://models.dev) reference prices → unmatched placeholder. Anything still unmatched marks the catalog `degraded`. This runs at sync time only; runtime never fetches metadata or prices.
36
+
-**Metadata + costs merge** — vendor context length tightens only a fallback context limit, while `supported_endpoints` selects Messages, Chat Completions, or Responses per model in that preference order; missing endpoint metadata preserves the last known route data. models.dev contributes release date, family, input limit, status, modalities, and cost tiers when present. Tier rows are accepted only when their base prices match this Command Code catalog. Base costs use CLI bundle → official Command Code docs → free SKUs (`$0`) → [models.dev](https://models.dev) reference prices → unmatched placeholder. Anything still unmatched marks the catalog `degraded`. This runs at sync time only; runtime never fetches metadata or prices.
-**Version-specific registration** — V1 uses the `plugin` config key, `server()` provider map, and V1 auth callback. V2 uses `plugins`, provider/model transforms, and a `commandcode` integration with key and `COMMANDCODE_API_KEY` environment methods. Both retain the Command Code wire model ID. V2 exposes tiered context pricing; V1 emits its supported `context_over_200k` field and keeps flat pricing for other tiers.
39
39
-**Degraded/cache fallbacks** — a `degraded`/`broken` manifest sets the degraded flag with a reason; an unreadable bundled `models.json` falls back to the last-good cache; auth/connect still registers even with an empty catalog.
Pin a version instead of `@latest`if you do not want automatic catalog patches.
61
+
The bare package name is unpinned and resolves npm's `latest` release when OpenCode installs or updates it; adding `@latest`is unnecessary. OpenCode V2 checks for updates at startup but keeps an existing cached package. Apply a newer package with OpenCode's plugin-update action, then restart to load it. OpenCode V1 can refresh the global package with `opencode plugin @brainervirus/opencode-commandcode --global --force`.
62
62
63
63
`file://` checkouts are **not** updated by npm; `git pull` after CI commits, or switch to the npm plugin line.
64
64
@@ -76,7 +76,7 @@ Set `COMMANDCODE_API_KEY`, or connect interactively. OpenCode V1 provides **Comm
76
76
/models
77
77
```
78
78
79
-
Catalog patches arrive as plugin updates: `@latest` refreshes in the background and takes effect on the next OpenCode restart. If a new model is missing after an announced sync, restart opencode once.
79
+
Catalog patches ship in new npm releases. OpenCode loads the version in its package cache; an update must be applied through the host before the new catalog appears. If a new model is missing after an announced sync, check the installed package version, apply the update, and restart OpenCode.
`package.json``name` is `@brainervirus/opencode-commandcode` with `publishConfig.access: "public"` (published as `@brainervirus/commandcode-go-opencode-provider` before the 0.6.0 rename). This stays its own repo; it is not folded into `workflow-toolkit`.
187
187
188
-
`file://` installs are **not** auto-updated by CI; catalog changes require `git pull` of this repo. npm installs update through `@latest`.
188
+
OpenCode V1 uses the singular `plugin` config key with the same bare package name. The package name without a suffix is unpinned and resolves npm's latest dist-tag when installed or updated; `@latest` is redundant. OpenCode V2 checks for unpinned updates at startup but keeps an existing package cache until the host's update action is applied. `file://` installs are notupdated by npm; catalog changes require `git pull` of this repo.
189
189
190
190
## Runtime Plugin Changes
191
191
@@ -294,7 +294,7 @@ Same sequence as the identity spec. Phase 1 (A) must refresh `models.json` befor
294
294
1. Rename package to `@brainervirus/commandcode-go-opencode-provider` (shipped at 0.5.0; renamed to `@brainervirus/opencode-commandcode` at 0.6.0).
295
295
2. Store `NPM_TOKEN` (npm user `brainervirus`) as a GitHub Actions secret; `publishConfig.access: public`.
296
296
3. Enable publish + GitHub Release in the workflow.
297
-
4. Document `"plugin": ["@brainervirus/opencode-commandcode@latest"]` vs pin.
297
+
4. Document the bare unpinned package name and explicit-version pinning.
@@ -10,7 +10,7 @@ Freshness has three independent boundaries:
10
10
11
11
1. Command Code must identify which extracted models are currently callable.
12
12
2. This provider must publish only that callable catalog with internally consistent metadata.
13
-
3. OpenCode must refresh mutable plugin package references without discarding a working cache.
13
+
3. OpenCode must make it clear when a mutable plugin package is stale and how to update it without losing a working cache.
14
14
15
15
## Current Failure
16
16
@@ -20,7 +20,7 @@ Separately, OpenCode can retain an older installation of `@brainervirus/opencode
20
20
21
21
The release pipeline also updated `manifest.json` after npm publication. Consequently, the manifest inside a newly published tarball could report the previous plugin version even though the repository was corrected by a later synchronization PR.
22
22
23
-
Provider-side resolution (2026-09-20): the availability filter shipped in `fix(catalog): exclude unavailable models` and the packed-manifest alignment shipped in `fix(release): align published manifest version`. The OpenCode-side mutable-package refresh (step 3 below) is still pending upstream.
23
+
Provider-side resolution (2026-09-20): the availability filter shipped in `fix(catalog): exclude unavailable models` and the packed-manifest alignment shipped in `fix(release): align published manifest version`. The original request for automatic warm-cache replacement is not implemented by OpenCode V2.0.18; startup loads the cached package and does not replace it. The plugin cannot update the package code that is already running.
24
24
25
25
## Decisions
26
26
@@ -86,19 +86,9 @@ The unavailable list is sorted by ID so repeated synchronization is deterministi
86
86
87
87
### Mutable OpenCode plugin packages
88
88
89
-
The upstream OpenCode implementation will rework pull request [anomalyco/opencode#49485](https://github.com/anomalyco/opencode/pull/49485).
89
+
OpenCode V2.0.18 loads a warm cached package at startup and does not silently replace it. An isolated local startup with a cached Command Code 0.9.1 package loaded 0.9.1 even though npm `latest` was 0.10.1. A clean cache does install the latest package. OpenCode's current V2 plugin documentation describes startup update checks without changing the installed package; the host's update action must be applied before a restart loads the new code. V1.18.30's `opencode plugin <module> --global --force` explicitly refreshes a global package.
90
90
91
-
For npm plugin references:
92
-
93
-
- exact versions are immutable and use the cache without refresh;
94
-
- bare package names, dist-tags such as `@latest`, and version ranges are mutable;
95
-
- a mutable reference with no cached installation blocks on installation; a failure reports the normal plugin installation error and leaves no partial cache;
96
-
- a mutable reference with a cached installation loads that cache immediately and starts at most one background refresh per OpenCode process;
97
-
- a successful background refresh becomes active on the next OpenCode restart; plugins are not hot-swapped in a running process;
98
-
- a failed background refresh leaves the cached installation untouched and does not block startup; and
99
-
- equivalent bare and explicit-latest references share one canonical cache location.
100
-
101
-
Concurrent refresh attempts for the same canonical package are deduplicated. Installation remains atomic so interruption cannot replace a working cache with a partial package.
91
+
The bare package name is the normal unpinned reference; adding `@latest` is redundant. Exact versions remain pinned. The plugin reads only its bundled catalog and cannot refresh its own npm package or hot-swap its running code.
102
92
103
93
Git, file, and workspace plugin references are outside this behavior change.
104
94
@@ -114,7 +104,7 @@ Release verification must inspect the packed artifact and fail before publicatio
114
104
115
105
The installed plugin reads only its bundled `models.json` and `manifest.json` for normal model registration. It does not call the availability endpoint, npm registry, or GitHub to decide which models to expose.
116
106
117
-
This preserves deterministic startup and offline use. Freshness is delivered by catalog automation plus OpenCode's mutable-package refresh behavior.
107
+
This preserves deterministic startup and offline use. Freshness is delivered by catalog automation plus the host's explicit package-update flow; a warm npm cache can remain stale until that update is applied.
118
108
119
109
## Non-Goals
120
110
@@ -140,13 +130,11 @@ This preserves deterministic startup and offline use. Freshness is delivered by
140
130
141
131
### OpenCode package refresh
142
132
143
-
- A warm mutable cache starts OpenCode without waiting for the registry.
144
-
- A cold mutable install failure reports an installation error and leaves no cache entry.
145
-
- One background refresh is attempted per canonical mutable package per process.
146
-
- Successful refresh output is used after restart, not during the current process.
147
-
- Offline or failed refresh preserves and continues using the prior cache.
148
-
- Exact-version references perform no background refresh.
149
-
- Bare and `@latest` references cannot maintain divergent cache roots.
133
+
- A clean cache with the bare package entry installs the current npm `latest` release.
134
+
- A warm OpenCode V2.0.18 cache loads its installed version at startup without replacing it.
135
+
- Applying a host plugin update and restarting loads the new package.
136
+
- The V1 force-install command refreshes its configured global package.
137
+
- Exact-version references remain pinned; `@latest` is not required for an unpinned package.
150
138
151
139
### Release metadata
152
140
@@ -156,7 +144,7 @@ This preserves deterministic startup and offline use. Freshness is delivered by
156
144
157
145
### End-to-end
158
146
159
-
From a clean OpenCode cache, installing the mutable Command Code plugin and restarting after a successful refresh exposes every exact-ID match between extractor candidates and the current API list, including newly added matches, and exposes none of the API-absent retired or unreleased entries.
147
+
From a clean OpenCode cache, the bare Command Code package installs the current npm release and exposes the catalog in that tarball. With a warm stale cache, users must apply the host's package update and restart before the newer catalog appears. In both cases the catalog exposes only the exact-ID matches produced by the provider sync.
160
148
161
149
## Coordination Plan
162
150
@@ -178,17 +166,17 @@ From a clean OpenCode cache, installing the mutable Command Code plugin and rest
178
166
- Owner: OpenCode contributor.
179
167
- Files: the package installation/cache path and tests in the upstream OpenCode repository.
180
168
- Dependency: rework pull request `#49485`; independent of provider steps 1 and 2.
181
-
- Evidence: cold, warm, offline, exact-version, canonical-cache, deduplication, and next-restart tests in upstream CI.
169
+
- Evidence: upstream docs and local warm-cache tests show that V2 checks but does not silently replace a cached package; automatic replacement still requires upstream support.
182
170
- Commit: follow OpenCode repository convention.
183
-
- Status: pending upstream.
171
+
- Status: pending upstream; see [OpenCode plugin update behavior](https://opencode.ai/v2/docs/plugins).
184
172
4.**Rollout verification**
185
173
- Owner: provider maintainer.
186
174
- Dependency: provider release and an OpenCode build containing step 3.
187
-
- Evidence: compare the installed tarball manifest to its package version, launch from a clean cache, restart after refresh, and compare displayed provider IDs with the public availability response.
175
+
- Evidence: compare the installed tarball manifest to its package version, launch from a clean cache, apply a host update to a warm cache, restart, and compare displayed provider IDs with the public availability response.
188
176
- Commit: none unless verification finds a defect.
189
177
- Status: pending upstream.
190
178
191
-
Provider steps 1 and 2 shipped on 2026-09-20 before the upstream change. Until OpenCode releases step 3, users on stale mutable caches may still need one manual cache refresh; that temporary operational workaround is not part of the target behavior.
179
+
Provider steps 1 and 2 shipped on 2026-09-20. Until OpenCode adds automatic package installation for warm caches, users may need to apply the host update action manually; do not clear the cache as a workaround because it discards a working install.
0 commit comments