@chenlongapps/opencode-token-usage 0.4.3 → 0.4.5

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
@@ -34,7 +34,7 @@ Alternatively, add the package to your project's `opencode.json` or `opencode.js
34
34
  ```
35
35
 
36
36
  > [!NOTE]
37
- > Requires Node.js 22+. OpenCode 2.0.9, 2.0.10, and 2.0.11 have been verified across project releases. The current SDK 2.0.11 build has been reverified on OpenCode 2.0.11.
37
+ > Requires Node.js 22+. OpenCode 2.0.9, 2.0.10, and 2.0.11 have been verified across project releases. The current SDK 2.0.11 build has been reverified on OpenCode 2.0.11 and 2.0.22.
38
38
 
39
39
  Restart OpenCode after installation. The panel appears in the native sidebar when `session.sidebar` is set to `auto` and the terminal is wide enough. OpenCode hides the sidebar in subagent views, so the plugin keeps one live summary line above the composer with Context, Total, Cost, and TPS. Click the line to open the full statistics in a centered dialog. Press Escape or click **esc** to close it; closing the dialog does not interrupt the subagent.
40
40
 
@@ -74,7 +74,7 @@ Costs follow the sidebar's pricing and `partial`/unavailable/free conventions. I
74
74
  | `Context` | Latest context usage after the most recent completed compaction in the viewed session; not aggregated across the subtree |
75
75
  | `Steps` | Assistant message count across the session tree, including subagents; follows OpenCode's own stats definition, so compaction and user messages are not steps |
76
76
  | `Est. Cost` | Estimated cost across the tree, pricing each assistant and compaction call with its actual model |
77
- | `TPS` | Generation throughput for `Output + Reasoning` across the tree; live estimates are marked with `~` |
77
+ | `TPS` | Generation throughput for `Output + Reasoning` across the tree. While streaming, it estimates recent observable text, reasoning-summary and tool-input deltas (UTF-8 bytes / 4) over a short sliding window after the first delta, excluding pre-first-token waiting, and marks the value with `~`. APIs such as OpenAI Responses do not expose complete hidden reasoning tokens in real time, so live values cannot represent hidden reasoning throughput. After completion it uses provider-reported Output and Reasoning tokens and removes `~` |
78
78
  | `TTFT` | Average time to first token across measurable assistant steps in the tree |
79
79
 
80
80
  #### Behavior
@@ -86,6 +86,7 @@ Costs follow the sidebar's pricing and `partial`/unavailable/free conventions. I
86
86
  - `Est. Cost` prices every message with its recorded model. A complete non-zero price resolved by OpenCode takes precedence. If OpenCode reports a complete zero price, a complete first-party snapshot price overrides it; incomplete prices fall back for the whole message without mixing rates.
87
87
  - The checked-in fallback snapshot is generated from [models.dev](https://models.dev/api.json) using only reviewed first-party provider/model families; a small set of manufacturer-verified exceptions is kept separately. It covers priced text models, without downloading prices while the plugin runs. Gateway models match exact manufacturer IDs, documented aliases, and known wrappers; only a terminal `-free` or `:free` can be removed for a second exact lookup.
88
88
  - Confirmed free usage displays `$0.00`; unavailable prices display `—`; known subtotals with unpriced messages are marked `partial`. The snapshot excludes gateway markups, regional premiums, unlisted discounts, non-text billing, tool fees, and taxes, so Est. Cost is not a provider bill. See [price sources and limitations](docs/pricing.md).
89
+ - Live `TPS` with `~` is an estimate from recent observable deltas after the first delta over a ~2s sliding window with light smoothing; it excludes TTFT and hidden-reasoning waits. Without `~` it is exact provider-reported `Output + Reasoning` throughput. No model-specific multipliers or hidden-reasoning guesses are applied.
89
90
  - Initial read failures display `Unavailable`. Later failures retain the last complete snapshot, display `Not updated`, and retry automatically.
90
91
 
91
92
  ### Development
@@ -98,12 +99,24 @@ npm run build
98
99
  npm run test:smoke
99
100
  ```
100
101
 
101
- The [price update workflow](.github/workflows/update-prices.yml) checks models.dev every day at 03:17 UTC (or on demand via **Run workflow**). No snapshot diff means no pull request; a diff that passes typecheck, tests, build, and pack validation opens or updates one review-only PR containing `src/prices.generated.ts`. Enable **Allow GitHub Actions to create and approve pull requests** under repository Actions settings. PRs created with `GITHUB_TOKEN` do not trigger a second CI run, so the update workflow runs the checks before opening the PR. Nothing is merged or published automatically.
102
+ The [price update workflow](.github/workflows/update-prices.yml) checks models.dev every day at 22:00 UTC (or on demand via **Run workflow** on `main`). No snapshot diff means no release. Changes within the reviewed first-party source allowlist pass typecheck, tests, build, and pack validation, then automatically bump the patch version (for example, `0.4.4` → `0.4.5`), commit only `src/prices.generated.ts`, `package.json`, and `package-lock.json`, and atomically push `main` and its version tag. The workflow creates a GitHub Release and explicitly dispatches [`publish.yml`](.github/workflows/publish.yml) on that tag to publish via npm Trusted Publishing/OIDC; no long-lived npm token is needed. GitHub Actions must be allowed to push to `main` and create tags, and npm must trust `publish.yml` with permission to run `npm publish`.
103
+
104
+ Failed validation never bumps the version. An unfinished tagged price release is retried with the same version before checking new prices; registry outages are not treated as missing versions. Publishing skips versions already on npm, prevents moving `latest` backwards, and verifies registry visibility after publication. Manufacturer/source allowlist additions, aliases, and manually verified price exceptions still require human review. See the [release guide](docs/releasing.md) for setup and retries.
102
105
 
103
106
  For a manual refresh, run `npm run prices:update` in a networked environment, review the generated diff and exceptions, then run the checks above. Builds and plugin refreshes do not contact models.dev.
104
107
 
105
108
  `test:smoke` packages the real artifact and validates loading, refreshes, `/usage`, subagent aggregation, per-message pricing, first-party price fallback, model switching, TPS, and TTFT against an isolated OpenCode instance and a local mock provider. It requires Python 3, an available local port, and npm network access. It never modifies your existing OpenCode configuration or calls paid models.
106
109
 
110
+ By default, smoke uses `opencode` from `PATH`. Stable OpenCode 2 versions from 2.0.9 onward can run; a host not yet verified with the current SDK prints a warning and continues through the actual compatibility checks. Passing the version check alone does not establish compatibility. The SDK dependencies remain pinned independently of your local CLI updates.
111
+
112
+ To reproduce a baseline with a separately installed binary, without downgrading your normal installation:
113
+
114
+ ```bash
115
+ OPENCODE_BIN=/absolute/path/to/opencode-2.0.11 npm run test:smoke
116
+ ```
117
+
118
+ `OPENCODE_BIN` selects the same executable for the version check, isolated server, and TUI. Relative paths resolve from the directory where you run the command. The host version and selected binary are recorded in the smoke output and `result.json`; see the [verification record](docs/verification.md) for tested combinations.
119
+
107
120
  To load the plugin from source, build the project and add the repository's absolute path to `plugins` in the target project.
108
121
 
109
122
  ### Documentation
package/README.zh-CN.md CHANGED
@@ -34,7 +34,7 @@ opencode plugin add @chenlongapps/opencode-token-usage
34
34
  ```
35
35
 
36
36
  > [!NOTE]
37
- > 需要 Node.js 22+。项目历次发布已验证 OpenCode 2.0.9、2.0.10 和 2.0.11;当前 SDK 2.0.11 构建已在 OpenCode 2.0.11 上重新验证。
37
+ > 需要 Node.js 22+。项目历次发布已验证 OpenCode 2.0.9、2.0.10 和 2.0.11;当前 SDK 2.0.11 构建已在 OpenCode 2.0.11 和 2.0.22 上重新验证。
38
38
 
39
39
  安装后重启 OpenCode。终端足够宽且 `session.sidebar` 设为 `auto` 时,面板会显示在原生侧边栏中。OpenCode 在子代理视图中隐藏侧边栏,因此插件会在输入区上方保留一行实时摘要,显示 Context、Total、Cost 和 TPS。点击摘要可在居中弹窗中查看完整统计;按 Escape 或点击 **esc** 即可关闭,关闭弹窗不会中断子代理。
40
40
 
@@ -74,7 +74,7 @@ opencode plugin add @chenlongapps/opencode-token-usage
74
74
  | `Context` | 当前会话最后一次已完成压缩后的最新上下文用量,不随子树累计 |
75
75
  | `Steps` | 全树(含子代理)的 assistant 消息数,口径与 OpenCode 自带统计一致,compaction 与用户消息不计为 step |
76
76
  | `Est. Cost` | 按每条 assistant 与 compaction 消息实际模型估算的全树费用 |
77
- | `TPS` | 全树 `Output + Reasoning` 的生成速度;生成中的估算值带 `~` 标记 |
77
+ | `TPS` | 全树 `Output + Reasoning` 的生成吞吐。请求进行中时,插件根据首个流式增量之后最近的可观察文本、reasoning summary 和工具输入流(UTF-8 字节数 / 4)按短时间滑动窗口估算输出速度,不包含首 token 前等待时间,并以 `~` 标记。OpenAI Responses 等 API 不会实时暴露完整的隐藏 reasoning token,因此实时值不能表示隐藏推理吞吐。请求完成后,插件使用服务端上报的 Output 与 Reasoning token 及时间信息计算精确 TPS,并移除 `~` 标记 |
78
78
  | `TTFT` | 全树中可测 assistant step 的平均首 token 时间 |
79
79
 
80
80
  #### 行为
@@ -86,6 +86,7 @@ opencode plugin add @chenlongapps/opencode-token-usage
86
86
  - `Est. Cost` 按每条消息记录的实际模型分别计算。OpenCode 当前解析出的完整非零价格优先;若 OpenCode 给出完整零价,且内置价格快照可以完整计价,则采用快照价格。价格不完整时整条消息回退,不混用两套费率。
87
87
  - 内置回退快照从 [models.dev](https://models.dev/api.json) 生成,只采用审核过的原厂 Provider 与自家模型系列;少量经原厂核实的例外单独维护。快照覆盖有价格的文本模型,插件运行时不下载价格。网关模型通过精确原厂 ID、明确别名和已知包装格式匹配;只有终尾 `-free` 或 `:free` 会在再次精确查找前移除。
88
88
  - 确认免费时显示 `$0.00`;价格不可用时显示 `—`;只有部分消息可计算时在已知小计后标注 `partial`。快照不含网关加价、区域溢价、未列明的折扣、非文本计费、工具费和税费;Est. Cost 是估算而非账单。覆盖范围、来源和限制见[价格来源与限制](docs/pricing.md)。
89
+ - 带 `~` 的实时 `TPS` 是首个流式增量之后约 2 秒滑动窗口内可观察增量的估算值(带轻度平滑),不包含 TTFT 与隐藏推理等待;不带 `~` 时为服务端上报的 `Output + Reasoning` 精确吞吐。不做模型专属倍率,也不猜测隐藏 reasoning token。
89
90
  - 首次读取失败显示 `Unavailable`;后续失败保留上次完整快照、标注 `Not updated` 并自动重试。
90
91
 
91
92
  ### 开发
@@ -98,12 +99,24 @@ npm run build
98
99
  npm run test:smoke
99
100
  ```
100
101
 
101
- [价格更新工作流](.github/workflows/update-prices.yml) 每天 UTC 03:17 检查 models.dev,也可通过 **Run workflow** 手动触发。快照无变化就不创建 PR;有变化且通过类型检查、测试、构建和打包检查时,只对 `src/prices.generated.ts` 创建或更新同一个待审 PR。需在仓库 Actions 设置中启用 **Allow GitHub Actions to create and approve pull requests**。使用 `GITHUB_TOKEN` 创建的 PR 不会再次触发 CI,因此更新工作流会先完成检查;不会自动合并或发布。
102
+ [价格更新工作流](.github/workflows/update-prices.yml) 每天 UTC 22:00 检查 models.dev,也可在 `main` 上通过 **Run workflow** 手动触发。快照无变化就不发布。经审核的原厂来源白名单内有变化时,先通过类型检查、测试、构建和打包检查,再自动升级 patch 版本(例如 `0.4.4` → `0.4.5`),只提交 `src/prices.generated.ts`、`package.json` 和 `package-lock.json`,并原子推送 `main` 与版本标签。工作流创建 GitHub Release,显式触发该标签上的 [`publish.yml`](.github/workflows/publish.yml),通过 npm Trusted Publishing/OIDC 发布,无需长期 npm token。仓库必须允许 GitHub Actions 推送 `main` 和创建标签;npm 必须信任 `publish.yml` 并允许执行 `npm publish`。
103
+
104
+ 验证失败不会升版本。已打标签但未完成的自动价格发布会优先重试同一版本,再检查新价格;registry 故障不会被当作版本不存在。发布时跳过 npm 已有版本、防止 `latest` 倒退,并在发布后核验 registry 中的版本。新增原厂/来源白名单、别名及人工核实的价格例外仍需人工审核。配置和重试方法见[发布说明](docs/releasing.md)。
102
105
 
103
106
  手动更新时,在联网的维护环境运行 `npm run prices:update`,审阅生成文件及例外差异,再执行上述检查。构建和插件刷新不会请求 models.dev。
104
107
 
105
108
  `test:smoke` 会打包真实产物,并在隔离的 OpenCode 与本地模拟提供商中验证加载、刷新、`/usage`、子代理累计、逐消息计价、原厂价格补全、模型切换、TPS 和 TTFT。它需要 Python 3、可用的本地端口和 npm 网络访问,不会修改现有 OpenCode 配置或调用付费模型。
106
109
 
110
+ 默认使用 `PATH` 中的 `opencode`。OpenCode 2.0.9 及之后的稳定版 2.x 可以运行;尚未与当前 SDK 验证的宿主会输出警告,然后继续实际兼容性检查。仅通过版本检查不代表兼容性已验证。SDK 依赖仍独立锁定,不随本机 CLI 更新而自动升级。
111
+
112
+ 如需用独立安装的二进制复现基准,而不降级日常使用的安装:
113
+
114
+ ```bash
115
+ OPENCODE_BIN=/absolute/path/to/opencode-2.0.11 npm run test:smoke
116
+ ```
117
+
118
+ `OPENCODE_BIN` 为版本检查、隔离服务端和 TUI 统一选择同一个可执行文件。相对路径以执行命令时的目录为基准解析。smoke 输出和 `result.json` 会记录宿主版本与所选二进制;已测试组合见[验证记录](docs/verification.md)。
119
+
107
120
  从源码加载时,先构建项目,再将仓库绝对路径加入目标项目的 `plugins`。
108
121
 
109
122
  ### 文档
package/ROADMAP.md CHANGED
@@ -111,9 +111,3 @@ Steps 1,234
111
111
 
112
112
  ## 待解决问题
113
113
 
114
- ### 后续评估与维护
115
-
116
- * [ ] GPT-6 Luna 实际约为 30 tok/s,但在 实时统计中仅显示 ~1.5 tok/s,而且这个数字长期不变化。初步怀疑是 Responses API 的原因。
117
- * [ ] TPS 的实时计算:当前为近似值,后续考虑通过更精确的算法计算。
118
- * [ ] 在定时或发布前验证中运行打包产物的真实宿主 smoke 测试;升级 OpenCode/SDK 时重新核对消息排序、分叉副本、compaction、事件与价格语义。
119
- * [ ] 同步仓库指南中的当前包版本与测试数量,避免 `AGENTS.md` 的状态说明落后于实际工程。
@@ -17,6 +17,16 @@ export interface PerformanceEvent {
17
17
  id?: string;
18
18
  created?: number;
19
19
  }
20
+ export interface StreamSample {
21
+ time: number;
22
+ bytes: number;
23
+ }
24
+ export declare const LIVE_WINDOW_MS = 2000;
25
+ export declare const LIVE_EWMA_ALPHA = 0.35;
26
+ export declare const LIVE_BYTES_PER_TOKEN = 4;
27
+ /** Raw live throughput from one step's recent observable deltas. */
28
+ export declare function estimatedLiveTps(samples: readonly StreamSample[]): number | undefined;
29
+ export declare function smoothLiveTps(previous: number | undefined, raw: number): number;
20
30
  export interface PreparedPerformance {
21
31
  tps?: number;
22
32
  ttftSum: number;
@@ -1,4 +1,31 @@
1
1
  import { normalize } from "./usage.js";
2
+ export const LIVE_WINDOW_MS = 2_000;
3
+ export const LIVE_EWMA_ALPHA = 0.35;
4
+ export const LIVE_BYTES_PER_TOKEN = 4;
5
+ /** Raw live throughput from one step's recent observable deltas. */
6
+ export function estimatedLiveTps(samples) {
7
+ if (samples.length < 2)
8
+ return undefined;
9
+ const first = samples[0];
10
+ const last = samples[samples.length - 1];
11
+ const duration = last.time - first.time;
12
+ if (!Number.isFinite(duration) || duration <= 0)
13
+ return undefined;
14
+ let bytes = 0;
15
+ for (const sample of samples) {
16
+ if (!Number.isFinite(sample.time) || !Number.isFinite(sample.bytes) || sample.bytes < 0)
17
+ return undefined;
18
+ bytes += sample.bytes;
19
+ }
20
+ if (bytes <= 0)
21
+ return undefined;
22
+ return (bytes / LIVE_BYTES_PER_TOKEN) / (duration / 1_000);
23
+ }
24
+ export function smoothLiveTps(previous, raw) {
25
+ if (previous === undefined || !Number.isFinite(previous))
26
+ return raw;
27
+ return previous * (1 - LIVE_EWMA_ALPHA) + raw * LIVE_EWMA_ALPHA;
28
+ }
2
29
  const finite = (value) => typeof value === "number" && Number.isFinite(value);
3
30
  function historicalFirst(message) {
4
31
  const started = message.time?.created;
@@ -187,7 +214,7 @@ export class PerformanceMonitor {
187
214
  if (this.active.has(key))
188
215
  return false;
189
216
  this.active.set(key, {
190
- messageID, sessionID, started: data.started, bytes: 0, events: new Set(),
217
+ messageID, sessionID, started: data.started, bytes: 0, samples: [], events: new Set(),
191
218
  });
192
219
  return false;
193
220
  }
@@ -229,7 +256,12 @@ export class PerformanceMonitor {
229
256
  delete sample.expiresAt;
230
257
  this.scheduleCleanup();
231
258
  }
232
- step.bytes += new TextEncoder().encode(data.delta).byteLength;
259
+ const sampleBytes = new TextEncoder().encode(data.delta).byteLength;
260
+ step.bytes += sampleBytes;
261
+ step.samples.push({ time: event.created, bytes: sampleBytes });
262
+ const cutoff = event.created - LIVE_WINDOW_MS;
263
+ while (step.samples.length > 0 && step.samples[0].time < cutoff)
264
+ step.samples.shift();
233
265
  step.last = Math.max(step.last ?? event.created, event.created);
234
266
  if (step.first === undefined) {
235
267
  step.first = event.created;
@@ -269,19 +301,28 @@ export class PerformanceMonitor {
269
301
  const sessions = new Set(sessionIDs);
270
302
  const samples = [...this.observed.values()].filter(sample => sessions.has(sample.sessionID));
271
303
  const result = performanceWithObservations(prepared, samples);
272
- let bytes = 0;
273
- let duration = 0;
304
+ // Live throughput covers only observable deltas after the first one, over a
305
+ // short sliding window. TTFT keeps the started -> first wait separately, and
306
+ // completed provider usage still replaces this estimate via reconcile().
307
+ let weighted = 0;
308
+ let durationTotal = 0;
274
309
  for (const step of this.active.values()) {
275
- if (!sessions.has(step.sessionID) || step.reconciledAt !== undefined || step.bytes <= 0)
310
+ if (!sessions.has(step.sessionID) || step.reconciledAt !== undefined)
311
+ continue;
312
+ const raw = estimatedLiveTps(step.samples);
313
+ if (raw === undefined)
276
314
  continue;
277
- const last = step.streamed ?? step.last;
278
- if (!finite(last) || last <= step.started)
315
+ const first = step.samples[0];
316
+ const last = step.samples[step.samples.length - 1];
317
+ const duration = last.time - first.time;
318
+ if (!finite(duration) || duration <= 0)
279
319
  continue;
280
- bytes += step.bytes;
281
- duration += last - step.started;
320
+ step.liveTps = smoothLiveTps(step.liveTps, raw);
321
+ weighted += step.liveTps * duration;
322
+ durationTotal += duration;
282
323
  }
283
- if (bytes > 0 && duration > 0) {
284
- result.tps = (bytes / 4) / (duration / 1_000);
324
+ if (durationTotal > 0) {
325
+ result.tps = weighted / durationTotal;
285
326
  result.tpsEstimated = true;
286
327
  }
287
328
  return result;
@@ -1,5 +1,5 @@
1
1
  export declare const GENERATED_PRICE_SNAPSHOT: {
2
- readonly verified: "2026-09-29";
2
+ readonly verified: "2026-10-07";
3
3
  readonly source: "https://models.dev/api.json";
4
4
  readonly entries: readonly [{
5
5
  readonly providerID: "ai21";
@@ -824,6 +824,14 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
824
824
  readonly output: 0;
825
825
  }];
826
826
  readonly released: "2026-06-09";
827
+ }, {
828
+ readonly providerID: "cohere";
829
+ readonly id: "north-small-translate-09-2026";
830
+ readonly prices: readonly [{
831
+ readonly input: 0;
832
+ readonly output: 0;
833
+ }];
834
+ readonly released: "2026-09-09";
827
835
  }, {
828
836
  readonly providerID: "deepseek";
829
837
  readonly id: "deepseek-flash";
@@ -861,10 +869,10 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
861
869
  readonly providerID: "deepseek";
862
870
  readonly id: "deepseek-v4-pro";
863
871
  readonly prices: readonly [{
864
- readonly input: 0.435;
865
- readonly output: 0.87;
872
+ readonly input: 0.66;
873
+ readonly output: 1.98;
866
874
  readonly cache: {
867
- readonly read: 0.003625;
875
+ readonly read: 0.022;
868
876
  };
869
877
  }];
870
878
  readonly released: "2026-08-12";
@@ -1418,6 +1426,17 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1418
1426
  };
1419
1427
  }];
1420
1428
  readonly released: "2024-11-01";
1429
+ }, {
1430
+ readonly providerID: "mistral";
1431
+ readonly id: "mistral-large-4";
1432
+ readonly prices: readonly [{
1433
+ readonly input: 0.68;
1434
+ readonly output: 2.09;
1435
+ readonly cache: {
1436
+ readonly read: 0.07;
1437
+ };
1438
+ }];
1439
+ readonly released: "2026-10-06";
1421
1440
  }, {
1422
1441
  readonly providerID: "mistral";
1423
1442
  readonly id: "mistral-large-latest";
@@ -1703,6 +1722,14 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1703
1722
  };
1704
1723
  }];
1705
1724
  readonly released: "2026-06-04";
1725
+ }, {
1726
+ readonly providerID: "nvidia";
1727
+ readonly id: "nvidia/nemotron-3.5-content-safety";
1728
+ readonly prices: readonly [{
1729
+ readonly input: 0;
1730
+ readonly output: 0;
1731
+ }];
1732
+ readonly released: "2026-06-04";
1706
1733
  }, {
1707
1734
  readonly providerID: "nvidia";
1708
1735
  readonly id: "nvidia/nemotron-3.5-lightning-30b-a3b";
@@ -1781,6 +1808,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1781
1808
  };
1782
1809
  }];
1783
1810
  readonly released: "2025-04-14";
1811
+ }, {
1812
+ readonly providerID: "openai";
1813
+ readonly id: "gpt-4.1-fast";
1814
+ readonly providers: readonly ["openai"];
1815
+ readonly prices: readonly [{
1816
+ readonly input: 3.5;
1817
+ readonly output: 14;
1818
+ readonly cache: {
1819
+ readonly read: 0.875;
1820
+ };
1821
+ }];
1822
+ readonly released: "2025-04-14";
1784
1823
  }, {
1785
1824
  readonly providerID: "openai";
1786
1825
  readonly id: "gpt-4.1-mini";
@@ -1792,6 +1831,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1792
1831
  };
1793
1832
  }];
1794
1833
  readonly released: "2025-04-14";
1834
+ }, {
1835
+ readonly providerID: "openai";
1836
+ readonly id: "gpt-4.1-mini-fast";
1837
+ readonly providers: readonly ["openai"];
1838
+ readonly prices: readonly [{
1839
+ readonly input: 0.7;
1840
+ readonly output: 2.8;
1841
+ readonly cache: {
1842
+ readonly read: 0.175;
1843
+ };
1844
+ }];
1845
+ readonly released: "2025-04-14";
1795
1846
  }, {
1796
1847
  readonly providerID: "openai";
1797
1848
  readonly id: "gpt-4.1-nano";
@@ -1803,6 +1854,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1803
1854
  };
1804
1855
  }];
1805
1856
  readonly released: "2025-04-14";
1857
+ }, {
1858
+ readonly providerID: "openai";
1859
+ readonly id: "gpt-4.1-nano-fast";
1860
+ readonly providers: readonly ["openai"];
1861
+ readonly prices: readonly [{
1862
+ readonly input: 0.2;
1863
+ readonly output: 0.8;
1864
+ readonly cache: {
1865
+ readonly read: 0.05;
1866
+ };
1867
+ }];
1868
+ readonly released: "2025-04-14";
1806
1869
  }, {
1807
1870
  readonly providerID: "openai";
1808
1871
  readonly id: "gpt-4o";
@@ -1822,6 +1885,15 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1822
1885
  readonly output: 15;
1823
1886
  }];
1824
1887
  readonly released: "2024-05-13";
1888
+ }, {
1889
+ readonly providerID: "openai";
1890
+ readonly id: "gpt-4o-2024-05-13-fast";
1891
+ readonly providers: readonly ["openai"];
1892
+ readonly prices: readonly [{
1893
+ readonly input: 8.75;
1894
+ readonly output: 26.25;
1895
+ }];
1896
+ readonly released: "2024-05-13";
1825
1897
  }, {
1826
1898
  readonly providerID: "openai";
1827
1899
  readonly id: "gpt-4o-2024-08-06";
@@ -1844,6 +1916,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1844
1916
  };
1845
1917
  }];
1846
1918
  readonly released: "2024-11-20";
1919
+ }, {
1920
+ readonly providerID: "openai";
1921
+ readonly id: "gpt-4o-fast";
1922
+ readonly providers: readonly ["openai"];
1923
+ readonly prices: readonly [{
1924
+ readonly input: 4.25;
1925
+ readonly output: 17;
1926
+ readonly cache: {
1927
+ readonly read: 2.125;
1928
+ };
1929
+ }];
1930
+ readonly released: "2024-05-13";
1847
1931
  }, {
1848
1932
  readonly providerID: "openai";
1849
1933
  readonly id: "gpt-4o-mini";
@@ -1855,6 +1939,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1855
1939
  };
1856
1940
  }];
1857
1941
  readonly released: "2024-07-18";
1942
+ }, {
1943
+ readonly providerID: "openai";
1944
+ readonly id: "gpt-4o-mini-fast";
1945
+ readonly providers: readonly ["openai"];
1946
+ readonly prices: readonly [{
1947
+ readonly input: 0.25;
1948
+ readonly output: 1;
1949
+ readonly cache: {
1950
+ readonly read: 0.125;
1951
+ };
1952
+ }];
1953
+ readonly released: "2024-07-18";
1858
1954
  }, {
1859
1955
  readonly providerID: "openai";
1860
1956
  readonly id: "gpt-5";
@@ -1866,6 +1962,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1866
1962
  };
1867
1963
  }];
1868
1964
  readonly released: "2025-08-07";
1965
+ }, {
1966
+ readonly providerID: "openai";
1967
+ readonly id: "gpt-5-fast";
1968
+ readonly providers: readonly ["openai"];
1969
+ readonly prices: readonly [{
1970
+ readonly input: 2.5;
1971
+ readonly output: 20;
1972
+ readonly cache: {
1973
+ readonly read: 0.25;
1974
+ };
1975
+ }];
1976
+ readonly released: "2025-08-07";
1869
1977
  }, {
1870
1978
  readonly providerID: "openai";
1871
1979
  readonly id: "gpt-5-mini";
@@ -1877,6 +1985,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1877
1985
  };
1878
1986
  }];
1879
1987
  readonly released: "2025-08-07";
1988
+ }, {
1989
+ readonly providerID: "openai";
1990
+ readonly id: "gpt-5-mini-fast";
1991
+ readonly providers: readonly ["openai"];
1992
+ readonly prices: readonly [{
1993
+ readonly input: 0.45;
1994
+ readonly output: 3.6;
1995
+ readonly cache: {
1996
+ readonly read: 0.045;
1997
+ };
1998
+ }];
1999
+ readonly released: "2025-08-07";
1880
2000
  }, {
1881
2001
  readonly providerID: "openai";
1882
2002
  readonly id: "gpt-5-nano";
@@ -1907,6 +2027,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1907
2027
  };
1908
2028
  }];
1909
2029
  readonly released: "2025-11-13";
2030
+ }, {
2031
+ readonly providerID: "openai";
2032
+ readonly id: "gpt-5.1-fast";
2033
+ readonly providers: readonly ["openai"];
2034
+ readonly prices: readonly [{
2035
+ readonly input: 2.5;
2036
+ readonly output: 20;
2037
+ readonly cache: {
2038
+ readonly read: 0.25;
2039
+ };
2040
+ }];
2041
+ readonly released: "2025-11-13";
1910
2042
  }, {
1911
2043
  readonly providerID: "openai";
1912
2044
  readonly id: "gpt-5.2";
@@ -1929,6 +2061,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1929
2061
  };
1930
2062
  }];
1931
2063
  readonly released: "2025-12-11";
2064
+ }, {
2065
+ readonly providerID: "openai";
2066
+ readonly id: "gpt-5.2-fast";
2067
+ readonly providers: readonly ["openai"];
2068
+ readonly prices: readonly [{
2069
+ readonly input: 3.5;
2070
+ readonly output: 28;
2071
+ readonly cache: {
2072
+ readonly read: 0.35;
2073
+ };
2074
+ }];
2075
+ readonly released: "2025-12-11";
1932
2076
  }, {
1933
2077
  readonly providerID: "openai";
1934
2078
  readonly id: "gpt-5.2-pro";
@@ -1959,6 +2103,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
1959
2103
  };
1960
2104
  }];
1961
2105
  readonly released: "2026-02-05";
2106
+ }, {
2107
+ readonly providerID: "openai";
2108
+ readonly id: "gpt-5.3-codex-fast";
2109
+ readonly providers: readonly ["openai"];
2110
+ readonly prices: readonly [{
2111
+ readonly input: 3.5;
2112
+ readonly output: 28;
2113
+ readonly cache: {
2114
+ readonly read: 0.35;
2115
+ };
2116
+ }];
2117
+ readonly released: "2026-02-05";
1962
2118
  }, {
1963
2119
  readonly providerID: "openai";
1964
2120
  readonly id: "gpt-5.3-codex-spark";
@@ -2397,6 +2553,47 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
2397
2553
  };
2398
2554
  }];
2399
2555
  readonly released: "2026-09-22";
2556
+ }, {
2557
+ readonly providerID: "openai";
2558
+ readonly id: "gpt-6.1-sol";
2559
+ readonly prices: readonly [{
2560
+ readonly input: 2;
2561
+ readonly output: 10;
2562
+ readonly cache: {
2563
+ readonly read: 0.1;
2564
+ readonly write: 2.5;
2565
+ };
2566
+ }, {
2567
+ readonly input: 4;
2568
+ readonly output: 15;
2569
+ readonly cache: {
2570
+ readonly read: 0.2;
2571
+ readonly write: 5;
2572
+ };
2573
+ readonly tier: {
2574
+ readonly type: "context";
2575
+ readonly size: 272000;
2576
+ };
2577
+ }];
2578
+ readonly released: "2026-09-29";
2579
+ }, {
2580
+ readonly providerID: "openai";
2581
+ readonly id: "gpt-6.1-sol-fast";
2582
+ readonly providers: readonly ["openai"];
2583
+ readonly prices: readonly [{
2584
+ readonly input: 4;
2585
+ readonly output: 20;
2586
+ readonly cache: {
2587
+ readonly read: 0.2;
2588
+ readonly write: 5;
2589
+ };
2590
+ }, {
2591
+ readonly tier: {
2592
+ readonly type: "context";
2593
+ readonly size: 272000;
2594
+ };
2595
+ }];
2596
+ readonly released: "2026-09-29";
2400
2597
  }, {
2401
2598
  readonly providerID: "openai";
2402
2599
  readonly id: "gpt-daybreak-blue-latest";
@@ -2462,6 +2659,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
2462
2659
  };
2463
2660
  }];
2464
2661
  readonly released: "2025-04-16";
2662
+ }, {
2663
+ readonly providerID: "openai";
2664
+ readonly id: "o3-fast";
2665
+ readonly providers: readonly ["openai"];
2666
+ readonly prices: readonly [{
2667
+ readonly input: 3.5;
2668
+ readonly output: 14;
2669
+ readonly cache: {
2670
+ readonly read: 0.875;
2671
+ };
2672
+ }];
2673
+ readonly released: "2025-04-16";
2465
2674
  }, {
2466
2675
  readonly providerID: "openai";
2467
2676
  readonly id: "o3-mini";
@@ -2492,6 +2701,18 @@ export declare const GENERATED_PRICE_SNAPSHOT: {
2492
2701
  };
2493
2702
  }];
2494
2703
  readonly released: "2025-04-16";
2704
+ }, {
2705
+ readonly providerID: "openai";
2706
+ readonly id: "o4-mini-fast";
2707
+ readonly providers: readonly ["openai"];
2708
+ readonly prices: readonly [{
2709
+ readonly input: 2;
2710
+ readonly output: 8;
2711
+ readonly cache: {
2712
+ readonly read: 0.5;
2713
+ };
2714
+ }];
2715
+ readonly released: "2025-04-16";
2495
2716
  }, {
2496
2717
  readonly providerID: "perplexity";
2497
2718
  readonly id: "sonar";
@@ -1,5 +1,5 @@
1
1
  export const GENERATED_PRICE_SNAPSHOT = {
2
- verified: "2026-09-29",
2
+ verified: "2026-10-07",
3
3
  source: "https://models.dev/api.json",
4
4
  entries: [
5
5
  { "providerID": "ai21", "id": "jamba-large", "prices": [{ "input": 2, "output": 8 }], "released": "2025-07-01" },
@@ -84,10 +84,11 @@ export const GENERATED_PRICE_SNAPSHOT = {
84
84
  { "providerID": "cohere", "id": "command-r7b-12-2024", "prices": [{ "input": 0.0375, "output": 0.15 }], "released": "2024-12-02" },
85
85
  { "providerID": "cohere", "id": "command-r7b-arabic-02-2025", "prices": [{ "input": 0.0375, "output": 0.15 }], "released": "2025-02-27" },
86
86
  { "providerID": "cohere", "id": "north-mini-code-1-0", "prices": [{ "input": 0, "output": 0 }], "released": "2026-06-09" },
87
+ { "providerID": "cohere", "id": "north-small-translate-09-2026", "prices": [{ "input": 0, "output": 0 }], "released": "2026-09-09" },
87
88
  { "providerID": "deepseek", "id": "deepseek-flash", "prices": [{ "input": 0.15, "output": 0.6, "cache": { "read": 0.003 } }], "released": "2026-09-10" },
88
89
  { "providerID": "deepseek", "id": "deepseek-v4-flash", "prices": [{ "input": 0.15, "output": 0.6, "cache": { "read": 0.003 } }], "released": "2026-09-10" },
89
90
  { "providerID": "deepseek", "id": "deepseek-v4-flash-vision-exp", "prices": [{ "input": 0.15, "output": 0.6, "cache": { "read": 0.003 } }], "released": "2026-09-10" },
90
- { "providerID": "deepseek", "id": "deepseek-v4-pro", "prices": [{ "input": 0.435, "output": 0.87, "cache": { "read": 0.003625 } }], "released": "2026-08-12" },
91
+ { "providerID": "deepseek", "id": "deepseek-v4-pro", "prices": [{ "input": 0.66, "output": 1.98, "cache": { "read": 0.022 } }], "released": "2026-08-12" },
91
92
  { "providerID": "google", "id": "deep-research-max-preview-04-2026", "prices": [{ "input": 2, "output": 12, "cache": { "read": 0.2 } }, { "input": 4, "output": 18, "cache": { "read": 0.4 }, "tier": { "type": "context", "size": 200000 } }], "released": "2026-04-21" },
92
93
  { "providerID": "google", "id": "deep-research-preview-04-2026", "prices": [{ "input": 2, "output": 12, "cache": { "read": 0.2 } }, { "input": 4, "output": 18, "cache": { "read": 0.4 }, "tier": { "type": "context", "size": 200000 } }], "released": "2026-04-21" },
93
94
  { "providerID": "google", "id": "gemini-2.5-computer-use-preview-10-2025", "prices": [{ "input": 1.25, "output": 10 }, { "input": 2.5, "output": 15, "tier": { "type": "context", "size": 200000 } }], "released": "2025-10-07" },
@@ -135,6 +136,7 @@ export const GENERATED_PRICE_SNAPSHOT = {
135
136
  { "providerID": "mistral", "id": "ministral-8b-latest", "prices": [{ "input": 0.1, "output": 0.1 }], "released": "2024-10-01" },
136
137
  { "providerID": "mistral", "id": "mistral-large-2411", "prices": [{ "input": 2, "output": 6 }], "released": "2024-11-18" },
137
138
  { "providerID": "mistral", "id": "mistral-large-2512", "prices": [{ "input": 0.5, "output": 1.5, "cache": { "read": 0.05 } }], "released": "2024-11-01" },
139
+ { "providerID": "mistral", "id": "mistral-large-4", "prices": [{ "input": 0.68, "output": 2.09, "cache": { "read": 0.07 } }], "released": "2026-10-06" },
138
140
  { "providerID": "mistral", "id": "mistral-large-latest", "prices": [{ "input": 0.5, "output": 1.5, "cache": { "read": 0.05 } }], "released": "2024-11-01" },
139
141
  { "providerID": "mistral", "id": "mistral-medium-2505", "prices": [{ "input": 0.4, "output": 2 }], "released": "2025-05-07" },
140
142
  { "providerID": "mistral", "id": "mistral-medium-2508", "prices": [{ "input": 0.4, "output": 2 }], "released": "2025-08-12" },
@@ -167,6 +169,7 @@ export const GENERATED_PRICE_SNAPSHOT = {
167
169
  { "providerID": "nvidia", "id": "nvidia/nemotron-3-nano-omni-30b-a3b-reasoning", "prices": [{ "input": 0, "output": 0 }], "released": "2026-04-28" },
168
170
  { "providerID": "nvidia", "id": "nvidia/nemotron-3-super-120b-a12b", "prices": [{ "input": 0.2, "output": 0.8 }], "released": "2026-03-11" },
169
171
  { "providerID": "nvidia", "id": "nvidia/nemotron-3-ultra-550b-a55b", "prices": [{ "input": 0.5, "output": 2.5, "cache": { "read": 0.15 } }], "released": "2026-06-04" },
172
+ { "providerID": "nvidia", "id": "nvidia/nemotron-3.5-content-safety", "prices": [{ "input": 0, "output": 0 }], "released": "2026-06-04" },
170
173
  { "providerID": "nvidia", "id": "nvidia/nemotron-3.5-lightning-30b-a3b", "prices": [{ "input": 0, "output": 0 }], "released": "2026-08-11" },
171
174
  { "providerID": "nvidia", "id": "nvidia/nemotron-content-safety-reasoning-4b", "prices": [{ "input": 0, "output": 0 }], "released": "2026-01-22" },
172
175
  { "providerID": "nvidia", "id": "nvidia/nemotron-mini-4b-instruct", "prices": [{ "input": 0, "output": 0 }], "released": "2024-08-21" },
@@ -176,23 +179,34 @@ export const GENERATED_PRICE_SNAPSHOT = {
176
179
  { "providerID": "openai", "id": "gpt-4", "prices": [{ "input": 30, "output": 60 }], "released": "2023-11-06" },
177
180
  { "providerID": "openai", "id": "gpt-4-turbo", "prices": [{ "input": 10, "output": 30 }], "released": "2023-11-06" },
178
181
  { "providerID": "openai", "id": "gpt-4.1", "prices": [{ "input": 2, "output": 8, "cache": { "read": 0.5 } }], "released": "2025-04-14" },
182
+ { "providerID": "openai", "id": "gpt-4.1-fast", "providers": ["openai"], "prices": [{ "input": 3.5, "output": 14, "cache": { "read": 0.875 } }], "released": "2025-04-14" },
179
183
  { "providerID": "openai", "id": "gpt-4.1-mini", "prices": [{ "input": 0.4, "output": 1.6, "cache": { "read": 0.1 } }], "released": "2025-04-14" },
184
+ { "providerID": "openai", "id": "gpt-4.1-mini-fast", "providers": ["openai"], "prices": [{ "input": 0.7, "output": 2.8, "cache": { "read": 0.175 } }], "released": "2025-04-14" },
180
185
  { "providerID": "openai", "id": "gpt-4.1-nano", "prices": [{ "input": 0.1, "output": 0.4, "cache": { "read": 0.025 } }], "released": "2025-04-14" },
186
+ { "providerID": "openai", "id": "gpt-4.1-nano-fast", "providers": ["openai"], "prices": [{ "input": 0.2, "output": 0.8, "cache": { "read": 0.05 } }], "released": "2025-04-14" },
181
187
  { "providerID": "openai", "id": "gpt-4o", "prices": [{ "input": 2.5, "output": 10, "cache": { "read": 1.25 } }], "released": "2024-05-13" },
182
188
  { "providerID": "openai", "id": "gpt-4o-2024-05-13", "prices": [{ "input": 5, "output": 15 }], "released": "2024-05-13" },
189
+ { "providerID": "openai", "id": "gpt-4o-2024-05-13-fast", "providers": ["openai"], "prices": [{ "input": 8.75, "output": 26.25 }], "released": "2024-05-13" },
183
190
  { "providerID": "openai", "id": "gpt-4o-2024-08-06", "prices": [{ "input": 2.5, "output": 10, "cache": { "read": 1.25 } }], "released": "2024-08-06" },
184
191
  { "providerID": "openai", "id": "gpt-4o-2024-11-20", "prices": [{ "input": 2.5, "output": 10, "cache": { "read": 1.25 } }], "released": "2024-11-20" },
192
+ { "providerID": "openai", "id": "gpt-4o-fast", "providers": ["openai"], "prices": [{ "input": 4.25, "output": 17, "cache": { "read": 2.125 } }], "released": "2024-05-13" },
185
193
  { "providerID": "openai", "id": "gpt-4o-mini", "prices": [{ "input": 0.15, "output": 0.6, "cache": { "read": 0.075 } }], "released": "2024-07-18" },
194
+ { "providerID": "openai", "id": "gpt-4o-mini-fast", "providers": ["openai"], "prices": [{ "input": 0.25, "output": 1, "cache": { "read": 0.125 } }], "released": "2024-07-18" },
186
195
  { "providerID": "openai", "id": "gpt-5", "prices": [{ "input": 1.25, "output": 10, "cache": { "read": 0.125 } }], "released": "2025-08-07" },
196
+ { "providerID": "openai", "id": "gpt-5-fast", "providers": ["openai"], "prices": [{ "input": 2.5, "output": 20, "cache": { "read": 0.25 } }], "released": "2025-08-07" },
187
197
  { "providerID": "openai", "id": "gpt-5-mini", "prices": [{ "input": 0.25, "output": 2, "cache": { "read": 0.025 } }], "released": "2025-08-07" },
198
+ { "providerID": "openai", "id": "gpt-5-mini-fast", "providers": ["openai"], "prices": [{ "input": 0.45, "output": 3.6, "cache": { "read": 0.045 } }], "released": "2025-08-07" },
188
199
  { "providerID": "openai", "id": "gpt-5-nano", "prices": [{ "input": 0.05, "output": 0.4, "cache": { "read": 0.005 } }], "released": "2025-08-07" },
189
200
  { "providerID": "openai", "id": "gpt-5-pro", "prices": [{ "input": 15, "output": 120 }], "released": "2025-10-06" },
190
201
  { "providerID": "openai", "id": "gpt-5.1", "prices": [{ "input": 1.25, "output": 10, "cache": { "read": 0.125 } }], "released": "2025-11-13" },
202
+ { "providerID": "openai", "id": "gpt-5.1-fast", "providers": ["openai"], "prices": [{ "input": 2.5, "output": 20, "cache": { "read": 0.25 } }], "released": "2025-11-13" },
191
203
  { "providerID": "openai", "id": "gpt-5.2", "prices": [{ "input": 1.75, "output": 14, "cache": { "read": 0.175 } }], "released": "2025-12-11" },
192
204
  { "providerID": "openai", "id": "gpt-5.2-chat-latest", "prices": [{ "input": 1.75, "output": 14, "cache": { "read": 0.175 } }], "released": "2025-12-11" },
205
+ { "providerID": "openai", "id": "gpt-5.2-fast", "providers": ["openai"], "prices": [{ "input": 3.5, "output": 28, "cache": { "read": 0.35 } }], "released": "2025-12-11" },
193
206
  { "providerID": "openai", "id": "gpt-5.2-pro", "prices": [{ "input": 21, "output": 168 }], "released": "2025-12-11" },
194
207
  { "providerID": "openai", "id": "gpt-5.3-chat-latest", "prices": [{ "input": 1.75, "output": 14, "cache": { "read": 0.175 } }], "released": "2026-03-03" },
195
208
  { "providerID": "openai", "id": "gpt-5.3-codex", "prices": [{ "input": 1.75, "output": 14, "cache": { "read": 0.175 } }], "released": "2026-02-05" },
209
+ { "providerID": "openai", "id": "gpt-5.3-codex-fast", "providers": ["openai"], "prices": [{ "input": 3.5, "output": 28, "cache": { "read": 0.35 } }], "released": "2026-02-05" },
196
210
  { "providerID": "openai", "id": "gpt-5.3-codex-spark", "prices": [{ "input": 1.75, "output": 14, "cache": { "read": 0.175 } }], "released": "2026-02-05" },
197
211
  { "providerID": "openai", "id": "gpt-5.4", "prices": [{ "input": 2.5, "output": 15, "cache": { "read": 0.25 } }, { "input": 5, "output": 22.5, "cache": { "read": 0.5 }, "tier": { "type": "context", "size": 272000 } }], "released": "2026-03-05" },
198
212
  { "providerID": "openai", "id": "gpt-5.4-fast", "providers": ["openai"], "prices": [{ "input": 5, "output": 30, "cache": { "read": 0.5 } }, { "tier": { "type": "context", "size": 272000 } }], "released": "2026-03-05" },
@@ -217,14 +231,18 @@ export const GENERATED_PRICE_SNAPSHOT = {
217
231
  { "providerID": "openai", "id": "gpt-6-luna-fast", "providers": ["openai"], "prices": [{ "input": 0.2, "output": 1, "cache": { "read": 0.02, "write": 0.25 } }, { "tier": { "type": "context", "size": 272000 } }], "released": "2026-09-22" },
218
232
  { "providerID": "openai", "id": "gpt-6-sol", "prices": [{ "input": 2, "output": 10, "cache": { "read": 0.2, "write": 2.5 } }, { "input": 4, "output": 15, "cache": { "read": 0.4, "write": 5 }, "tier": { "type": "context", "size": 272000 } }], "released": "2026-09-22" },
219
233
  { "providerID": "openai", "id": "gpt-6-sol-fast", "providers": ["openai"], "prices": [{ "input": 4, "output": 20, "cache": { "read": 0.4, "write": 5 } }, { "tier": { "type": "context", "size": 272000 } }], "released": "2026-09-22" },
234
+ { "providerID": "openai", "id": "gpt-6.1-sol", "prices": [{ "input": 2, "output": 10, "cache": { "read": 0.1, "write": 2.5 } }, { "input": 4, "output": 15, "cache": { "read": 0.2, "write": 5 }, "tier": { "type": "context", "size": 272000 } }], "released": "2026-09-29" },
235
+ { "providerID": "openai", "id": "gpt-6.1-sol-fast", "providers": ["openai"], "prices": [{ "input": 4, "output": 20, "cache": { "read": 0.2, "write": 5 } }, { "tier": { "type": "context", "size": 272000 } }], "released": "2026-09-29" },
220
236
  { "providerID": "openai", "id": "gpt-daybreak-blue-latest", "prices": [{ "input": 4, "output": 20, "cache": { "read": 0.4, "write": 5 } }, { "input": 8, "output": 30, "cache": { "read": 0.8, "write": 10 }, "tier": { "type": "context", "size": 272000 } }], "released": "2026-08-07" },
221
237
  { "providerID": "openai", "id": "gpt-daybreak-red-latest", "prices": [{ "input": 12.5, "output": 75, "cache": { "read": 1.25, "write": 15.625 } }], "released": "2026-08-07" },
222
238
  { "providerID": "openai", "id": "o1", "prices": [{ "input": 15, "output": 60, "cache": { "read": 7.5 } }], "released": "2024-12-05" },
223
239
  { "providerID": "openai", "id": "o1-pro", "prices": [{ "input": 150, "output": 600 }], "released": "2025-03-19" },
224
240
  { "providerID": "openai", "id": "o3", "prices": [{ "input": 2, "output": 8, "cache": { "read": 0.5 } }], "released": "2025-04-16" },
241
+ { "providerID": "openai", "id": "o3-fast", "providers": ["openai"], "prices": [{ "input": 3.5, "output": 14, "cache": { "read": 0.875 } }], "released": "2025-04-16" },
225
242
  { "providerID": "openai", "id": "o3-mini", "prices": [{ "input": 1.1, "output": 4.4, "cache": { "read": 0.55 } }], "released": "2024-12-20" },
226
243
  { "providerID": "openai", "id": "o3-pro", "prices": [{ "input": 20, "output": 80 }], "released": "2025-06-10" },
227
244
  { "providerID": "openai", "id": "o4-mini", "prices": [{ "input": 1.1, "output": 4.4, "cache": { "read": 0.275 } }], "released": "2025-04-16" },
245
+ { "providerID": "openai", "id": "o4-mini-fast", "providers": ["openai"], "prices": [{ "input": 2, "output": 8, "cache": { "read": 0.5 } }], "released": "2025-04-16" },
228
246
  { "providerID": "perplexity", "id": "sonar", "prices": [{ "input": 1, "output": 1 }], "released": "2024-01-01" },
229
247
  { "providerID": "perplexity", "id": "sonar-deep-research", "prices": [{ "input": 2, "output": 8, "reasoning": 3 }], "released": "2025-02-01" },
230
248
  { "providerID": "perplexity", "id": "sonar-pro", "prices": [{ "input": 3, "output": 15 }], "released": "2024-01-01" },
package/dist/pricing.d.ts CHANGED
@@ -14,7 +14,7 @@ export interface OfficialPriceEntry {
14
14
  /** Checked-in data: updating prices is explicit, not a network request at
15
15
  * startup, during a refresh, or during an npm build. */
16
16
  export declare const OFFICIAL_PRICE_SNAPSHOT: {
17
- verified: "2026-09-29";
17
+ verified: "2026-10-07";
18
18
  source: "https://models.dev/api.json";
19
19
  entries: OfficialPriceEntry[];
20
20
  };
package/docs/pricing.md CHANGED
@@ -4,7 +4,9 @@
4
4
 
5
5
  ## 更新方式
6
6
 
7
- GitHub Actions [价格更新工作流](../.github/workflows/update-prices.yml) 每天 UTC 03:17 从 models.dev 检查一次。生成文件与仓库版本相同就结束;有变化时先运行类型检查、测试、构建和打包检查,再创建或更新同一个仅包含 `src/prices.generated.ts` 的 PR,等待人工审阅与合并,不自动发布。也可从 Actions 页面手动触发。仓库须允许 GitHub Actions 创建 PR;使用内置 `GITHUB_TOKEN` 创建 PR 不会再次触发常规 CI,故上述检查在更新工作流内完成。
7
+ GitHub Actions [价格更新工作流](../.github/workflows/update-prices.yml) 每天 UTC 22:00 从 models.dev 检查一次,也可从 Actions 页面在 `main` 上手动触发。生成快照没有差异就结束,不会因检查日期或 API 中未导入的元数据变化发布新版本。白名单内的快照有变化(包含新增、移除和重新定价)时,先运行类型检查、测试、构建和 `npm pack --dry-run`,全部通过后自动升级 patch 版本,只提交 `src/prices.generated.ts`、`package.json`、`package-lock.json`,原子推送 `main` 与版本标签,再创建 GitHub Release 并显式触发 `publish.yml` 自动发布 npm。
8
+
9
+ 验证失败不升版本;并发修改 `main` 会令原子推送失败,不覆盖他人提交或留下孤立的远端标签。已推送但 npm 未完成的自动价格版本会先重试原标签,不再递增版本。npm 查询只有明确的 404 才视为版本不存在,网络错误会停止流程。工作流摘要记录快照条数与新增/移除/变化数量;最终 npm 结果见发布工作流。仓库推送权限与 npm Trusted Publishing 配置见[发布说明](releasing.md)。
8
10
 
9
11
  本地手动更新可在联网的维护环境中运行:
10
12
 
@@ -15,7 +17,7 @@ npm test
15
17
  npm run build
16
18
  ```
17
19
 
18
- 审阅生成文件与 `overrides.ts` 的差异后提交。更新脚本只请求 `https://models.dev/api.json`,从人工确认的**原厂 Provider + 自家模型系列**提取公开的文本模型价格;原厂平台上托管的其他厂商模型、OpenRouter 等网关报价、地域性/订阅制费率不作为回退价格来源。API 不标注模型的真实厂商,因此新增原厂或新系列需要维护者先审核并扩充 `ORIGINAL_PROVIDERS`,不能按相似名称自动猜测。
20
+ 本地更新时,审阅生成文件与 `overrides.ts` 的差异后提交。更新脚本只请求 `https://models.dev/api.json`,从人工确认的**原厂 Provider + 自家模型系列**提取公开的文本模型价格;原厂平台上托管的其他厂商模型、OpenRouter 等网关报价、地域性/订阅制费率不作为回退价格来源。自动化不修改来源白名单、别名或人工例外。API 不标注模型的真实厂商,因此新增原厂或新系列需要维护者先审核并扩充 `ORIGINAL_PROVIDERS`,不能按相似名称自动猜测。
19
21
 
20
22
  `src/prices.generated.ts` 是随 npm 包发布的离线快照:插件启动、刷新、构建、打包和测试均不请求 models.dev。`src/aliases.ts` 只记录无法按已知包装形式解决的厂商 slug 与精确模型 ID 差异;`src/overrides.ts` 只记录有原厂来源的缺失 SKU、已核实的例外费率及无法直接使用的 API 字段。普通价格变动通过重新生成快照维护,不往别名或例外表中增加常规型号。
21
23
 
@@ -1,5 +1,49 @@
1
1
  # 验证记录
2
2
 
3
+ ## 2026-10-05 · 自动价格 patch 与 npm 发布链路(本地验证)
4
+
5
+ 环境:macOS、Node.js v22.23.2、插件包仍为 0.4.4,SDK 仍锁定 2.0.11。本轮只修改价格更新与发布自动化、测试和文档,未更新真实价格快照、未推送提交或标签、未创建 GitHub Release,也未实际发布 npm。
6
+
7
+ | 检查 | 结果 |
8
+ | --- | --- |
9
+ | `npm run typecheck` | 通过 |
10
+ | `npm test` | 101 项通过,新增 16 项价格刷新/发布回归验证 |
11
+ | `npm run build` | 通过 |
12
+ | `npm pack --dry-run` | 通过,执行真实 `prepack` 构建 |
13
+ | `npm publish --dry-run` | 通过,完整执行类型检查、101 项测试与构建;未写入 registry |
14
+ | GitHub 工作流 | 通过 actionlint 1.7.12、YAML 解析和 bash 语法检查;检查工具来自官方发行且校验 SHA-256 |
15
+ | npm 只读查询 | 当前 `0.4.4` 已存在;发布状态为 `published=true`,价格恢复状态为 `retry=false` |
16
+
17
+ 发布测试在临时仓库和本地 bare remote 中实际运行 `npm version patch`、受限提交、带注释标签及 `git push --atomic`,验证 `0.4.4 → 0.4.5` 的两个 package 文件同步、仅提交三个允许文件、版本钩子不执行,以及并发更新 `main` 时不覆盖远端提交或留下孤立标签。另覆盖未完成价格版本按原标签重试、禁止每日任务发布未完成的手动版本、已占用版本/标签、registry 故障与错误响应、锁文件不一致、`latest` 倒退和发布可见性延迟。
18
+
19
+ 价格刷新覆盖无变化时跨日期保持字节不变、忽略未导入的上游元数据,以及新增、移除、零价、缓存、Reasoning 和档位差异。独立临时副本将全部生成模型的已有费率改为另一组数字,重新运行价格与用量测试,确认正常调价不再被写死的旧费率断言拦住;算法固定夹具和人工价格例外的精确断言仍保留。
20
+
21
+ 真实 GitHub 定时任务、机器人推送/Release/dispatch 和 npm OIDC 写入尚未执行;需将这些变更提交到默认分支,并满足发布说明中的权限及 Trusted Publisher 配置后,在实际工作流中验证。此次未重新运行 OpenCode TUI smoke,之前已验证的宿主结果保留在下方。
22
+
23
+ ## 2026-10-02 · smoke 宿主版本策略与兼容性
24
+
25
+ 环境:macOS、Node.js v22.23.2、插件包 0.4.3。OpenCode SDK 仍精确锁定 2.0.11,未随本机 CLI 升级;本机默认宿主为 Homebrew 安装的 OpenCode 2.0.22。旧版基准使用校验 npm SHA-512 完整性的官方 `@opencode/cli-darwin-arm64@2.0.11` 独立二进制,没有降级或修改日常安装。
26
+
27
+ | 检查 | 结果 |
28
+ | --- | --- |
29
+ | `npm run typecheck` | 通过 |
30
+ | `npm test` | 85 项通过,含 6 项 smoke 版本与二进制选择回归测试 |
31
+ | `npm run build` | 通过,两版 smoke 的 `npm pack` 均执行真实构建 |
32
+ | `npm run test:smoke`,默认宿主 2.0.22 | 完整通过 |
33
+ | `OPENCODE_BIN=… npm run test:smoke`,独立宿主 2.0.11 | 完整通过 |
34
+
35
+ 版本检查不再把补丁版本列为白名单:允许稳定版 `>=2.0.9 <3.0.0` 运行实际集成检查。尚未与当前 SDK 验证的宿主会输出警告,但不被提前拒绝;当前已验证列表为 2.0.11、2.0.22。低于最低版本、其他主版本以及无法解析的稳定版输出仍会失败。版本检查通过本身不代表兼容性已验证。`OPENCODE_BIN` 统一用于版本探测、隔离服务端与 TUI;相对路径在切换到临时项目之前解析,结果文件记录实际宿主版本与所选二进制。
36
+
37
+ 本轮保留全部原有 token、费用、上下文、布局、子代理、TPS 与 TTFT 断言,并修正测试夹具的时序:实时场景提供多段、300ms 间隔的模拟文本,避免短片段被宿主批处理合并或跨出 2s TPS 窗口;模拟流在 TUI 观察到实时指标后才结束。隔离 CLI 配置关闭持久标签页,避免不同 TUI 进程复用其他会话的焦点;详细模式滚动持续等待真实目标行可见,避免旧宿主在重新排版前处理 End。压缩模拟响应使用宿主要求的结构化摘要格式。现有 OpenCode 配置未修改,也未调用付费模型。
38
+
39
+ 两版真实宿主新增验证:分叉为独立根,继承 assistant ID 保留 `_序号` 后缀;继承消息仍占被查看会话的 Context,但不重复累计用量或 Steps;分叉自己的调用单独计价。真实压缩投影为 `status === "completed"`,`order: "asc"` 的完整历史仍保留压缩前消息,压缩后没有新 assistant 时隐藏旧 Context,新消息恢复 Context,compaction 不计为 assistant step。原有全树 Total 5,080、成本 `$0.00504`、上下文上限 128,000 → 32,000 与原厂回退价 `$0.000149` 均保持通过。
40
+
41
+ 验证产物:
42
+ - OpenCode 2.0.22:`/private/var/folders/rw/bmx6c8hd737brl55m0_ff_b80000gn/T/opencode/token-usage-smoke-93KAN2`。
43
+ - OpenCode 2.0.11:`/private/var/folders/rw/bmx6c8hd737brl55m0_ff_b80000gn/T/opencode/token-usage-smoke-p0SsRF`。
44
+
45
+ 产物包含 `result.json`、终端捕获、已隐藏服务器密码的日志,以及流式事件、生成中的消息和压缩消息诊断文件。2.0.9、2.0.10 的历史记录保留在下方,本轮未重新执行这两个宿主;后续版本仍需实际运行 smoke,不能据版本范围宣称兼容。
46
+
3
47
  ## v0.4.3 开发验证(`/usage` 模型费率展示)
4
48
 
5
49
  验证日期:2026-09-29。Node.js v22.23.2;SDK 2.0.11;真实宿主使用隔离的 `@opencode/cli-darwin-arm64@2.0.11`,包版本仍为 0.4.2。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chenlongapps/opencode-token-usage",
3
- "version": "0.4.3",
3
+ "version": "0.4.5",
4
4
  "description": "Session-tree token usage, live performance, context window and estimated cost for OpenCode 2",
5
5
  "keywords": [
6
6
  "opencode",
@@ -47,7 +47,7 @@
47
47
  "scripts": {
48
48
  "build": "node scripts/build.mjs",
49
49
  "typecheck": "tsc --noEmit",
50
- "test": "tsx --test test/*.test.ts",
50
+ "test": "tsx --test test/*.test.ts test/*.test.mjs",
51
51
  "test:smoke": "node scripts/smoke.mjs",
52
52
  "prices:update": "tsx scripts/update-prices.ts",
53
53
  "release:patch": "npm version patch",