opencode-cmd-provider 1.5.1 → 1.6.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,84 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.0 - 2026-08-28
4
+
5
+ ### Deals pipeline: RSC-primary + daily catalog refresh cron
6
+
7
+ The deals catalog is no longer scraped from HTML tables — it is generated from
8
+ the Command Code docs site's React Server Components (RSC) stream (the docs
9
+ pages fetched with an `rsc: 1` header; see ADR-0005). The HTML live fetch and
10
+ HTML fixtures are gone; `scripts/parse-docs.mjs` keeps its parsers as a
11
+ documented air-gapped fallback.
12
+
13
+ - **RSC parser** — `scripts/parse-rsc.mjs` with committed fixtures
14
+ (`tests/fixtures/rsc-{pricing-limits,goat,pro}.txt`), shape-pinning unit
15
+ tests, a slug-id→snapshot-id alias map, and the shared depth-state-machine
16
+ extracted to `scripts/json-stream.mjs`.
17
+ - **Tier overrides** — `scripts/tier-overrides.mjs` pins the 7 known Command
18
+ Code tier-categorization disagreements to `opensource` so TUI badges stay
19
+ stable.
20
+ - **Daily cron** — `.github/workflows/catalog-refresh.yml` (06:00 UTC +
21
+ `workflow_dispatch`) regenerates snapshot/facts/fixtures/deals, builds,
22
+ tests, and opens a `chore: catalog refresh` PR (body via
23
+ `scripts/diff-catalog.mjs`) only when upstream moved; silent exit when
24
+ nothing drifted.
25
+ - **Fixture lockstep** — `npm run refresh` now re-captures the RSC fixtures
26
+ from the live docs pages (`scripts/capture-rsc-fixtures.mjs`) before
27
+ regenerating the deals catalog, so fixtures, catalog, and tests stay
28
+ consistent. Standalone `refresh:deals` falls back to fixtures on 5xx/network
29
+ and fails loudly on 4xx.
30
+ - **Catalog refresh** — deals/snapshot/facts refreshed to
31
+ `command-code@1.37.0` (new: `tencent/hy4-preview`, classified
32
+ reasoning-capable without explicit efforts); benchmark pins updated to
33
+ upstream's new values (Gemini 3.7 Flash, MiniMax M3).
34
+ - **Fixes** — live RSC URLs corrected (the `/docs/rsc/*` draft routes 404 on
35
+ the real site); the cron now builds before testing (the pack contract test
36
+ needs `dist/` in a fresh checkout); 4xx RSC responses fail loudly instead of
37
+ silently falling back to fixtures.
38
+ - **Follow-ups** — open decisions tracked in issues #89 (shape-pinning value
39
+ pins) and #90 (expired-deal filtering).
40
+
41
+ ## 1.5.2 - 2026-08-28
42
+
43
+ Chore: catalog refresh to `command-code@1.36.0`, with a deals-coverage gate
44
+ fix for name-colliding free variants.
45
+
46
+ - Added `z-ai/glm-5.3-flash` (GLM-5.3 Flash) and `Qwen/Qwen3.8-Flash` with
47
+ deals records; removed `stealth/ox-alpha` (dropped from the upstream
48
+ catalog).
49
+ - MiniMax free variants (`minimax/minimax-m3-free`,
50
+ `minimax/minimax-m2.7-free`) now append `(free)` to their picker display
51
+ name — upstream renamed them to share the paid display name — derived
52
+ data-driven from the zero-cost table, with updated deal allowance pricing
53
+ for `deepseek/deepseek-v4-flash-vision-exp`.
54
+ - The deals-coverage gate now iterates every snapshot entry by id, so free
55
+ variants whose display names collide with paid siblings are actually
56
+ coverage-checked (a fixture that silently dropped them previously passed
57
+ with exit 0 and emitted a partial deals catalog); a shared
58
+ `scripts/snapshot-index.mjs` parser replaced the duplicated regex parsing.
59
+
60
+ ### Fixes
61
+
62
+ - **Deals-coverage gate**: `check-deals-coverage.mjs` and the
63
+ `missingDealsModels` check in `refresh-deals.mjs` iterated a first-wins
64
+ name→id map, so MiniMax free variants — whose snapshot display names
65
+ collide with their paid siblings — were never actually checked. Both gates
66
+ now iterate by id, with the name fallback applying only to unambiguous
67
+ names; records that resolve to no snapshot id are skipped instead of
68
+ collapsing under `undefined`.
69
+ - Catalog refresh to `command-code@1.33.0` added the MiniMax free variants;
70
+ the `1.36.0` refresh added GLM-5.3 Flash and Qwen 3.8 Flash, dropped Ox
71
+ Alpha, and extended `src/plugin/models.ts` with the zero-cost `(free)`
72
+ suffix. The extended pricing import now fits the print width again
73
+ (`format:check` passes).
74
+
75
+ ### Chores
76
+
77
+ - New `tests/deals-coverage.test.ts` regression cases: removed free variants
78
+ now fail the gate; deals free flag ⇔ facts zero-cost table consistency;
79
+ negative suffix test (absent cost entry must not get `(free)`).
80
+ - README documents the `(free)` suffix and its zero-cost derivation.
81
+
3
82
  ## 1.5.1 - 2026-08-24
4
83
 
5
84
  Fix: provider parsers now synthesize the full reasoning and text lifecycle —
package/README.md CHANGED
@@ -101,8 +101,9 @@ opencode run --model commandcode/claude-sonnet-5 "hello"
101
101
  ## Deals intelligence
102
102
 
103
103
  Every Command Code model ships with deal/allowance/benchmark intelligence
104
- (bundled in `src/deals/catalog.ts`), scraped from the Command Code docs. It
105
- surfaces in two places:
104
+ (bundled in `src/deals/catalog.ts`), extracted from the Command Code docs'
105
+ React Server Components (RSC) stream — the structured payload the docs site
106
+ serves for `rsc: 1` requests (see ADR-0005). It surfaces in two places:
106
107
 
107
108
  - **Sidebar** — in a session, the OpenCode sidebar (`ctrl+x b`) shows a
108
109
  `Command Code` section for the selected model: tier, GOAT/Pro allowance,
@@ -118,20 +119,26 @@ spec. The sidebar is a TUI plugin loaded from `tui.json` — which is why
118
119
  installs made before the `./tui` export only wrote the server target and never
119
120
  showed a sidebar. Re-run with `--force` to add `tui.json`.
120
121
 
121
- When the Deals catalog is empty (scraping mitigated), the feature degrades
122
- visibly rather than silently: the sidebar shows a `Deals unavailable` banner
123
- with placeholder rows, and `cmd_plan_summary` reports that no deal data is
124
- bundled. Core (models, auth, streaming) is unaffected.
122
+ When the Deals catalog is empty (the upstream fetch failed or the RSC shape
123
+ changed), the feature degrades visibly rather than silently: the sidebar shows
124
+ a `Deals unavailable` banner with placeholder rows, and `cmd_plan_summary`
125
+ reports that no deal data is bundled. Core (models, auth, streaming) is
126
+ unaffected.
125
127
 
126
128
  ## Model discovery and offline behavior
127
129
 
128
130
  The plugin ships two bundled catalogs and auto-registers every model into
129
131
  OpenCode's config at startup, with the `[CMD]` display-name prefix (e.g.
130
132
  `[CMD] Claude Sonnet 5`) so they aren't confused with same-named models from
131
- other providers. Model availability changes when the package is updated. You
132
- can still declare your own `provider.commandcode` entry; your declarations
133
- always win and the snapshot fills in only what's missing (`whitelist`/
134
- `blacklist` on a declared entry filter the auto-registered models too).
133
+ other providers. Free-tier variants that share an upstream display name with a
134
+ paid model (e.g. the MiniMax M3 free tier) get a `(free)` suffix
135
+ `[CMD] MiniMax M3 (free)` — so the two are distinguishable in the model
136
+ picker. The suffix is derived from the bundled pricing table: a model is
137
+ labeled free only when the catalog carries an explicit zero-cost entry. Model
138
+ availability changes when the package is updated. You can still declare your
139
+ own `provider.commandcode` entry; your declarations always win and the
140
+ snapshot fills in only what's missing (`whitelist`/`blacklist` on a declared
141
+ entry filter the auto-registered models too).
135
142
 
136
143
  The `[CMD] ` display-name prefix is configurable through the declared
137
144
  provider entry's options:
@@ -156,12 +163,22 @@ auto-registered models only.
156
163
  modalities). Regenerated from the live catalog via `npm run refresh:snapshot`.
157
164
  - Deals — `src/deals/catalog.ts` (per-model tier, benchmarks, deal
158
165
  discounts, `was`/`now` rates, peak/off-peak windows, and GOAT/Pro monthly
159
- allowances for every model). Scraped from the Command Code docs
160
- (`pricing-limits`, `plans/goat`, `plans/pro`; fixtures in
161
- `tests/fixtures/*.html`) via `npm run refresh:deals` (add `-- --fixtures` to
162
- regenerate offline from fixtures; without it, fetches live pages).
163
-
164
- Run `npm run refresh` to regenerate both catalogs at once (offline from fixtures).
166
+ allowances for every model). Extracted from the Command Code docs' RSC
167
+ stream (the `pricing-limits`, `plans/goat`, `plans/pro` pages fetched with
168
+ an `rsc: 1` header; fixtures in `tests/fixtures/rsc-*.txt`) via
169
+ `npm run refresh:deals`. Standalone live runs fall back to the committed
170
+ fixtures on 5xx/network failure and fail loudly on 4xx; add
171
+ `-- --fixtures` to regenerate offline from the committed fixtures.
172
+
173
+ Run `npm run refresh` to regenerate everything at once: the snapshot and
174
+ facts come from the live Command Code catalog, the RSC fixtures are
175
+ re-captured from the live docs pages (`npm run refresh:fixtures`), and the
176
+ deals catalog is regenerated from the fresh fixtures — so fixtures, catalog,
177
+ and tests stay in lockstep. A daily GitHub Actions cron
178
+ (`.github/workflows/catalog-refresh.yml`, 06:00 UTC, also manually
179
+ triggerable via `workflow_dispatch`) runs the same pipeline: when upstream
180
+ moved it opens a `chore: catalog refresh` PR whose body is the human-readable
181
+ diff from `scripts/diff-catalog.mjs`; when nothing drifted it exits silently.
165
182
 
166
183
  Auto-registration adds no network latency to OpenCode startup — the snapshot is
167
184
  bundled, and the plugin never contacts the Command Code API to list models. The
@@ -171,14 +188,14 @@ endpoint being reachable.
171
188
  The following environment variables are intended for tests, local mocks, and
172
189
  compatible API endpoints:
173
190
 
174
- | Variable | Purpose |
175
- | ------------------------------- | -------------------------------------- |
176
- | `COMMANDCODE_API_BASE` | Override the Command Code API base URL |
177
- | `COMMANDCODE_FACTS_URL` | Override the bundled `models.md` URL |
178
- | `COMMANDCODE_MODALITIES_URL` | Override the CLI bundle URL |
179
- | `COMMANDCODE_DEALS_PRICING_URL` | Override the `pricing-limits` docs URL |
180
- | `COMMANDCODE_DEALS_GOAT_URL` | Override the `plans/goat` docs URL |
181
- | `COMMANDCODE_DEALS_PRO_URL` | Override the `plans/pro` docs URL |
191
+ | Variable | Purpose |
192
+ | ----------------------------- | ------------------------------------------ |
193
+ | `COMMANDCODE_API_BASE` | Override the Command Code API base URL |
194
+ | `COMMANDCODE_FACTS_URL` | Override the bundled `models.md` URL |
195
+ | `COMMANDCODE_MODALITIES_URL` | Override the CLI bundle URL |
196
+ | `COMMANDCODE_RSC_PRICING_URL` | Override the `pricing-limits` RSC page URL |
197
+ | `COMMANDCODE_RSC_GOAT_URL` | Override the `plans/goat` RSC page URL |
198
+ | `COMMANDCODE_RSC_PRO_URL` | Override the `plans/pro` RSC page URL |
182
199
 
183
200
  ### Reasoning support
184
201
 
@@ -1,7 +1,7 @@
1
- export declare const FACTS_SOURCE_URL = "https://unpkg.com/command-code@1.32.1/dist/bundled/command-code-knowledge/reference/models.md";
2
- export declare const MODALITIES_SOURCE_URL = "https://unpkg.com/command-code@1.32.1/dist/cli.mjs";
3
- export declare const FACTS_PACKAGE_VERSION = "1.32.1";
4
- export declare const FACTS_LAST_REFRESHED = "2026-08-24";
1
+ export declare const FACTS_SOURCE_URL = "https://unpkg.com/command-code@1.37.0/dist/bundled/command-code-knowledge/reference/models.md";
2
+ export declare const MODALITIES_SOURCE_URL = "https://unpkg.com/command-code@1.37.0/dist/cli.mjs";
3
+ export declare const FACTS_PACKAGE_VERSION = "1.37.0";
4
+ export declare const FACTS_LAST_REFRESHED = "2026-08-28";
5
5
  export declare const MODEL_EFFORTS: Readonly<Record<string, readonly string[]>>;
6
6
  export declare const MODEL_COSTS: Readonly<Record<string, {
7
7
  input: number;
@@ -4,19 +4,20 @@
4
4
  // command-code npm package's bundled model catalog (models.md), plus input
5
5
  // modalities parsed from its CLI bundle (dist/cli.mjs). Regenerate
6
6
  // with `npm run refresh:snapshot`.
7
- export const FACTS_SOURCE_URL = "https://unpkg.com/command-code@1.32.1/dist/bundled/command-code-knowledge/reference/models.md";
8
- export const MODALITIES_SOURCE_URL = "https://unpkg.com/command-code@1.32.1/dist/cli.mjs";
9
- export const FACTS_PACKAGE_VERSION = "1.32.1";
10
- export const FACTS_LAST_REFRESHED = "2026-08-24";
7
+ export const FACTS_SOURCE_URL = "https://unpkg.com/command-code@1.37.0/dist/bundled/command-code-knowledge/reference/models.md";
8
+ export const MODALITIES_SOURCE_URL = "https://unpkg.com/command-code@1.37.0/dist/cli.mjs";
9
+ export const FACTS_PACKAGE_VERSION = "1.37.0";
10
+ export const FACTS_LAST_REFRESHED = "2026-08-28";
11
11
  export const MODEL_EFFORTS = {
12
12
  "deepseek/deepseek-v4-pro": ["high", "max"],
13
13
  "deepseek/deepseek-v4-flash": ["high", "max"],
14
14
  "deepseek/deepseek-v4-flash-vision-exp": ["high", "max"],
15
+ "z-ai/glm-5.3-flash": ["low", "high", "max"],
15
16
  "zai-org/GLM-5.3": ["low", "high", "max"],
16
17
  "zai-org/GLM-5.2": ["high", "max"],
17
18
  "Qwen/Qwen3.8-Max": ["low", "medium", "xhigh"],
18
19
  "Qwen/Qwen3.8-27B": ["low", "medium", "xhigh"],
19
- "stealth/ox-alpha": ["low", "high", "max"],
20
+ "Qwen/Qwen3.8-Flash": ["low", "medium", "xhigh"],
20
21
  "claude-sonnet-5": ["low", "medium", "high", "xhigh", "max"],
21
22
  "claude-sonnet-4-6": ["low", "medium", "high", "xhigh", "max"],
22
23
  "claude-fable-5": ["low", "medium", "high", "xhigh", "max"],
@@ -42,12 +43,13 @@ export const MODEL_EFFORTS = {
42
43
  export const MODEL_COSTS = {
43
44
  "deepseek/deepseek-v4-pro": { input: 0.66, output: 1.98, cacheRead: 0.022, cacheWrite: 0 },
44
45
  "deepseek/deepseek-v4-flash": { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 },
45
- "deepseek/deepseek-v4-flash-vision-exp": { input: 0.22, output: 0.66, cacheRead: 0.01, cacheWrite: 0 },
46
+ "deepseek/deepseek-v4-flash-vision-exp": { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 },
46
47
  "moonshotai/Kimi-K3": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 0 },
47
48
  "moonshotai/Kimi-K2.7-Code": { input: 0.95, output: 4, cacheRead: 0.19, cacheWrite: 0 },
48
49
  "moonshotai/Kimi-K2.7-Code-Highspeed": { input: 1.9, output: 8, cacheRead: 0.38, cacheWrite: 0 },
49
50
  "moonshotai/Kimi-K2.6": { input: 0.95, output: 4, cacheRead: 0.16, cacheWrite: 0 },
50
51
  "moonshotai/Kimi-K2.5": { input: 0.6, output: 3, cacheRead: 0.1, cacheWrite: 0 },
52
+ "z-ai/glm-5.3-flash": { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 },
51
53
  "zai-org/GLM-5.3": { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
52
54
  "zai-org/GLM-5.2": { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
53
55
  "zai-org/GLM-5.2-Fast": { input: 3, output: 10.25, cacheRead: 0.5, cacheWrite: 0 },
@@ -55,11 +57,14 @@ export const MODEL_COSTS = {
55
57
  "zai-org/GLM-5": { input: 1, output: 3.2, cacheRead: 0.2, cacheWrite: 0 },
56
58
  "MiniMaxAI/MiniMax-M3": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
57
59
  "MiniMaxAI/MiniMax-M2.7": { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
60
+ "minimax/minimax-m3-free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
61
+ "minimax/minimax-m2.7-free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
58
62
  "MiniMaxAI/MiniMax-M2.5": { input: 0.3, output: 1.2, cacheRead: 0.03, cacheWrite: 0 },
59
63
  "xiaomi/mimo-v2.5-pro": { input: 0.435, output: 0.87, cacheRead: 0.0036, cacheWrite: 0 },
60
64
  "xiaomi/mimo-v2.5": { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 },
61
65
  "Qwen/Qwen3.8-Max": { input: 2, output: 6, cacheRead: 0.25, cacheWrite: 2.5 },
62
66
  "Qwen/Qwen3.8-27B": { input: 0.4, output: 3, cacheRead: 0.04, cacheWrite: 0 },
67
+ "Qwen/Qwen3.8-Flash": { input: 0.16, output: 0.47, cacheRead: 0.016, cacheWrite: 0 },
63
68
  "Qwen/Qwen3.7-Max": { input: 2.5, output: 7.5, cacheRead: 0.5, cacheWrite: 3.13 },
64
69
  "Qwen/Qwen3.7-Plus": { input: 0.4, output: 1.6, cacheRead: 0.08, cacheWrite: 0.5 },
65
70
  "Qwen/Qwen3.7-Flash": { input: 0.03, output: 0.13, cacheRead: 0.006, cacheWrite: 0.038 },
@@ -68,11 +73,11 @@ export const MODEL_COSTS = {
68
73
  "stepfun/Step-3.7-Flash": { input: 0.2, output: 1.15, cacheRead: 0.04, cacheWrite: 0 },
69
74
  "stepfun/Step-3.5-Flash": { input: 0.1, output: 0.3, cacheRead: 0.02, cacheWrite: 0 },
70
75
  "tencent/hy3-paid": { input: 0.14, output: 0.58, cacheRead: 0.035, cacheWrite: 0 },
76
+ "tencent/hy4-preview": { input: 0.834, output: 2.501, cacheRead: 0.042, cacheWrite: 0 },
71
77
  "nvidia/nemotron-3-ultra-550b-a55b": { input: 0.6, output: 2.4, cacheRead: 0.12, cacheWrite: 0 },
72
78
  "thinkingmachines/inkling": { input: 1, output: 4.05, cacheRead: 0.17, cacheWrite: 0 },
73
79
  "thinkingmachines/inkling-small": { input: 0.5, output: 1.2, cacheRead: 0.1, cacheWrite: 0 },
74
80
  "poolside/laguna-s-2.1-free": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
75
- "stealth/ox-alpha": { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
76
81
  "claude-sonnet-5": { input: 2, output: 10, cacheRead: 0.2, cacheWrite: 2.5 },
77
82
  "claude-sonnet-4-6": { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
78
83
  "claude-fable-5": { input: 10, output: 50, cacheRead: 1, cacheWrite: 12.5 },
@@ -105,6 +110,7 @@ export const MODEL_INPUT_MODALITIES = {
105
110
  "Qwen/Qwen3.7-Flash": ["text", "image"],
106
111
  "Qwen/Qwen3.7-Plus": ["text", "image"],
107
112
  "Qwen/Qwen3.8-27B": ["text", "image"],
113
+ "Qwen/Qwen3.8-Flash": ["text", "image"],
108
114
  "Qwen/Qwen3.8-Max": ["text", "image"],
109
115
  "claude-fable-5": ["text", "image"],
110
116
  "claude-haiku-4-5-20251001": ["text", "image"],
@@ -129,16 +135,17 @@ export const MODEL_INPUT_MODALITIES = {
129
135
  "meta/muse-spark-1.1": ["text", "image"],
130
136
  "meta/muse-spark-1.2": ["text", "image"],
131
137
  "meta/muse-spark-1.2-contributor": ["text", "image"],
138
+ "minimax/minimax-m3-free": ["text", "image"],
132
139
  "moonshotai/Kimi-K2.5": ["text", "image"],
133
140
  "moonshotai/Kimi-K2.6": ["text", "image"],
134
141
  "moonshotai/Kimi-K2.7-Code": ["text", "image"],
135
142
  "moonshotai/Kimi-K2.7-Code-Highspeed": ["text", "image"],
136
143
  "moonshotai/Kimi-K3": ["text", "image"],
137
144
  "sakana/fugu-ultra": ["text", "image"],
138
- "stealth/ox-alpha": ["text", "image"],
139
145
  "stepfun/Step-3.7-Flash": ["text", "image"],
140
146
  "thinkingmachines/inkling": ["text", "image"],
141
147
  "thinkingmachines/inkling-small": ["text", "image"],
142
148
  "xai/grok-4.5": ["text", "image"],
143
149
  "xiaomi/mimo-v2.5": ["text", "image"],
150
+ "z-ai/glm-5.3-flash": ["text", "image"],
144
151
  };
@@ -26,6 +26,7 @@ export const MODEL_SNAPSHOT = [
26
26
  { id: "moonshotai/Kimi-K2.7-Code-Highspeed", name: "Kimi K2.7 Code HighSpeed", contextLength: 262000 },
27
27
  { id: "moonshotai/Kimi-K2.6", name: "Kimi K2.6", contextLength: 256000 },
28
28
  { id: "moonshotai/Kimi-K2.5", name: "Kimi K2.5", contextLength: 256000 },
29
+ { id: "z-ai/glm-5.3-flash", name: "GLM-5.3 Flash", contextLength: 1048576 },
29
30
  { id: "zai-org/GLM-5.3", name: "GLM-5.3", contextLength: 1000000 },
30
31
  { id: "zai-org/GLM-5.2", name: "GLM-5.2", contextLength: 1000000 },
31
32
  { id: "zai-org/GLM-5.2-Fast", name: "GLM-5.2 Fast", contextLength: 1000000 },
@@ -33,11 +34,14 @@ export const MODEL_SNAPSHOT = [
33
34
  { id: "zai-org/GLM-5", name: "GLM-5", contextLength: 200000 },
34
35
  { id: "MiniMaxAI/MiniMax-M3", name: "MiniMax M3", contextLength: 1000000 },
35
36
  { id: "MiniMaxAI/MiniMax-M2.7", name: "MiniMax M2.7", contextLength: 200000 },
37
+ { id: "minimax/minimax-m3-free", name: "MiniMax M3", contextLength: 1000000 },
38
+ { id: "minimax/minimax-m2.7-free", name: "MiniMax M2.7", contextLength: 197000 },
36
39
  { id: "MiniMaxAI/MiniMax-M2.5", name: "MiniMax M2.5", contextLength: 200000 },
37
40
  { id: "xiaomi/mimo-v2.5-pro", name: "MiMo V2.5 Pro", contextLength: 1000000 },
38
41
  { id: "xiaomi/mimo-v2.5", name: "MiMo V2.5", contextLength: 1000000 },
39
42
  { id: "Qwen/Qwen3.8-Max", name: "Qwen 3.8 Max", contextLength: 1000000 },
40
43
  { id: "Qwen/Qwen3.8-27B", name: "Qwen 3.8 27B", contextLength: 262144 },
44
+ { id: "Qwen/Qwen3.8-Flash", name: "Qwen 3.8 Flash", contextLength: 1000000 },
41
45
  { id: "Qwen/Qwen3.7-Max", name: "Qwen 3.7 Max", contextLength: 1000000 },
42
46
  { id: "Qwen/Qwen3.7-Plus", name: "Qwen 3.7 Plus", contextLength: 1000000 },
43
47
  { id: "Qwen/Qwen3.7-Flash", name: "Qwen 3.7 Flash", contextLength: 1000000 },
@@ -46,6 +50,7 @@ export const MODEL_SNAPSHOT = [
46
50
  { id: "stepfun/Step-3.7-Flash", name: "Step 3.7 Flash", contextLength: 256000 },
47
51
  { id: "stepfun/Step-3.5-Flash", name: "Step 3.5 Flash", contextLength: 1000000 },
48
52
  { id: "tencent/hy3-paid", name: "Tencent Hy3", contextLength: 262144 },
53
+ { id: "tencent/hy4-preview", name: "Tencent Hy4 Preview", contextLength: 1048576 },
49
54
  { id: "google/gemini-3.7-flash", name: "Gemini 3.7 Flash", contextLength: 1048576 },
50
55
  { id: "google/gemini-3.6-flash", name: "Gemini 3.6 Flash", contextLength: 1000000 },
51
56
  { id: "google/gemini-3.5-flash", name: "Gemini 3.5 Flash", contextLength: 1000000 },
@@ -55,7 +60,6 @@ export const MODEL_SNAPSHOT = [
55
60
  { id: "nvidia/nemotron-3-ultra-550b-a55b", name: "Nemotron 3 Ultra", contextLength: 1000000 },
56
61
  { id: "thinkingmachines/inkling", name: "Inkling", contextLength: 256000 },
57
62
  { id: "thinkingmachines/inkling-small", name: "Inkling Small", contextLength: 1000000 },
58
- { id: "stealth/ox-alpha", name: "Ox Alpha", contextLength: 1048576 },
59
63
  { id: "poolside/laguna-s-2.1-free", name: "Laguna S 2.1", contextLength: 256000 },
60
64
  { id: "meta/muse-spark-1.1", name: "Muse Spark 1.1", contextLength: 1048576 },
61
65
  { id: "meta/muse-spark-1.2", name: "Muse Spark 1.2", contextLength: 1048576 },
@@ -51,5 +51,5 @@ export interface ModelDeals {
51
51
  export declare const MODEL_DEALS: Readonly<Record<string, ModelDeals>>;
52
52
  export declare const PLAN_CATALOG: Readonly<Record<PlanId, PlanInfo>>;
53
53
  export declare const DEAL_SOURCE_URL = "https://commandcode.ai/docs/resources/pricing-limits";
54
- export declare const DEAL_LAST_REFRESHED = "2026-08-24";
54
+ export declare const DEAL_LAST_REFRESHED = "2026-08-28";
55
55
  export declare const DEAL_PACKAGE_VERSION = "docs";
@@ -5,64 +5,68 @@
5
5
  // enrich the model picker, the sidebar panel, and the plan summary tool
6
6
  // without network access at runtime. Regenerate with `npm run refresh:deals`.
7
7
  export const MODEL_DEALS = {
8
- "claude-fable-5": { tier: "premium", benchmark: { "intelligence": 62.1, "tokPerSec": 67.5 }, free: false },
9
- "claude-haiku-4-5-20251001": { tier: "premium", benchmark: { "intelligence": 24.1, "tokPerSec": 101.1 }, free: false, allowance: { "pro": 20 } },
10
- "claude-opus-4-7": { tier: "premium", benchmark: { "intelligence": 55 }, free: false },
11
- "claude-opus-4-8": { tier: "premium", benchmark: { "intelligence": 57.3 }, free: false },
12
- "claude-opus-5": { tier: "premium", benchmark: { "intelligence": 63.1, "tokPerSec": 54.4 }, free: false },
13
- "claude-sonnet-4-6": { tier: "premium", benchmark: { "intelligence": 48.4 }, free: false, allowance: { "pro": 20 } },
14
- "claude-sonnet-5": { tier: "premium", benchmark: { "intelligence": 55.3, "tokPerSec": 81.9 }, free: false, allowance: { "pro": 20 } },
15
- "deepseek/deepseek-v4-flash": { tier: "opensource", benchmark: { "intelligence": 51.8, "tokPerSec": 114.6 }, peakOffPeak: { "peak": { "input": 0.44, "output": 1.32, "cacheRead": 0.014, "cacheWrite": 0 }, "offPeak": { "input": 0.22, "output": 0.66, "cacheRead": 0.007, "cacheWrite": 0 }, "windows": "01–04 & 06–10 UTC" }, free: false, allowance: { "goat": 60, "pro": 70 } },
16
- "deepseek/deepseek-v4-flash-vision-exp": { tier: "opensource", peakOffPeak: { "peak": { "input": 0.44, "output": 1.32, "cacheRead": 0.02, "cacheWrite": 0 }, "offPeak": { "input": 0.22, "output": 0.66, "cacheRead": 0.01, "cacheWrite": 0 }, "windows": "01–04 & 06–10 UTC" }, free: false, allowance: { "goat": 20, "pro": 30 } },
17
- "deepseek/deepseek-v4-pro": { tier: "opensource", benchmark: { "intelligence": 53.2, "tokPerSec": 75.3 }, peakOffPeak: { "peak": { "input": 1.32, "output": 3.96, "cacheRead": 0.044, "cacheWrite": 0 }, "offPeak": { "input": 0.66, "output": 1.98, "cacheRead": 0.022, "cacheWrite": 0 }, "windows": "01–04 & 06–10 UTC" }, free: false, allowance: { "goat": 20, "pro": 30 } },
18
- "google/gemini-3.1-flash-lite": { tier: "premium", benchmark: { "intelligence": 25.6 }, free: false, allowance: { "pro": 20 } },
19
- "google/gemini-3.5-flash": { tier: "premium", benchmark: { "intelligence": 52 }, free: false, allowance: { "pro": 20 } },
20
- "google/gemini-3.5-flash-lite": { tier: "premium", benchmark: { "intelligence": 37.4, "tokPerSec": 361.2 }, free: false, allowance: { "pro": 20 } },
21
- "google/gemini-3.6-flash": { tier: "premium", benchmark: { "intelligence": 51.6, "tokPerSec": 187.4 }, free: false, allowance: { "pro": 20 } },
22
- "google/gemini-3.7-flash": { tier: "opensource", discount: { "pct": 50, "endsAt": "2026-12-31" }, was: { "input": 1.5, "output": 7.5, "cacheRead": 0.15 }, now: { "input": 0.75, "output": 3.75, "cacheRead": 0.075 }, benchmark: { "intelligence": 56, "tokPerSec": 339.4 }, free: false, allowance: { "goat": 40, "pro": 60 } },
23
- "gpt-5.3-codex": { tier: "premium", benchmark: { "intelligence": 45.5, "tokPerSec": 132.3 }, free: false, allowance: { "pro": 20 } },
24
- "gpt-5.4": { tier: "premium", benchmark: { "intelligence": 53.1 }, free: false, allowance: { "pro": 20 } },
25
- "gpt-5.4-mini": { tier: "premium", benchmark: { "intelligence": 40.9 }, free: false, allowance: { "pro": 20 } },
26
- "gpt-5.5": { tier: "premium", benchmark: { "intelligence": 56.3 }, free: false, allowance: { "pro": 20 } },
27
- "gpt-5.6-luna": { tier: "opensource", benchmark: { "intelligence": 52.3, "tokPerSec": 165 }, overContext: { "input": 0.4, "output": 1.8, "cacheRead": 0.04, "cacheWrite": 0.5 }, free: false, allowance: { "goat": 20, "pro": 30 } },
28
- "gpt-5.6-sol": { tier: "opensource", benchmark: { "intelligence": 60.9, "tokPerSec": 68.7 }, overContext: { "input": 10, "output": 45, "cacheRead": 1, "cacheWrite": 12.5 }, free: false, allowance: { "goat": 70, "pro": 80 } },
29
- "gpt-5.6-terra": { tier: "premium", benchmark: { "intelligence": 56.6, "tokPerSec": 117.1 }, overContext: { "input": 4, "output": 18, "cacheRead": 0.4, "cacheWrite": 5 }, free: false, allowance: { "pro": 20 } },
30
- "meta/muse-spark-1.1": { tier: "premium", benchmark: { "intelligence": 53.2 }, free: false, allowance: { "pro": 20 } },
8
+ "claude-fable-5": { tier: "premium", benchmark: { "intelligence": 62.1, "tokPerSec": 67.8 }, free: false, allowance: { "goat": 20, "pro": 20 } },
9
+ "claude-haiku-4-5-20251001": { tier: "premium", benchmark: { "intelligence": 24.1, "tokPerSec": 103.9 }, free: false, allowance: { "goat": 20, "pro": 20 } },
10
+ "claude-opus-4-7": { tier: "premium", benchmark: { "intelligence": 55 }, free: false, allowance: { "goat": 20, "pro": 20 } },
11
+ "claude-opus-4-8": { tier: "premium", benchmark: { "intelligence": 57.3 }, free: false, allowance: { "goat": 20, "pro": 20 } },
12
+ "claude-opus-5": { tier: "premium", benchmark: { "intelligence": 63.1, "tokPerSec": 55.5 }, free: false, allowance: { "goat": 20, "pro": 20 } },
13
+ "claude-sonnet-4-6": { tier: "premium", benchmark: { "intelligence": 48.4 }, free: false, allowance: { "goat": 20, "pro": 20 } },
14
+ "claude-sonnet-5": { tier: "premium", benchmark: { "intelligence": 55.3, "tokPerSec": 89.6 }, free: false, allowance: { "goat": 20, "pro": 20 } },
15
+ "deepseek/deepseek-v4-flash": { tier: "opensource", benchmark: { "intelligence": 51.8, "tokPerSec": 129 }, peakOffPeak: { "peak": { "input": 0.44, "output": 1.32, "cacheRead": 0.014, "cacheWrite": 0 }, "offPeak": { "input": 0.22, "output": 0.66, "cacheRead": 0.007, "cacheWrite": 0 }, "windows": "01–04 & 06–10 UTC" }, free: false, allowance: { "goat": 60, "pro": 70 } },
16
+ "deepseek/deepseek-v4-flash-vision-exp": { tier: "opensource", peakOffPeak: { "peak": { "input": 0.44, "output": 1.32, "cacheRead": 0.014, "cacheWrite": 0 }, "offPeak": { "input": 0.22, "output": 0.66, "cacheRead": 0.007, "cacheWrite": 0 }, "windows": "01–04 & 06–10 UTC" }, free: false, allowance: { "goat": 20, "pro": 30 } },
17
+ "deepseek/deepseek-v4-pro": { tier: "opensource", benchmark: { "intelligence": 53.2, "tokPerSec": 61 }, peakOffPeak: { "peak": { "input": 1.32, "output": 3.96, "cacheRead": 0.044, "cacheWrite": 0 }, "offPeak": { "input": 0.66, "output": 1.98, "cacheRead": 0.022, "cacheWrite": 0 }, "windows": "01–04 & 06–10 UTC" }, free: false, allowance: { "goat": 20, "pro": 30 } },
18
+ "google/gemini-3.1-flash-lite": { tier: "premium", benchmark: { "intelligence": 25.6 }, free: false, allowance: { "goat": 20, "pro": 20 } },
19
+ "google/gemini-3.5-flash": { tier: "premium", benchmark: { "intelligence": 52 }, free: false, allowance: { "goat": 20, "pro": 20 } },
20
+ "google/gemini-3.5-flash-lite": { tier: "premium", benchmark: { "intelligence": 37.4, "tokPerSec": 368.8 }, free: false, allowance: { "goat": 20, "pro": 20 } },
21
+ "google/gemini-3.6-flash": { tier: "premium", benchmark: { "intelligence": 51.6, "tokPerSec": 197.3 }, free: false, allowance: { "goat": 20, "pro": 20 } },
22
+ "google/gemini-3.7-flash": { tier: "opensource", discount: { "pct": 50, "endsAt": "2026-12-31" }, was: { "input": 1.5, "output": 7.5, "cacheRead": 0.15 }, now: { "input": 0.75, "output": 3.75, "cacheRead": 0.075 }, benchmark: { "intelligence": 56, "tokPerSec": 365.9 }, free: false, allowance: { "goat": 20, "pro": 30 } },
23
+ "gpt-5.3-codex": { tier: "premium", benchmark: { "intelligence": 45.5, "tokPerSec": 121.4 }, free: false, allowance: { "goat": 20, "pro": 20 } },
24
+ "gpt-5.4": { tier: "premium", benchmark: { "intelligence": 53.1 }, free: false, allowance: { "goat": 20, "pro": 20 } },
25
+ "gpt-5.4-mini": { tier: "premium", benchmark: { "intelligence": 40.9 }, free: false, allowance: { "goat": 20, "pro": 20 } },
26
+ "gpt-5.5": { tier: "premium", benchmark: { "intelligence": 56.3 }, free: false, allowance: { "goat": 20, "pro": 20 } },
27
+ "gpt-5.6-luna": { tier: "opensource", benchmark: { "intelligence": 52.3, "tokPerSec": 124.1 }, overContext: { "input": 0.4, "output": 1.8, "cacheRead": 0.04, "cacheWrite": 0.5 }, free: false, allowance: { "goat": 20, "pro": 30 } },
28
+ "gpt-5.6-sol": { tier: "opensource", benchmark: { "intelligence": 60.9, "tokPerSec": 69.6 }, overContext: { "input": 10, "output": 45, "cacheRead": 1, "cacheWrite": 12.5 }, free: false, allowance: { "goat": 70, "pro": 80 } },
29
+ "gpt-5.6-terra": { tier: "premium", benchmark: { "intelligence": 56.6, "tokPerSec": 112.8 }, overContext: { "input": 4, "output": 18, "cacheRead": 0.4, "cacheWrite": 5 }, free: false, allowance: { "goat": 20, "pro": 20 } },
30
+ "meta/muse-spark-1.1": { tier: "premium", benchmark: { "intelligence": 53.2 }, free: false, allowance: { "goat": 20, "pro": 20 } },
31
31
  "meta/muse-spark-1.2": { tier: "opensource", benchmark: { "intelligence": 56.8 }, free: false, allowance: { "goat": 20, "pro": 30 } },
32
32
  "meta/muse-spark-1.2-contributor": { tier: "opensource", benchmark: { "intelligence": 56.8 }, free: false, allowance: { "goat": 20, "pro": 30 } },
33
- "MiniMaxAI/MiniMax-M2.5": { tier: "opensource", benchmark: { "intelligence": 34.5 }, free: false },
34
- "MiniMaxAI/MiniMax-M2.7": { tier: "opensource", benchmark: { "intelligence": 38.9 }, free: false },
35
- "MiniMaxAI/MiniMax-M3": { tier: "opensource", discount: { "pct": 50 }, was: { "input": 0.6, "output": 2.4, "cacheRead": 0.12 }, now: { "input": 0.3, "output": 1.2, "cacheRead": 0.06 }, benchmark: { "intelligence": 45.4, "tokPerSec": 104.4 }, free: false, allowance: { "goat": 47, "pro": 57 } },
36
- "moonshotai/Kimi-K2.5": { tier: "opensource", benchmark: { "intelligence": 36 }, free: false },
37
- "moonshotai/Kimi-K2.6": { tier: "opensource", benchmark: { "intelligence": 45.1 }, free: false },
38
- "moonshotai/Kimi-K2.7-Code": { tier: "opensource", benchmark: { "intelligence": 43, "tokPerSec": 38.2 }, free: false, allowance: { "goat": 60, "pro": 70 } },
33
+ "minimax/minimax-m2.7-free": { tier: "opensource", free: true, benchmark: { "intelligence": 38.9 } },
34
+ "minimax/minimax-m3-free": { tier: "opensource", free: true, benchmark: { "intelligence": 45.4 } },
35
+ "MiniMaxAI/MiniMax-M2.5": { tier: "opensource", benchmark: { "intelligence": 34.5 }, free: false, allowance: { "goat": 20, "pro": 30 } },
36
+ "MiniMaxAI/MiniMax-M2.7": { tier: "opensource", benchmark: { "intelligence": 38.9 }, free: false, allowance: { "goat": 20, "pro": 30 } },
37
+ "MiniMaxAI/MiniMax-M3": { tier: "opensource", discount: { "pct": 50 }, was: { "input": 0.6, "output": 2.4, "cacheRead": 0.12 }, now: { "input": 0.3, "output": 1.2, "cacheRead": 0.06 }, benchmark: { "intelligence": 45.4, "tokPerSec": 111.3 }, free: false, allowance: { "goat": 47, "pro": 57 } },
38
+ "moonshotai/Kimi-K2.5": { tier: "opensource", benchmark: { "intelligence": 36 }, free: false, allowance: { "goat": 20, "pro": 30 } },
39
+ "moonshotai/Kimi-K2.6": { tier: "opensource", benchmark: { "intelligence": 45.1 }, free: false, allowance: { "goat": 20, "pro": 30 } },
40
+ "moonshotai/Kimi-K2.7-Code": { tier: "opensource", benchmark: { "intelligence": 43, "tokPerSec": 39.5 }, free: false, allowance: { "goat": 60, "pro": 70 } },
39
41
  "moonshotai/Kimi-K2.7-Code-Highspeed": { tier: "opensource", free: false, allowance: { "goat": 20, "pro": 30 } },
40
- "moonshotai/Kimi-K3": { tier: "opensource", benchmark: { "intelligence": 59.7, "tokPerSec": 38.6 }, free: false, allowance: { "goat": 20, "pro": 30 } },
41
- "nvidia/nemotron-3-ultra-550b-a55b": { tier: "opensource", benchmark: { "intelligence": 38.3, "tokPerSec": 135.8 }, free: false, allowance: { "goat": 20, "pro": 30 } },
42
+ "moonshotai/Kimi-K3": { tier: "opensource", benchmark: { "intelligence": 59.7, "tokPerSec": 38.4 }, free: false, allowance: { "goat": 20, "pro": 30 } },
43
+ "nvidia/nemotron-3-ultra-550b-a55b": { tier: "opensource", benchmark: { "intelligence": 38.3, "tokPerSec": 174.2 }, free: false, allowance: { "goat": 20, "pro": 30 } },
42
44
  "poolside/laguna-s-2.1-free": { tier: "opensource", free: true },
43
- "Qwen/Qwen3.6-Max-Preview": { tier: "opensource", benchmark: { "intelligence": 41.1 }, free: false },
45
+ "Qwen/Qwen3.6-Max-Preview": { tier: "opensource", benchmark: { "intelligence": 41.1 }, free: false, allowance: { "goat": 20, "pro": 30 } },
44
46
  "Qwen/Qwen3.6-Plus": { tier: "opensource", benchmark: { "intelligence": 40.5 }, overContext: { "input": 2, "output": 6, "cacheRead": 0.2, "cacheWrite": 0 }, free: false, allowance: { "goat": 33, "pro": 43 } },
45
- "Qwen/Qwen3.7-Flash": { tier: "opensource", overContext: { "input": 0.2, "output": 0.8, "cacheRead": 0.04, "cacheWrite": 0.25 }, free: false },
46
- "Qwen/Qwen3.7-Max": { tier: "opensource", benchmark: { "intelligence": 46.7 }, free: false, allowance: { "goat": 33, "pro": 43 } },
47
- "Qwen/Qwen3.7-Plus": { tier: "opensource", benchmark: { "intelligence": 39.4, "tokPerSec": 55.6 }, overContext: { "input": 1.2, "output": 4.8, "cacheRead": 0.24, "cacheWrite": 1.5 }, free: false, allowance: { "goat": 33, "pro": 43 } },
48
- "Qwen/Qwen3.8-27B": { tier: "opensource", benchmark: { "intelligence": 52 }, free: false, allowance: { "goat": 70, "pro": 80 } },
49
- "Qwen/Qwen3.8-Max": { tier: "opensource", benchmark: { "intelligence": 58.1, "tokPerSec": 46.7 }, free: false, allowance: { "goat": 20, "pro": 30 } },
50
- "sakana/fugu-ultra": { tier: "premium", free: false },
51
- "stealth/ox-alpha": { tier: "opensource", free: true },
47
+ "Qwen/Qwen3.7-Flash": { tier: "opensource", overContext: { "input": 0.2, "output": 0.8, "cacheRead": 0.04, "cacheWrite": 0.25 }, free: false, allowance: { "goat": 20, "pro": 30 } },
48
+ "Qwen/Qwen3.7-Max": { tier: "opensource", discount: { "pct": 50, "endsAt": "2026-06-22" }, was: { "input": 5, "output": 15, "cacheRead": 1 }, now: { "input": 2.5, "output": 7.5, "cacheRead": 0.5 }, benchmark: { "intelligence": 46.7 }, free: false, allowance: { "goat": 33, "pro": 43 } },
49
+ "Qwen/Qwen3.7-Plus": { tier: "opensource", benchmark: { "intelligence": 39.4, "tokPerSec": 55.5 }, overContext: { "input": 1.2, "output": 4.8, "cacheRead": 0.24, "cacheWrite": 1.5 }, free: false, allowance: { "goat": 33, "pro": 43 } },
50
+ "Qwen/Qwen3.8-27B": { tier: "opensource", benchmark: { "intelligence": 52, "tokPerSec": 50.5 }, free: false, allowance: { "goat": 70, "pro": 80 } },
51
+ "Qwen/Qwen3.8-Flash": { tier: "opensource", free: false, allowance: { "goat": 20, "pro": 30 } },
52
+ "Qwen/Qwen3.8-Max": { tier: "opensource", benchmark: { "intelligence": 58.1, "tokPerSec": 23.6 }, free: false, allowance: { "goat": 20, "pro": 30 } },
53
+ "sakana/fugu-ultra": { tier: "premium", free: false, allowance: { "goat": 20, "pro": 20 } },
52
54
  "stepfun/Step-3.5-Flash": { tier: "opensource", benchmark: { "intelligence": 26.5 }, free: false, allowance: { "goat": 20, "pro": 30 } },
53
- "stepfun/Step-3.7-Flash": { tier: "opensource", benchmark: { "intelligence": 30.9, "tokPerSec": 120.1 }, free: false, allowance: { "goat": 20, "pro": 30 } },
54
- "tencent/hy3-paid": { tier: "opensource", benchmark: { "intelligence": 42.2, "tokPerSec": 74.8 }, free: false, allowance: { "goat": 70, "pro": 80 } },
55
- "thinkingmachines/inkling": { tier: "opensource", benchmark: { "intelligence": 42.3, "tokPerSec": 69.8 }, free: false, allowance: { "goat": 20, "pro": 30 } },
56
- "thinkingmachines/inkling-small": { tier: "opensource", benchmark: { "intelligence": 41.2, "tokPerSec": 61.3 }, free: false, allowance: { "goat": 20, "pro": 30 } },
57
- "xai/grok-4.5": { tier: "opensource", benchmark: { "intelligence": 55.8, "tokPerSec": 51 }, free: false, allowance: { "goat": 20, "pro": 30 } },
58
- "xai/grok-4.6": { tier: "opensource", benchmark: { "intelligence": 60.9, "tokPerSec": 66 }, overContext: { "input": 4, "output": 12, "cacheRead": 1, "cacheWrite": 0 }, free: false, allowance: { "goat": 20, "pro": 30 } },
59
- "xiaomi/mimo-v2.5": { tier: "opensource", discount: { "pct": 98 }, was: { "input": 0.8, "output": 4, "cacheRead": 0.16 }, now: { "input": 0.14, "output": 0.28, "cacheRead": 0.0028 }, benchmark: { "intelligence": 38, "tokPerSec": 61.8 }, free: false, allowance: { "goat": 30, "pro": 40 } },
60
- "xiaomi/mimo-v2.5-pro": { tier: "opensource", discount: { "pct": 99 }, was: { "input": 2, "output": 6, "cacheRead": 0.4 }, now: { "input": 0.435, "output": 0.87, "cacheRead": 0.0036 }, benchmark: { "intelligence": 42.9, "tokPerSec": 58.1 }, free: false, allowance: { "goat": 20, "pro": 30 } },
61
- "zai-org/GLM-5": { tier: "opensource", benchmark: { "intelligence": 40.6 }, free: false },
62
- "zai-org/GLM-5.1": { tier: "opensource", benchmark: { "intelligence": 41, "tokPerSec": 28.2 }, free: false },
63
- "zai-org/GLM-5.2": { tier: "opensource", benchmark: { "intelligence": 52.6, "tokPerSec": 69 }, free: false, allowance: { "goat": 70, "pro": 80 } },
55
+ "stepfun/Step-3.7-Flash": { tier: "opensource", benchmark: { "intelligence": 30.9, "tokPerSec": 94.1 }, free: false, allowance: { "goat": 20, "pro": 30 } },
56
+ "tencent/hy3-paid": { tier: "opensource", benchmark: { "intelligence": 42.2, "tokPerSec": 69.1 }, free: false, allowance: { "goat": 70, "pro": 80 } },
57
+ "tencent/hy4-preview": { tier: "opensource", free: false, allowance: { "goat": 20, "pro": 30 } },
58
+ "thinkingmachines/inkling": { tier: "opensource", benchmark: { "intelligence": 42.3, "tokPerSec": 50.6 }, free: false, allowance: { "goat": 20, "pro": 30 } },
59
+ "thinkingmachines/inkling-small": { tier: "opensource", benchmark: { "intelligence": 41.2, "tokPerSec": 115.5 }, free: false, allowance: { "goat": 20, "pro": 30 } },
60
+ "xai/grok-4.5": { tier: "opensource", benchmark: { "intelligence": 55.8, "tokPerSec": 48.7 }, free: false, allowance: { "goat": 20, "pro": 30 } },
61
+ "xai/grok-4.6": { tier: "opensource", benchmark: { "intelligence": 60.9, "tokPerSec": 60.8 }, overContext: { "input": 4, "output": 12, "cacheRead": 1, "cacheWrite": 0 }, free: false, allowance: { "goat": 20, "pro": 30 } },
62
+ "xiaomi/mimo-v2.5": { tier: "opensource", discount: { "pct": 98 }, was: { "input": 0.8, "output": 4, "cacheRead": 0.16 }, now: { "input": 0.14, "output": 0.28, "cacheRead": 0.0028 }, benchmark: { "intelligence": 38, "tokPerSec": 64.1 }, free: false, allowance: { "goat": 30, "pro": 40 } },
63
+ "xiaomi/mimo-v2.5-pro": { tier: "opensource", discount: { "pct": 99 }, was: { "input": 2, "output": 6, "cacheRead": 0.4 }, now: { "input": 0.435, "output": 0.87, "cacheRead": 0.0036 }, benchmark: { "intelligence": 42.9, "tokPerSec": 43.1 }, free: false, allowance: { "goat": 20, "pro": 30 } },
64
+ "z-ai/glm-5.3-flash": { tier: "opensource", benchmark: { "intelligence": 57.5, "tokPerSec": 41.8 }, free: false, allowance: { "goat": 40, "pro": 50 } },
65
+ "zai-org/GLM-5": { tier: "opensource", benchmark: { "intelligence": 40.6 }, free: false, allowance: { "goat": 20, "pro": 30 } },
66
+ "zai-org/GLM-5.1": { tier: "opensource", benchmark: { "intelligence": 41 }, free: false, allowance: { "goat": 20, "pro": 30 } },
67
+ "zai-org/GLM-5.2": { tier: "opensource", benchmark: { "intelligence": 52.6, "tokPerSec": 68.9 }, free: false, allowance: { "goat": 70, "pro": 80 } },
64
68
  "zai-org/GLM-5.2-Fast": { tier: "opensource", free: false, allowance: { "goat": 20, "pro": 30 } },
65
- "zai-org/GLM-5.3": { tier: "opensource", benchmark: { "intelligence": 59.5, "tokPerSec": 79.6 }, free: false, allowance: { "goat": 20, "pro": 30 } },
69
+ "zai-org/GLM-5.3": { tier: "opensource", benchmark: { "intelligence": 59.5, "tokPerSec": 80.6 }, free: false, allowance: { "goat": 20, "pro": 30 } },
66
70
  };
67
71
  export const PLAN_CATALOG = {
68
72
  go: { price: 1, credits: 10, window5h: 3, windowWeek: 6, display: "Go" },
@@ -74,5 +78,5 @@ export const PLAN_CATALOG = {
74
78
  provider: { price: 15, credits: 0, window5h: 0, windowWeek: 0, display: "Provider" },
75
79
  };
76
80
  export const DEAL_SOURCE_URL = "https://commandcode.ai/docs/resources/pricing-limits";
77
- export const DEAL_LAST_REFRESHED = "2026-08-24";
81
+ export const DEAL_LAST_REFRESHED = "2026-08-28";
78
82
  export const DEAL_PACKAGE_VERSION = "docs";
@@ -1,4 +1,4 @@
1
- import { MODEL_COSTS, ZERO_MODEL_COST } from "../provider/pricing.js";
1
+ import { MODEL_COSTS, ZERO_MODEL_COST, isFreeModelCost, } from "../provider/pricing.js";
2
2
  import { reasoningVariantsForModel, isReasoningModel } from "../provider/reasoning.js";
3
3
  import { inputModalitiesForModel } from "../provider/modalities.js";
4
4
  const DEFAULT_MAX_OUTPUT_TOKENS = 65_536;
@@ -95,8 +95,14 @@ export function augmentConfigCommandCodeModels(config) {
95
95
  function configModelFor(model, prefix = DEFAULT_DISPLAY_PREFIX) {
96
96
  const variants = reasoningVariantsForModel(model.id);
97
97
  const costs = MODEL_COSTS[model.id] ?? ZERO_MODEL_COST;
98
+ // Upstream names the paid and free MiniMax variants identically
99
+ // (`MiniMax M3` / `MiniMax M2.7`); append `(free)` to the picker entry so
100
+ // users can tell them apart. Data-driven from the zero cost table — a model
101
+ // is only "free" when the catalog has an actual zero-cost entry (an absent
102
+ // entry falls back to ZERO_MODEL_COST and is NOT free).
103
+ const freeSuffix = MODEL_COSTS[model.id] !== undefined && isFreeModelCost(costs) ? " (free)" : "";
98
104
  return {
99
- name: `${prefix}${model.name}`,
105
+ name: `${prefix}${model.name}${freeSuffix}`,
100
106
  limit: {
101
107
  context: model.contextLength,
102
108
  output: Math.min(model.contextLength, DEFAULT_MAX_OUTPUT_TOKENS),
@@ -9,3 +9,10 @@ export interface CommandCodeModelCostRates {
9
9
  export interface CommandCodeModelCost extends CommandCodeModelCostRates {
10
10
  }
11
11
  export declare const ZERO_MODEL_COST: CommandCodeModelCost;
12
+ /**
13
+ * True when every rate is zero — the model is served free (e.g. the MiniMax
14
+ * M3 / M2.7 free variants). Used to disambiguate display names: the upstream
15
+ * catalog names the paid and free variants identically (`MiniMax M3`), so the
16
+ * auto-registered picker entry appends `(free)` when this matches.
17
+ */
18
+ export declare function isFreeModelCost(cost: CommandCodeModelCost | undefined): boolean;
@@ -8,3 +8,16 @@ export const ZERO_MODEL_COST = {
8
8
  cacheRead: 0,
9
9
  cacheWrite: 0,
10
10
  };
11
+ /**
12
+ * True when every rate is zero — the model is served free (e.g. the MiniMax
13
+ * M3 / M2.7 free variants). Used to disambiguate display names: the upstream
14
+ * catalog names the paid and free variants identically (`MiniMax M3`), so the
15
+ * auto-registered picker entry appends `(free)` when this matches.
16
+ */
17
+ export function isFreeModelCost(cost) {
18
+ return (cost !== undefined &&
19
+ cost.input === 0 &&
20
+ cost.output === 0 &&
21
+ cost.cacheRead === 0 &&
22
+ cost.cacheWrite === 0);
23
+ }
@@ -29,14 +29,16 @@ export const REASONING_MODELS = new Set([
29
29
  "meta/muse-spark-1.1",
30
30
  "meta/muse-spark-1.2",
31
31
  "meta/muse-spark-1.2-contributor",
32
+ "minimax/minimax-m3-free",
32
33
  "moonshotai/Kimi-K2.7-Code",
33
34
  "moonshotai/Kimi-K2.7-Code-Highspeed",
34
35
  "moonshotai/Kimi-K3",
35
36
  "nvidia/nemotron-3-ultra-550b-a55b",
36
37
  "poolside/laguna-s-2.1-free",
37
- "stealth/ox-alpha",
38
38
  "stepfun/Step-3.7-Flash",
39
39
  "tencent/hy3-paid",
40
+ // Live RSC caps.reasoning=true, models.md has no Efforts entry (2026-08-28).
41
+ "tencent/hy4-preview",
40
42
  "thinkingmachines/inkling",
41
43
  "thinkingmachines/inkling-small",
42
44
  ]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-cmd-provider",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "Command Code provider + plugin for opencode",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -20,15 +20,16 @@
20
20
  "typecheck": "tsc --noEmit",
21
21
  "refresh:snapshot": "node scripts/refresh-snapshot.mjs",
22
22
  "refresh:deals": "node scripts/refresh-deals.mjs",
23
- "refresh": "npm run refresh:snapshot && npm run refresh:deals -- --fixtures",
23
+ "refresh": "npm run refresh:snapshot && npm run refresh:fixtures && npm run refresh:deals -- --fixtures",
24
24
  "test": "npm run typecheck && npm run test:unit && npm run test:integration && npm run test:contract && npm run format:check",
25
- "test:unit": "tsx tests/env.test.ts && tsx tests/auth-key.test.ts && tsx tests/converters.test.ts && tsx tests/stream.test.ts && tsx tests/provider-codecs.test.ts && tsx tests/provider-transport.test.ts && tsx tests/provider-parity.test.ts && tsx tests/provider-upgrade-fallback.test.ts && tsx tests/provider-zdr.test.ts && tsx tests/redact.test.ts && tsx tests/cost.test.ts && tsx tests/retry.test.ts && tsx tests/reasoning.test.ts && tsx tests/modalities.test.ts && tsx tests/snapshot.test.ts && tsx tests/refresh-snapshot.test.ts && tsx tests/oauth.test.ts && tsx tests/auth-mirror.test.ts && tsx tests/parse-facts.test.ts && tsx tests/parse-modalities.test.ts && tsx tests/catalog-metadata.test.ts && tsx tests/plugin-models.test.ts && tsx tests/vendor.test.ts && tsx tests/deals-enrichment.test.ts && tsx tests/deals-coverage.test.ts && tsx tests/plan-summary.test.ts && tsx tests/html-tables.test.ts && tsx tests/parse-docs.test.ts && tsx tests/refresh-deals.test.ts && tsx tests/tui-deals-panel.test.ts && tsx tests/plugin-install.test.ts",
25
+ "test:unit": "tsx tests/env.test.ts && tsx tests/auth-key.test.ts && tsx tests/converters.test.ts && tsx tests/stream.test.ts && tsx tests/provider-codecs.test.ts && tsx tests/provider-transport.test.ts && tsx tests/provider-parity.test.ts && tsx tests/provider-upgrade-fallback.test.ts && tsx tests/provider-zdr.test.ts && tsx tests/redact.test.ts && tsx tests/cost.test.ts && tsx tests/retry.test.ts && tsx tests/reasoning.test.ts && tsx tests/modalities.test.ts && tsx tests/snapshot.test.ts && tsx tests/refresh-snapshot.test.ts && tsx tests/oauth.test.ts && tsx tests/auth-mirror.test.ts && tsx tests/parse-facts.test.ts && tsx tests/parse-modalities.test.ts && tsx tests/catalog-metadata.test.ts && tsx tests/plugin-models.test.ts && tsx tests/vendor.test.ts && tsx tests/deals-enrichment.test.ts && tsx tests/deals-coverage.test.ts && tsx tests/plan-summary.test.ts && tsx tests/html-tables.test.ts && tsx tests/parse-docs.test.ts && tsx tests/parse-rsc.test.ts && tsx tests/mock-cc-rsc.test.ts && tsx tests/capture-rsc-fixtures.test.ts && tsx tests/refresh-deals.test.ts && tsx tests/refresh-deals-rsc.test.ts && tsx tests/tier-overrides.test.ts && tsx tests/tui-deals-panel.test.ts && tsx tests/diff-catalog.test.ts && tsx tests/plugin-install.test.ts",
26
26
  "test:integration": "tsx tests/integration-do-stream.test.ts && tsx tests/integration-do-generate.test.ts",
27
27
  "test:contract": "tsx tests/contract.test.ts",
28
28
  "test:e2e": "node tests/e2e-opencode.mjs",
29
29
  "build:tui": "bun scripts/build-tui.ts",
30
30
  "format": "prettier --write '**/*.{ts,mjs,json,md}'",
31
- "format:check": "prettier --check '**/*.{ts,mjs,json,md}'"
31
+ "format:check": "prettier --check '**/*.{ts,mjs,json,md}'",
32
+ "refresh:fixtures": "node scripts/capture-rsc-fixtures.mjs"
32
33
  },
33
34
  "keywords": [
34
35
  "opencode",