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: AGENTS.md
-1Lines changed: 0 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -42,6 +42,5 @@ Any branch that changes shipped behavior — `plugin.ts`, `index.ts`, `src/**`,
42
42
43
43
-`src/schemas.ts` is the single source of truth for `ModelEntry` / `CatalogManifest` shapes. `src/catalog.ts` and `src/manifest.ts` derive them via `z.infer` — never redeclare the shape. Verify: `grep -rn "interface ModelEntry\|type CatalogManifest = {" src` must be empty.
44
44
- zod lives only at validation boundaries (bundled `models.json` / `manifest.json` reads in `plugin.ts`, provider availability payloads, user config files). Hot paths (`src/convert.ts`, `src/stream.ts`, `src/model.ts`, the `generate*` model loops) stay zod-free. Verify: `grep -rn 'from "zod"' src/convert.ts src/stream.ts src/model.ts` must be empty.
45
-
-`dist/plugin.js` budget: ~708KB with zod bundled (was ~45KB type-only). A second runtime dependency requires either `--external` in `scripts/build-plugin.ts` or updating this budget line. Verify: `bun run build && du -h dist/plugin.js`.
46
45
- V1 (`generateOpencodeModels` in `src/catalog.ts`) and V2 (`toV2Model` in `src/v2models.ts`) cost/limit/modality mappings must stay in parity — change one, update the other plus `tests/unit/v2models.test.ts`. UI/map keys use `toConfigKey` in `src/catalog.ts` (do not duplicate it); the Command Code wire id is always catalog `entry.id` (V1 model `id`, V2 `modelID`) — bare short names 400 as unsupported_model.
47
46
- Entry points: `plugin.ts` owns all config-hook logic; `index.ts` re-exports + SDK factory; `src/entry.ts` is bundle glue for `scripts/build-plugin.ts` only. Do not add a fourth entry or duplicate the catalog-load path.
Copy file name to clipboardExpand all lines: README.md
+23-9Lines changed: 23 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,8 @@
6
6
7
7
[Command Code](https://commandcode.ai) API provider for [opencode](https://opencode.ai). Use Claude, GPT, Gemini, DeepSeek, Qwen, Kimi, GLM, MiniMax, Step, and other models through a single API key.
8
8
9
+
This plugin is for Command Code accounts with Provider API access. GOAT is the live-tested baseline; other API-enabled plans can use models their account is entitled to. The $1 Go plan has no Provider API access. The catalog follows the provider-wide model list, so a model appearing in OpenCode does not imply that every account can call it. See [GOAT plan details](https://commandcode.ai/docs/plans/goat) and [Provider API docs](https://commandcode.ai/docs/provider).
10
+
9
11
This package keeps a **bundled** model catalog current via CI. You do **not** need a local `command-code` CLI. Catalog patches publish automatically after a green PR merges to `main`.
10
12
11
13
Previously published as `@brainervirus/commandcode-go-opencode-provider`. Use this name instead.
@@ -17,44 +19,56 @@ This package is based on **[FanFan4204/opencode-commandcode-provider](https://gi
17
19
### What this package adds
18
20
19
21
- Bundled `models.json` is the default runtime catalog (no local CLI scrape).
20
-
-Dual OpenCode entry: V2 `setup` injects the provider plus models via transforms; V1 `server` fills `provider.commandcode`defaults plus models and registers API-key auth (auth stays V1-only).
22
+
-V1 and V2 use their native plugin and provider surfaces. V1 `server()` fills `provider.commandcode` and registers API-key auth; V2 `setup()` registers provider/model transforms and a key/env integration for `/connect` and `opencode auth login`.
21
23
- Validation at the boundaries via `src/schemas.ts` (zod): bundled `models.json` / `manifest.json` reads, provider availability payloads, and the plugin config file.
22
24
- CLI cost extraction can fail without dropping models; official docs fill missing costs, remaining paid gaps use [models.dev](https://models.dev) as a reference price at sync time. Command Code free SKUs stay `$0`.
23
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.
24
26
- Reasoning effort **variants** on models that declare `reasoningEfforts`.
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.
25
29
- Quiet OpenCode startup (diagnostics go to `startup.json`, not stdout).
26
30
27
31
## How it works
28
32
29
-
Each CI sync extracts the model catalog from the latest `command-code` npm bundle, merges costs, and commits versioned artifacts; at startup the plugin loads those artifacts and registers them with OpenCode — never the other way around.
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.
30
34
31
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.
32
-
-**Costs merge** — per model, first hit wins: CLI bundle costs → 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 prices.
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.
-**V1 injection + V2 transform** — V1 `server()`fills `provider.commandcode` defaults and the models map; V2 `setup()` adds/updates the provider inventory (baseURL, API key binding) and sets models through `ctx.provider.transform`.
38
+
-**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.
35
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. The config key stays `plugin` in OpenCode V2 — there is no `plugins` key.
61
+
Pin a version instead of `@latest` if you do not want automatic catalog patches.
48
62
49
63
`file://` checkouts are **not** updated by npm; `git pull` after CI commits, or switch to the npm plugin line.
50
64
51
65
### 2. No provider block needed
52
66
53
-
On OpenCode V2 the plugin registers the `commandcode` provider itself (Provider API base URL plus `COMMANDCODE_API_KEY` binding) and its models. On V1 the `server` hook fills the same `provider.commandcode` defaults — `npm: "@ai-sdk/openai-compatible"` plus the Provider API `baseURL`; the plugin package itself is never the SDK `npm` field. Only add a manual `provider.commandcode` entry if you need non-default transport options.
67
+
On OpenCode V2 the plugin registers the `commandcode` provider, its models, and its API base URL through the V2 provider API. On V1 the `server` hook fills `provider.commandcode` defaults — `npm: "@ai-sdk/openai-compatible"` plus the Provider API `baseURL`; the plugin package itself is never the SDK `npm` field. Only add a manual provider entry if you need non-default transport options.
54
68
55
69
### 3. Connect
56
70
57
-
Set `COMMANDCODE_API_KEY`, or on OpenCode V1 run `/connect`, search for **Command Code**, and enter your API key. V2 registers the provider with the env binding; the `/connect` API-key method is V1-only.
71
+
Set `COMMANDCODE_API_KEY`, or connect interactively. OpenCode V1 provides **Command Code** through `/connect`; OpenCode V2 registers key and environment methods for `/connect` and `opencode auth login commandcode`. V2 uses OpenCode's automatic provider activation and preserves an explicit activation setting. Connect before running a model; an explicit run while disconnected still returns an authorization error from the API.
58
72
59
73
### 4. Select a model
60
74
@@ -97,9 +111,9 @@ bun run generate-readme # reports catalog counts only; README is hand-edited
97
111
bun run catalog:ci # entry used by the catalog-sync workflow
98
112
```
99
113
100
-
Entry points: `plugin.ts` owns all config-hook logic (dual default `{ id, setup }` plus `server`); `index.ts` re-exports the plugin plus the `createCommandCode` SDK factory; `src/entry.ts` is bundle glue for `scripts/build-plugin.ts` only — it produces `dist/plugin.js`.
114
+
Entry points: `plugin.ts` owns both config surfaces (V2 `id`/`setup` plus V1`server`); `index.ts` re-exports the plugin plus the `createCommandCode` SDK factory; `src/entry.ts` is bundle glue for `scripts/build-plugin.ts` only — it produces `dist/plugin.js`.
101
115
102
-
CI (`.github/workflows/catalog-sync.yml`) opens a `fix(catalog)` PR every 6 hours when Command Code ships a new catalog; if extraction fails it opens a `catalog-break` issue instead. The PR auto-merges after **check (test)**, **check (typecheck)**, **check (lint)**, **check (format)**, and **check (pack)** are green. `.github/workflows/release.yml` then runs **semantic-release** (build + verified npm publish + GitHub Release + tag). Do not push to `main`.
116
+
CI (`.github/workflows/catalog-sync.yml`) checks every 6 hours for CLI catalog changes and provider availability/endpoint metadata changes; it opens a `fix(catalog)` PR only when generated files change. If extraction fails or the model-count safety floor is breached, it opens a `catalog-break` issue and leaves the last-good files intact. The PR auto-merges after **check (test)**, **check (typecheck)**, **check (lint)**, **check (format)**, and **check (pack)** are green. `.github/workflows/release.yml` then runs **semantic-release** (build + verified npm publish + GitHub Release + tag). Do not push to `main`.
103
117
104
118
The GitHub Actions secret name is `NPMJS`. It is mapped to both `NPM_TOKEN` and `NODE_AUTH_TOKEN`. Use an npm **Automation** token (bypasses 2FA). A login token from `~/.npmrc` fails CI with `EOTP`. Catalog PRs get a real CI run when `RELEASE_SYNC_TOKEN` is a PAT; `GITHUB_TOKEN` can open the PR but GitHub will not start workflows from that event.
Copy file name to clipboardExpand all lines: docs/2026-08-28-ci-catalog/spec.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -17,7 +17,7 @@ Watch `command-code` on npm every 6 hours, refresh the bundled catalog, publish
17
17
- Human merges to `main` run semantic-release; releases are path-gated (`scripts/analyze-release-scope.ts`), so CI/docs/tests-only merges do not publish.
18
18
- Cost-only CLI failure still ships (`degraded` only if unmatched placeholder costs remain). Model extract failure → no publish, `catalog-break` issue.
19
19
- Runtime catalog stays bundled `models.json`. No GitHub fetch at OpenCode startup.
20
-
-Hybrid OpenCode transport stays `@ai-sdk/openai-compatible` + Provider API; this package is the **plugin**, not the SDK `npm` field.
20
+
-Chat Completions keep `@ai-sdk/openai-compatible`; provider `supported_endpoints` selects per-model Responses (`@ai-sdk/openai`) or Anthropic Messages where advertised. This package remains the **plugin**, not the SDK `npm` field.
Copy file name to clipboardExpand all lines: docs/specs/2026-08-19-stable-model-identity.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Command Code OpenCode Provider — Runtime Identity and Resilience
2
2
3
-
Status: shipped (updated 2026-09-26)
3
+
Status: shipped baseline (updated 2026-09-26; current V2 additions are in the [2026-09-28 parity spec](./2026-09-28-v2-parity.md))
4
4
5
5
## Goal
6
6
@@ -35,7 +35,7 @@ Every load with models rewrites the cache; every load writes `startup.json`. Wri
35
35
| cost data missing after the CI waterfall | continue; unmatched costs keep the placeholder and the manifest is `degraded`|
36
36
| provider availability call fails in sync | no artifact writes and a `catalog-break` issue; the previous catalog stays |
37
37
| opt-in local extract fails | ignore override; use bundled |
38
-
| auth/connect |registers on V1 regardless of catalog state |
38
+
| auth/connect |V1 auth and V2 integration register regardless of catalog state |
39
39
40
40
Degraded reporting is internal: `startup.json` carries `degraded` and `degradedReason`, and V1/V2 registration is unchanged. There is no separate degraded UI.
41
41
@@ -57,7 +57,7 @@ Degraded reporting is internal: `startup.json` carries `degraded` and `degradedR
57
57
- Default is quiet: no `console.log`/`console.warn` in the plugin load path.
58
58
-`~/.local/state/opencode/commandcode-provider/startup.json` records `catalogSource` (`bundled`/`cache`/`opt-in-local`), `commandCodeVersion`, `modelCount`, `reasoningModelCount`, `degraded`, and `degradedReason`.
59
59
-`debugStartupLogs: true` mirrors the summary to stderr once.
60
-
- V1 `server()`registers provider defaults and the API-key auth method; V2 `setup()`adds/updates the provider inventory and models through transforms. Auth stays V1-only.
60
+
-At this spec's 0.9.1 baseline, V1 `server()`registered provider defaults and the API-key auth method; V2 `setup()`only added/updated provider inventory and models. V2 key/env integration support was added later; see the [parity spec](./2026-09-28-v2-parity.md).
61
61
62
62
## Config
63
63
@@ -81,7 +81,7 @@ If favorites migration is ever needed, reopen it as a new spec against the curre
81
81
82
82
## Test coverage
83
83
84
-
Unit tests exercise the shipped contract (`tests/unit/plugin.test.ts`, `startup.test.ts`, `schemas.test.ts`, `catalog.test.ts`, `v2models.test.ts`, `auth.test.ts`):
84
+
Unit tests exercise the baseline contract (`tests/unit/plugin.test.ts`, `startup.test.ts`, `schemas.test.ts`, `catalog.test.ts`, `v2models.test.ts`, `auth.test.ts`); V2 integration behavior is covered by `tests/unit/plugin-v2.test.ts`:
85
85
86
86
- bundled load, cache fallback, and dropped-entry degraded reasons
87
87
- V1 map key vs wire id; V2 `id` vs `modelID`
@@ -92,3 +92,4 @@ Unit tests exercise the shipped contract (`tests/unit/plugin.test.ts`, `startup.
0 commit comments