@chenlongapps/opencode-token-usage 0.4.1 → 0.4.3
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 +11 -7
- package/README.zh-CN.md +10 -6
- package/ROADMAP.md +13 -0
- package/dist/aliases.d.ts +6 -0
- package/dist/aliases.js +32 -0
- package/dist/context-capture.d.ts +43 -0
- package/dist/context-capture.js +111 -0
- package/dist/controller.d.ts +4 -0
- package/dist/controller.js +43 -15
- package/dist/index.js +29 -8
- package/dist/overrides.d.ts +22 -0
- package/dist/overrides.js +181 -0
- package/dist/performance.d.ts +9 -0
- package/dist/performance.js +61 -26
- package/dist/prices.generated.d.ts +3454 -0
- package/dist/prices.generated.js +294 -0
- package/dist/pricing.d.ts +14 -189
- package/dist/pricing.js +86 -580
- package/dist/source.d.ts +3 -2
- package/dist/source.js +31 -16
- package/dist/tui.js +209 -153
- package/dist/usage.d.ts +24 -2
- package/dist/usage.js +93 -16
- package/docs/pricing.md +24 -290
- package/docs/verification.md +36 -0
- package/package.json +2 -1
package/dist/usage.d.ts
CHANGED
|
@@ -24,6 +24,8 @@ export interface Price {
|
|
|
24
24
|
};
|
|
25
25
|
input?: number;
|
|
26
26
|
output?: number;
|
|
27
|
+
/** Optional first-party rate when reasoning differs from ordinary output. */
|
|
28
|
+
reasoning?: number;
|
|
27
29
|
cache?: {
|
|
28
30
|
read?: number;
|
|
29
31
|
write?: number;
|
|
@@ -83,6 +85,20 @@ export declare function estimate(tokens: Tokens, prices?: readonly Price[]): {
|
|
|
83
85
|
defaultPrice: boolean;
|
|
84
86
|
};
|
|
85
87
|
export type CostStatus = "empty" | "complete" | "partial" | "unavailable";
|
|
88
|
+
export type PriceSource = "OpenCode" | "Built-in snapshot";
|
|
89
|
+
export interface AppliedRates {
|
|
90
|
+
source: PriceSource;
|
|
91
|
+
lowerExclusive: number | undefined;
|
|
92
|
+
upperInclusive: number | undefined;
|
|
93
|
+
calls: number;
|
|
94
|
+
rates: {
|
|
95
|
+
input: number | undefined;
|
|
96
|
+
output: number | undefined;
|
|
97
|
+
reasoning: number | undefined;
|
|
98
|
+
cacheRead: number | undefined;
|
|
99
|
+
cacheWrite: number | undefined;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
86
102
|
/** Prices every call with its recorded model. A complete non-zero OpenCode
|
|
87
103
|
* price wins; a complete snapshot price can replace a complete OpenCode zero.
|
|
88
104
|
* Incomplete OpenCode prices fall back to the snapshot as a whole. */
|
|
@@ -102,6 +118,8 @@ export interface ModelCost {
|
|
|
102
118
|
tokens: number;
|
|
103
119
|
cost: number;
|
|
104
120
|
costStatus: CostStatus;
|
|
121
|
+
appliedRates: readonly AppliedRates[];
|
|
122
|
+
unpricedCalls: number;
|
|
105
123
|
}
|
|
106
124
|
/** Groups the same per-message estimates used by the tree total; unlabelled calls stay visible. */
|
|
107
125
|
export declare function summarizeModels(messages: Iterable<UsageMessage>, catalog?: PriceCatalog): ModelCost[];
|
|
@@ -114,11 +132,15 @@ export interface ContextDetails {
|
|
|
114
132
|
usage: ContextUsage;
|
|
115
133
|
tokens: Tokens;
|
|
116
134
|
}
|
|
117
|
-
export declare function contextDetails(messages: readonly UsageMessage[], limit?: number): ContextDetails | undefined;
|
|
118
|
-
export declare function contextUsage(messages: readonly UsageMessage[], limit?: number): ContextUsage | undefined;
|
|
135
|
+
export declare function contextDetails(messages: readonly UsageMessage[], limit?: number, revertMessageID?: string): ContextDetails | undefined;
|
|
136
|
+
export declare function contextUsage(messages: readonly UsageMessage[], limit?: number, revertMessageID?: string): ContextUsage | undefined;
|
|
119
137
|
export declare function formatTokens(value: number): string;
|
|
120
138
|
export declare const formatCost: (value: number) => string;
|
|
121
139
|
export declare function formatEstimatedCost(cost: number, status: CostStatus): string | undefined;
|
|
140
|
+
/** Per-million rates need more precision than a rounded total cost. */
|
|
141
|
+
export declare function formatRate(value: number | undefined): string;
|
|
142
|
+
export declare function formatRateTier(value: Pick<AppliedRates, "lowerExclusive" | "upperInclusive">): string;
|
|
143
|
+
export declare function rateRows(value: AppliedRates): readonly (readonly [string, string])[];
|
|
122
144
|
/** Compact display for scan-first views: 812, 139.4K, 3.70M. Detailed views keep formatTokens. */
|
|
123
145
|
export declare function formatCompact(value: number): string;
|
|
124
146
|
/** Splits a percentage into filled and empty cell counts for a plain-text bar. */
|
package/dist/usage.js
CHANGED
|
@@ -10,12 +10,15 @@ export function normalize(tokens) {
|
|
|
10
10
|
export const incoming = (t) => t.input + t.cache.read + t.cache.write;
|
|
11
11
|
export const total = (t) => incoming(t) + t.output + t.reasoning;
|
|
12
12
|
// Matches OpenCode 2.0.11 SessionUsage.calculateCost: thresholds are exclusive.
|
|
13
|
-
|
|
13
|
+
function selectedPrice(tokens, prices) {
|
|
14
14
|
const tier = prices.filter(p => p.tier && incoming(tokens) > p.tier.size)
|
|
15
15
|
.sort((a, b) => b.tier.size - a.tier.size)[0];
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
return tier ?? prices.find(p => !p.tier);
|
|
17
|
+
}
|
|
18
|
+
export function estimate(tokens, prices = []) {
|
|
19
|
+
const price = selectedPrice(tokens, prices);
|
|
20
|
+
const rates = [price?.input, price?.output, price?.reasoning ?? price?.output, price?.cache?.read, price?.cache?.write];
|
|
21
|
+
const quantities = [tokens.input, tokens.output, tokens.reasoning, tokens.cache.read, tokens.cache.write];
|
|
19
22
|
return {
|
|
20
23
|
cost: quantities.reduce((sum, quantity, index) => sum + quantity * safe(rates[index]), 0) / 1_000_000,
|
|
21
24
|
defaultPrice: total(tokens) > 0 && (!price || rates.some((rate, index) => quantities[index] > 0
|
|
@@ -25,13 +28,41 @@ export function estimate(tokens, prices = []) {
|
|
|
25
28
|
function priceMessage(tokens, model, catalog) {
|
|
26
29
|
if (!model)
|
|
27
30
|
return undefined;
|
|
28
|
-
let
|
|
31
|
+
let prices = catalog.get(modelKey(model)) ?? [];
|
|
32
|
+
let source = "OpenCode";
|
|
33
|
+
let value = estimate(tokens, prices);
|
|
29
34
|
if (value.defaultPrice || value.cost === 0) {
|
|
30
|
-
const
|
|
31
|
-
|
|
35
|
+
const fallback = officialPrice(model)?.prices ?? [];
|
|
36
|
+
const snapshot = estimate(tokens, fallback);
|
|
37
|
+
if (!snapshot.defaultPrice) {
|
|
32
38
|
value = snapshot;
|
|
39
|
+
prices = fallback;
|
|
40
|
+
source = "Built-in snapshot";
|
|
41
|
+
}
|
|
33
42
|
}
|
|
34
|
-
|
|
43
|
+
const price = selectedPrice(tokens, prices);
|
|
44
|
+
return value.defaultPrice || !price ? undefined : { cost: value.cost, source, price, prices };
|
|
45
|
+
}
|
|
46
|
+
const validRate = (value) => value !== undefined && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
47
|
+
function appliedRates(value) {
|
|
48
|
+
const lowerExclusive = value.price.tier?.size;
|
|
49
|
+
const next = value.prices.reduce((size, price) => {
|
|
50
|
+
const threshold = price.tier?.size;
|
|
51
|
+
return threshold !== undefined && threshold > (lowerExclusive ?? -Infinity) && threshold < size ? threshold : size;
|
|
52
|
+
}, Infinity);
|
|
53
|
+
return {
|
|
54
|
+
source: value.source,
|
|
55
|
+
lowerExclusive,
|
|
56
|
+
upperInclusive: Number.isFinite(next) ? next : undefined,
|
|
57
|
+
calls: 1,
|
|
58
|
+
rates: {
|
|
59
|
+
input: validRate(value.price.input),
|
|
60
|
+
output: validRate(value.price.output),
|
|
61
|
+
reasoning: validRate(value.price.reasoning ?? value.price.output),
|
|
62
|
+
cacheRead: validRate(value.price.cache?.read),
|
|
63
|
+
cacheWrite: validRate(value.price.cache?.write),
|
|
64
|
+
},
|
|
65
|
+
};
|
|
35
66
|
}
|
|
36
67
|
function costStatus(known, missing) {
|
|
37
68
|
if (missing > 0)
|
|
@@ -69,7 +100,7 @@ export function summarize(messages, catalog = new Map()) {
|
|
|
69
100
|
if (value === undefined)
|
|
70
101
|
missingCosts++;
|
|
71
102
|
else {
|
|
72
|
-
cost += value;
|
|
103
|
+
cost += value.cost;
|
|
73
104
|
knownCosts++;
|
|
74
105
|
}
|
|
75
106
|
}
|
|
@@ -89,21 +120,33 @@ export function summarizeModels(messages, catalog = new Map()) {
|
|
|
89
120
|
if (count === 0)
|
|
90
121
|
continue;
|
|
91
122
|
const key = message.model && modelKey(message.model);
|
|
92
|
-
const group = groups.get(key) ?? { calls: 0, tokens: 0, cost: 0, known: 0, missing: 0 };
|
|
123
|
+
const group = groups.get(key) ?? { calls: 0, tokens: 0, cost: 0, known: 0, missing: 0, rates: new Map() };
|
|
93
124
|
group.calls++;
|
|
94
125
|
group.tokens += count;
|
|
95
126
|
const value = priceMessage(tokens, message.model, catalog);
|
|
96
127
|
if (value === undefined)
|
|
97
128
|
group.missing++;
|
|
98
129
|
else {
|
|
99
|
-
group.cost += value;
|
|
130
|
+
group.cost += value.cost;
|
|
100
131
|
group.known++;
|
|
132
|
+
const applied = appliedRates(value);
|
|
133
|
+
const rateKey = JSON.stringify([applied.source, applied.lowerExclusive, applied.upperInclusive, ...Object.values(applied.rates)]);
|
|
134
|
+
const existing = group.rates.get(rateKey);
|
|
135
|
+
if (existing)
|
|
136
|
+
existing.calls++;
|
|
137
|
+
else
|
|
138
|
+
group.rates.set(rateKey, applied);
|
|
101
139
|
}
|
|
102
140
|
groups.set(key, group);
|
|
103
141
|
}
|
|
104
142
|
return [...groups].map(([model, group]) => ({
|
|
105
143
|
model: model ?? "Unknown model", calls: group.calls, tokens: group.tokens,
|
|
106
144
|
cost: group.cost, costStatus: costStatus(group.known, group.missing),
|
|
145
|
+
appliedRates: [...group.rates.values()].sort((a, b) => {
|
|
146
|
+
const lowerA = a.lowerExclusive ?? -Infinity, lowerB = b.lowerExclusive ?? -Infinity;
|
|
147
|
+
return lowerA === lowerB ? a.source.localeCompare(b.source) : lowerA - lowerB;
|
|
148
|
+
}),
|
|
149
|
+
unpricedCalls: group.missing,
|
|
107
150
|
})).sort((a, b) => b.cost - a.cost || a.model.localeCompare(b.model));
|
|
108
151
|
}
|
|
109
152
|
const usableLimit = (value) => value !== undefined && Number.isFinite(value) && value > 0;
|
|
@@ -111,18 +154,25 @@ const usableLimit = (value) => value !== undefined && Number.isFinite(value) &&
|
|
|
111
154
|
// the last completed compaction carries the current context size. Running or failed
|
|
112
155
|
// compactions do not reset it, and a last message without usage hides the row entirely
|
|
113
156
|
// instead of falling back to pre-compaction history.
|
|
114
|
-
export function contextDetails(messages, limit) {
|
|
157
|
+
export function contextDetails(messages, limit, revertMessageID) {
|
|
115
158
|
if (!usableLimit(limit))
|
|
116
159
|
return undefined;
|
|
160
|
+
// The staged revert excludes its boundary message and every later message.
|
|
161
|
+
// Session.message.list is ascending; an absent marker can occur during a
|
|
162
|
+
// concurrent commit, in which case the ordered ID still gives the cutoff.
|
|
163
|
+
const found = revertMessageID ? messages.findIndex(message => message.id === revertMessageID) : -1;
|
|
164
|
+
const next = revertMessageID && found < 0 ? messages.findIndex(message => message.id > revertMessageID) : -1;
|
|
165
|
+
const end = !revertMessageID ? messages.length : found >= 0 ? found
|
|
166
|
+
: next >= 0 ? next : messages.length;
|
|
117
167
|
let boundary = -1;
|
|
118
|
-
for (let index =
|
|
168
|
+
for (let index = end - 1; index >= 0; index--) {
|
|
119
169
|
const message = messages[index];
|
|
120
170
|
if (message.type === "compaction" && message.status === "completed") {
|
|
121
171
|
boundary = index;
|
|
122
172
|
break;
|
|
123
173
|
}
|
|
124
174
|
}
|
|
125
|
-
for (let index =
|
|
175
|
+
for (let index = end - 1; index > boundary; index--) {
|
|
126
176
|
const message = messages[index];
|
|
127
177
|
if (message.type !== "assistant" || !message.tokens)
|
|
128
178
|
continue;
|
|
@@ -132,8 +182,8 @@ export function contextDetails(messages, limit) {
|
|
|
132
182
|
}
|
|
133
183
|
return undefined;
|
|
134
184
|
}
|
|
135
|
-
export function contextUsage(messages, limit) {
|
|
136
|
-
return contextDetails(messages, limit)?.usage;
|
|
185
|
+
export function contextUsage(messages, limit, revertMessageID) {
|
|
186
|
+
return contextDetails(messages, limit, revertMessageID)?.usage;
|
|
137
187
|
}
|
|
138
188
|
export function formatTokens(value) {
|
|
139
189
|
return Math.round(safe(value)).toLocaleString("en-US");
|
|
@@ -146,6 +196,33 @@ export function formatEstimatedCost(cost, status) {
|
|
|
146
196
|
return "—";
|
|
147
197
|
return `${formatCost(cost)}${status === "partial" ? " · partial" : ""}`;
|
|
148
198
|
}
|
|
199
|
+
/** Per-million rates need more precision than a rounded total cost. */
|
|
200
|
+
export function formatRate(value) {
|
|
201
|
+
if (value === undefined || !Number.isFinite(value) || value < 0)
|
|
202
|
+
return "—";
|
|
203
|
+
if (value === 0)
|
|
204
|
+
return "$0.00";
|
|
205
|
+
const decimal = value.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 12 });
|
|
206
|
+
return `$${decimal === "0.00" ? value.toExponential(2) : decimal}`;
|
|
207
|
+
}
|
|
208
|
+
export function formatRateTier(value) {
|
|
209
|
+
const lower = value.lowerExclusive, upper = value.upperInclusive;
|
|
210
|
+
if (lower === undefined && upper === undefined)
|
|
211
|
+
return "all incoming sizes";
|
|
212
|
+
if (lower === undefined)
|
|
213
|
+
return `≤${formatTokens(upper)} incoming`;
|
|
214
|
+
if (upper === undefined)
|
|
215
|
+
return `>${formatTokens(lower)} incoming`;
|
|
216
|
+
return `>${formatTokens(lower)} to ≤${formatTokens(upper)} incoming`;
|
|
217
|
+
}
|
|
218
|
+
export function rateRows(value) {
|
|
219
|
+
const rates = value.rates;
|
|
220
|
+
return [
|
|
221
|
+
["Input", formatRate(rates.input)], ["Output", formatRate(rates.output)],
|
|
222
|
+
["Reasoning", formatRate(rates.reasoning)], ["Cache Read", formatRate(rates.cacheRead)],
|
|
223
|
+
["Cache Write", formatRate(rates.cacheWrite)],
|
|
224
|
+
];
|
|
225
|
+
}
|
|
149
226
|
/** Compact display for scan-first views: 812, 139.4K, 3.70M. Detailed views keep formatTokens. */
|
|
150
227
|
export function formatCompact(value) {
|
|
151
228
|
const n = safe(value);
|
package/docs/pricing.md
CHANGED
|
@@ -1,303 +1,37 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 内置原厂价格快照
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
插件在 OpenCode 当前模型目录无法为一条消息提供完整价格时,使用仓库内已生成的价格快照。快照的版本、核对日期、逐模型费率和档位见 [`src/prices.generated.ts`](../src/prices.generated.ts);来源是 [models.dev 的 API](https://models.dev/api.json)。少量经原厂核实的例外见 [`src/overrides.ts`](../src/overrides.ts),例外的来源、原因及统一核验日期也保存在该文件。所有金额均为美元 / 100 万 token。
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 更新方式
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
- OpenCode 当前解析出的完整适用非零价格优先。若完整适用价格为零,则尝试使用内置价格;只有快照能完整覆盖该消息实际使用的 token 类别时才覆盖零价,否则保留 OpenCode 的零价。OpenCode 价格不完整时,整条消息回退到内置价格,不混用两套费率。
|
|
9
|
-
- 网关模型只通过精确厂商 ID、精确别名及已知包装格式匹配,例如 `openai/gpt-5.6-luna`、`us.anthropic.claude-opus-5` 和 `claude-opus-5@default`。匹配这些现有形式后,也会尝试仅移除模型 ID 的末尾 `-free` 或 `:free` 再精确匹配基础 ID,例如 `mimo-v2.6-flash-free`、`meta/muse-spark-1.3:free` 和 `muse-spark-1.3-contributor-free`;`-pro`、`-fast`、`-free-preview` 等其他后缀不会剥离。单独列出的 Fast 型号仅按完整 ID 和厂商支持的 provider 精确匹配,不会回退到标准费率。不按相似名称猜测。
|
|
10
|
-
- 目录首版只新增 2026-03-22 至 2026-09-22 发布、具有明确 token 费率的模型。后续版本只限制新增窗口,已经收录的条目不会因超过半年而自动删除。
|
|
11
|
-
- 采用同步 API 的公开价;Meta Contributor 条件价按单独标注的来源记录。仅收录下表明确列出的 Fast 型号,不含 Batch、Flex、其他 Fast/Priority、区域溢价、网关加价、企业折扣、工具费和税费,因此 Est. Cost 仍是估算,不代表账单。
|
|
12
|
-
- 任一有用量消息仍无法定价时,已知小计标记 `partial`;全部无法定价时显示 `—`。明确零价才显示 `$0.00`。
|
|
13
|
-
- 促销价按核验日官网显示的费率收录(如 `gpt-5.6-sol`、MiniMax-M3 的"长期 5 折"标价),不用划线原价。
|
|
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,故上述检查在更新工作流内完成。
|
|
14
8
|
|
|
15
|
-
|
|
9
|
+
本地手动更新可在联网的维护环境中运行:
|
|
16
10
|
|
|
17
|
-
|
|
11
|
+
```sh
|
|
12
|
+
npm run prices:update
|
|
13
|
+
npm run typecheck
|
|
14
|
+
npm test
|
|
15
|
+
npm run build
|
|
16
|
+
```
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
| --- | --- | ---: | ---: | ---: | ---: | --- |
|
|
21
|
-
| `gpt-5.5` | 2026-04-23 | 5 | 30 | 0.5 | — | >272K:10 / 45 / 1 / — |
|
|
22
|
-
| `gpt-5.5-fast`(Fast) | 2026-04-23 | 12.5 | 75 | 1.25 | — | >272K:无官方 Fast 费率 |
|
|
23
|
-
| `gpt-5.5-pro` | 2026-04-23 | 30 | 180 | — | — | >272K:60 / 270 / — / — |
|
|
24
|
-
| `gpt-5.6-sol` | 2026-07-09 | 4 | 20 | 0.4 | 5 | >272K:8 / 30 / 0.8 / 10 |
|
|
25
|
-
| `gpt-5.6-sol-fast`(Fast) | 2026-07-09 | 8 | 40 | 0.8 | 10 | >272K:16 / 60 / 1.6 / 20 |
|
|
26
|
-
| `gpt-5.6-terra` | 2026-07-09 | 2 | 12 | 0.2 | 2.5 | >272K:4 / 18 / 0.4 / 5 |
|
|
27
|
-
| `gpt-5.6-terra-fast`(Fast) | 2026-07-09 | 4 | 24 | 0.4 | 5 | >272K:8 / 36 / 0.8 / 10 |
|
|
28
|
-
| `gpt-5.6-luna` | 2026-07-09 | 0.2 | 1.2 | 0.02 | 0.25 | >272K:0.4 / 1.8 / 0.04 / 0.5 |
|
|
29
|
-
| `gpt-5.6-luna-fast`(Fast) | 2026-07-09 | 0.4 | 2.4 | 0.04 | 0.5 | >272K:0.8 / 3.6 / 0.08 / 1 |
|
|
30
|
-
| `gpt-6-astra` | 2026-09-04 | 10 | 50 | 1 | 12.5 | >272K:20 / 75 / 2 / 25 |
|
|
31
|
-
| `gpt-6-astra-fast`(Fast) | 2026-09-04 | 20 | 100 | 2 | 25 | >272K:40 / 150 / 4 / 50 |
|
|
32
|
-
| `gpt-6-sol` | 2026-09-22 | 2 | 10 | 0.2 | 2.5 | >272K:4 / 15 / 0.4 / 5 |
|
|
33
|
-
| `gpt-6-sol-fast`(Fast) | 2026-09-22 | 4 | 20 | 0.4 | 5 | >272K:8 / 30 / 0.8 / 10 |
|
|
34
|
-
| `gpt-6-luna` | 2026-09-22 | 0.1 | 0.5 | 0.01 | 0.125 | >272K:0.2 / 0.75 / 0.02 / 0.25 |
|
|
35
|
-
| `gpt-6-luna-fast`(Fast) | 2026-09-22 | 0.2 | 1 | 0.02 | 0.25 | >272K:0.4 / 1.5 / 0.04 / 0.5 |
|
|
36
|
-
| `chat-latest`(别名 `gpt-chat-latest`) | 2026-05-05 | 5 | 30 | 0.5 | — | — |
|
|
18
|
+
审阅生成文件与 `overrides.ts` 的差异后提交。更新脚本只请求 `https://models.dev/api.json`,从人工确认的**原厂 Provider + 自家模型系列**提取公开的文本模型价格;原厂平台上托管的其他厂商模型、OpenRouter 等网关报价、地域性/订阅制费率不作为回退价格来源。API 不标注模型的真实厂商,因此新增原厂或新系列需要维护者先审核并扩充 `ORIGINAL_PROVIDERS`,不能按相似名称自动猜测。
|
|
37
19
|
|
|
38
|
-
`
|
|
20
|
+
`src/prices.generated.ts` 是随 npm 包发布的离线快照:插件启动、刷新、构建、打包和测试均不请求 models.dev。`src/aliases.ts` 只记录无法按已知包装形式解决的厂商 slug 与精确模型 ID 差异;`src/overrides.ts` 只记录有原厂来源的缺失 SKU、已核实的例外费率及无法直接使用的 API 字段。普通价格变动通过重新生成快照维护,不往别名或例外表中增加常规型号。
|
|
39
21
|
|
|
40
|
-
##
|
|
22
|
+
## 估算规则与边界
|
|
41
23
|
|
|
42
|
-
|
|
24
|
+
- 每条 assistant / compaction 消息使用自身记录的模型和五类 token 用量计价。OpenCode 当前解析出的完整非零价格优先;价格不完整时,整条消息回退到快照;完整零价只有在快照能覆盖该消息实际使用的类别时才被替换。两套价格不混用。
|
|
25
|
+
- 上下文档位按该条消息的 `input + cache read + cache write` 选择,档位阈值为**严格大于**。输出与推理分开统计;原厂明确提供不同 `reasoning` 单价时分别计费,否则沿用输出单价。
|
|
26
|
+
- 缺少实际用到的 token 类别费率就不能按该来源完整计价,不把缺价填作零。无法计价显示 `—`,部分可计价显示 `partial`,明确零价显示 `$0.00`。
|
|
27
|
+
- `/usage` 的 By Model 详细模式仅列出有用量模型在**当前估算**中实际采用的费率,按来源与上下文档位归组,并显示每组调用数;无法定价的调用单独计数。五类费率均为美元/百万文本 token,缺少某类价格显示 `—`,Reasoning 未单列价格时沿用 Output。这里使用当前解析出的模型目录或打包快照重新估算历史消息,不代表消息生成时的实际价格或提供商账单。
|
|
28
|
+
- 网关仅通过精确原厂 ID、唯一的完整裸 ID、明确别名及已知包装格式匹配。终尾 `-free` / `:free` 可在精确匹配失败后再去掉;不剥离 `-fast`、`-pro` 等其他后缀。Fast 模式只匹配支持它的原厂 Provider;不会把普通费率借给网关 Fast 变体。
|
|
29
|
+
- 导入文本输入与文本输出的 token 费率;图片、音频、视频、存储时长、搜索和工具调用等独立计费项无法由五类 token 可靠还原。音频输出另有不同价格的型号不会导入;其余多模态请求仍可能超出此文本估算范围。
|
|
43
30
|
|
|
44
|
-
|
|
45
|
-
| --- | --- | ---: | ---: | ---: | ---: |
|
|
46
|
-
| `claude-opus-4-7` | 2026-04-14 | 5 | 25 | 0.5 | 6.25 |
|
|
47
|
-
| `claude-opus-4-8` | 2026-05-28 | 5 | 25 | 0.5 | 6.25 |
|
|
48
|
-
| `claude-opus-4-8-fast`(Fast) | 2026-05-28 | 10 | 50 | 1 | 12.5 |
|
|
49
|
-
| `claude-fable-5` | 2026-06-07 | 10 | 50 | 1 | 12.5 |
|
|
50
|
-
| `claude-sonnet-5` | 2026-06-29 | 2 | 10 | 0.2 | 2.5 |
|
|
51
|
-
| `claude-opus-5` | 2026-07-24 | 5 | 25 | 0.5 | 6.25 |
|
|
52
|
-
| `claude-opus-5-fast`(Fast) | 2026-07-24 | 10 | 50 | 1 | 12.5 |
|
|
53
|
-
| `claude-fable-5-1` | 2026-09-01 | 10 | 50 | 0.25 | 12.5 |
|
|
54
|
-
| `claude-opus-5-5` | 2026-09-22 | 4 | 20 | 0.2 | 5 |
|
|
55
|
-
| `claude-opus-5-5-fast`(Fast) | 2026-09-22 | 8 | 40 | 0.4 | 10 |
|
|
31
|
+
## 人工核实的例外
|
|
56
32
|
|
|
57
|
-
|
|
33
|
+
`overrides.ts` 保存较少量的可追溯例外,而不是另一份手动维护的完整价格目录。例如 DeepSeek 的历史消息没有计费时段,因此使用官网峰值价而不是 API 的低峰价;xAI 在 200K 起涨价,需要把目录中的阈值调整为符合 OpenCode 严格大于比较的 199,999;Z.ai 的缓存存储按时间收费,不把目录中的 `cache_write: 0` 解释为免费;阿里云隐式和显式缓存写入费率不同,不把聚合的 Cache Write 当作其中一种。
|
|
58
34
|
|
|
59
|
-
|
|
35
|
+
另外,OpenAI Fast 的长上下文档、Step 5 Preview 的缓存写入、Kimi K3 的五分钟缓存写入、腾讯 Hy3 的按量价格,以及 models.dev 暂无原厂条目的少数型号(如 Aion)均按文件中标注的原厂页面和理由维护。Meta Contributor 是具有单独条件价格的原厂 SKU;仅精确匹配对应 Contributor 型号,不将普通 Muse Spark 一概按该价计算。
|
|
60
36
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
## Google
|
|
64
|
-
|
|
65
|
-
来源:[Gemini Developer API Pricing](https://ai.google.dev/gemini-api/docs/pricing)
|
|
66
|
-
|
|
67
|
-
| 模型 | 发布日期 | Input | Output(含 thinking) | Cache Read |
|
|
68
|
-
| --- | --- | ---: | ---: | ---: |
|
|
69
|
-
| `gemini-3.1-flash-lite` | 2026-05-07 | 0.25 | 1.5 | 0.025 |
|
|
70
|
-
| `gemini-3.5-flash` | 2026-05-19 | 1.5 | 9 | 0.15 |
|
|
71
|
-
| `gemini-3.5-flash-lite` | 2026-07-21 | 0.3 | 2.5 | 0.03 |
|
|
72
|
-
| `gemini-3.6-flash` | 2026-07-21 | 0.75 | 3.75 | 0.075 |
|
|
73
|
-
| `gemini-3.7-flash` | 2026-08-13 | 0.75 | 3.75 | 0.075 |
|
|
74
|
-
| `gemini-3.8-flash` | 2026-09-02 | 0.75 | 3.75 | 0.075 |
|
|
75
|
-
|
|
76
|
-
Gemini 3.6–3.8 Flash 的表中价格有效至 2026-12-31。上下文缓存还按存储时间收费;消息 token 统计无法表示该费用,因此目录不伪造 Cache Write 费率,遇到实际 cache write 且 OpenCode 也缺价时会标为不可用。
|
|
77
|
-
|
|
78
|
-
## xAI
|
|
79
|
-
|
|
80
|
-
来源:[Grok Models & Pricing](https://docs.x.ai/developers/models)
|
|
81
|
-
|
|
82
|
-
| 模型 | 发布日期 | Input | Output | Cache Read | ≥200K Input / Output / Cache Read |
|
|
83
|
-
| --- | --- | ---: | ---: | ---: | --- |
|
|
84
|
-
| `grok-build-0.1` | 2026-04-16 | 1 | 2 | 0.2 | 2 / 4 / 0.4 |
|
|
85
|
-
| `grok-4.3` | 2026-04-17 | 1.25 | 2.5 | 0.2 | 2.5 / 5 / 0.4 |
|
|
86
|
-
| `grok-4.5` | 2026-07-08 | 2 | 6 | 0.3 | 4 / 12 / 0.6 |
|
|
87
|
-
| `grok-4.6` | 2026-08-12 | 2 | 6 | 0.5 | 4 / 12 / 1 |
|
|
88
|
-
| `grok-4.7` | 2026-09-21 | 2 | 6 | 0.5 | 4 / 12 / 1 |
|
|
89
|
-
|
|
90
|
-
## Mistral 与 Cohere
|
|
91
|
-
|
|
92
|
-
来源:[Mistral Pricing](https://docs.mistral.ai/inference/pricing)、[Cohere Pricing](https://cohere.com/pricing)
|
|
93
|
-
|
|
94
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
95
|
-
| --- | --- | ---: | ---: | ---: |
|
|
96
|
-
| `mistral-medium-3-5-26-04` | 2026-04-29 | 1.5 | 7.5 | 0.15 |
|
|
97
|
-
| `command-a-plus-05-2026` | 2026-05-20 | 2.5 | 10 | — |
|
|
98
|
-
|
|
99
|
-
## Z.ai(GLM)
|
|
100
|
-
|
|
101
|
-
来源:[Z.AI Pricing](https://docs.z.ai/guides/overview/pricing)
|
|
102
|
-
|
|
103
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
104
|
-
| --- | --- | ---: | ---: | ---: |
|
|
105
|
-
| `glm-5.1` | 2026-04-06 | 1.4 | 4.4 | 0.26 |
|
|
106
|
-
| `glm-5.2` | 2026-06-16 | 1.4 | 4.4 | 0.26 |
|
|
107
|
-
| `glm-5.3` | 2026-08-16 | 1.4 | 4.4 | 0.26 |
|
|
108
|
-
| `glm-5.3-flash` | 2026-08-26 | 0.15 | 0.5 | 0.03 |
|
|
109
|
-
| `glm-5.3-flashx` | 2026-09-18 | 0.37 | 1.25 | 0.075 |
|
|
110
|
-
|
|
111
|
-
官方按时间收取缓存存储费(限期免费),没有 cache write token 价,因此这些模型遇到实际 cache write 用量且 OpenCode 也缺价时标记为不可用。
|
|
112
|
-
|
|
113
|
-
## DeepSeek
|
|
114
|
-
|
|
115
|
-
来源:[DeepSeek Models & Pricing](https://api-docs.deepseek.com/quick_start/pricing)
|
|
116
|
-
|
|
117
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
118
|
-
| --- | --- | ---: | ---: | ---: |
|
|
119
|
-
| `deepseek-v4.1-flash` | 2026-09-10 | 0.30 | 1.20 | 0.006 |
|
|
120
|
-
| `deepseek-v4-pro-0813` | 2026-08-13 | 1.32 | 3.96 | 0.044 |
|
|
121
|
-
|
|
122
|
-
表中采用官方**峰值时段最高价**作为保守估算上界;非峰值时段实际费率为表中一半。历史消息没有保留请求发生时对应的计费时段,无法准确选择峰谷档。已退役的 `deepseek-v4-flash` 与 `deepseek-v4-flash-vision-exp` 当前由官方路由到 V4.1 Flash 并按 Flash 价格计费;`deepseek-v4-flash-0731` 作为明确版本别名映射到同一条目。`deepseek-v4-pro` 当前对应 V4-Pro-0813。
|
|
123
|
-
|
|
124
|
-
## Moonshot(Kimi)
|
|
125
|
-
|
|
126
|
-
来源:[Kimi Model Inference Pricing](https://platform.moonshot.ai/docs/pricing)
|
|
127
|
-
|
|
128
|
-
| 模型 | 发布日期 | Input | Output | Cache Read | Cache Write |
|
|
129
|
-
| --- | --- | ---: | ---: | ---: | ---: |
|
|
130
|
-
| `kimi-k3` | 2026-07-15 | 3 | 15 | 0.30 | 3(5 分钟 TTL) |
|
|
131
|
-
| `kimi-k2.7-code` | 2026-06-12 | 0.95 | 4.00 | 0.19 | — |
|
|
132
|
-
| `kimi-k2.6` | 2026-04-20 | 0.95 | 4.00 | 0.16 | — |
|
|
133
|
-
|
|
134
|
-
K3 同时公布 5 分钟与 1 小时 cache write,快照沿用 Anthropic 约定取 5 分钟档;K2 系列只公布 cache 命中输入价,没有 cache write 价。
|
|
135
|
-
|
|
136
|
-
## 阿里云百炼(Qwen)
|
|
137
|
-
|
|
138
|
-
来源:[Model Studio Model inference pricing](https://www.alibabacloud.com/help/en/model-studio/model-pricing)(新加坡 International 站点标准价)
|
|
139
|
-
|
|
140
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
141
|
-
| --- | --- | ---: | ---: | ---: |
|
|
142
|
-
| `qwen3.8-max`(含别名 `qwen3.8-max-0902`) | 2026-08-03 | 2 | 6 | — |
|
|
143
|
-
| `qwen3.8-2.4t-a95b` | 2026-08-12 | 2 | 6 | — |
|
|
144
|
-
| `qwen3.8-27b` | 2026-08-14 | 0.5 | 3 | 0.1 |
|
|
145
|
-
| `qwen3.8-flash` | 2026-08-26 | 0.15 | 0.47 | — |
|
|
146
|
-
| `qwen3.7-max` | 2026-05-20 | 2.5 | 7.5 | 0.5 |
|
|
147
|
-
| `qwen3.7-plus` | 2026-05-26 | 0.4 / 1.2(>256K) | 1.6 / 4.8(>256K) | 0.08 / 0.24(>256K) |
|
|
148
|
-
| `qwen3.7-flash` | 2026-07-15 | 0.03 / 0.10 / 0.20(>32K、>256K) | 0.13 / 0.40 / 0.80(>32K、>256K) | 0.006 / 0.02 / 0.04(>32K、>256K) |
|
|
149
|
-
| `qwen3.6-max-preview` | 2026-04-20 | 1.3 / 2(>128K) | 7.8 / 12(>128K) | — |
|
|
150
|
-
| `qwen3.6-plus` | 2026-04-02 | 0.5 / 2(>256K) | 3 / 6(>256K) | — |
|
|
151
|
-
| `qwen3.6-flash` | 2026-04-16 | 0.25 / 1(>256K) | 1.5 / 4(>256K) | — |
|
|
152
|
-
| `qwen3.6-27b` | 2026-04-22 | 0.6 | 3.6 | — |
|
|
153
|
-
| `qwen3.6-35b-a3b` | 2026-04-15 | 0.375 | 2.25 | — |
|
|
154
|
-
| `qwen3.5-plus-2026-04-20`(别名 `qwen3.5-plus-20260420`) | 2026-04-20 | 0.4 / 0.5(>256K) | 2.4 / 3(>256K) | — |
|
|
155
|
-
|
|
156
|
-
档位边界按官方措辞换算:`256K<Token≤1M` 即传入超过 256,000 token 启用高价档。Cache Read 收录官方隐式缓存命中价(所在档 Input 的 20%),仅限官方公布该费率的模型;`qwen3.8-max`、`qwen3.8-max-0902`、`qwen3.8-flash`、`qwen3.8-2.4t-a95b` 的缓存价只在控制台公布,不收录。隐式缓存创建按 Input 100% 计费、显式缓存创建按 125% 计费,聚合字段无法区分,因此一律不收 Cache Write。`qwen3.7-plus` 页面当前标注限期 8 折,快照采用未打折的刊例价。
|
|
157
|
-
|
|
158
|
-
## 小米(MiMo)
|
|
159
|
-
|
|
160
|
-
来源:[Xiaomi MiMo API Pricing](https://mimo.mi.com/docs/price/pay-as-you-go)(海外美元价)
|
|
161
|
-
|
|
162
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
163
|
-
| --- | --- | ---: | ---: | ---: |
|
|
164
|
-
| `mimo-v2.5` | 2026-04-22 | 0.14 | 0.28 | 0.0028 |
|
|
165
|
-
| `mimo-v2.5-pro` | 2026-04-22 | 0.435 | 0.87 | 0.0036 |
|
|
166
|
-
| `mimo-v2.6-flash` | 2026-09-21 | 0.14 | 0.28 | 0.0028 |
|
|
167
|
-
| `mimo-v2.6-pro` | 2026-09-21 | 0.435 | 0.87 | 0.0036 |
|
|
168
|
-
| `mimo-v2.6-pro-ultraspeed` | 2026-09-21 | 4.35 | 8.7 | 0.036 |
|
|
169
|
-
|
|
170
|
-
V2.6 系列官方宣布沿用 V2.5 系列 API 定价。Cache Write 官方限期免费,不设 token 价。
|
|
171
|
-
|
|
172
|
-
## MiniMax
|
|
173
|
-
|
|
174
|
-
来源:[MiniMax Pay as You Go](https://platform.minimax.io/docs/guides/pricing-paygo)
|
|
175
|
-
|
|
176
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
177
|
-
| --- | --- | ---: | ---: | ---: |
|
|
178
|
-
| `minimax-m3` | 2026-05-31 | 0.30 / 0.60(>512K) | 1.20 / 2.40(>512K) | 0.06 / 0.12(>512K) |
|
|
179
|
-
|
|
180
|
-
M3 页面标注"长期 5 折",快照按核验日的实收价收录;官方只公布 cache 读取价,没有 cache write 价。
|
|
181
|
-
|
|
182
|
-
## 腾讯(混元)
|
|
183
|
-
|
|
184
|
-
来源:[Tencent Cloud TokenHub Model pricing](https://intl.cloud.tencent.com/document/product/1300/78937)(新加坡国际站美元价)
|
|
185
|
-
|
|
186
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
187
|
-
| --- | --- | ---: | ---: | ---: |
|
|
188
|
-
| `hy3` | 2026-07-06 | 0.132 | 0.528 | 0.033 |
|
|
189
|
-
| `hy4-preview` | 2026-08-27 | 0.834 | 2.501 | 0.042 |
|
|
190
|
-
|
|
191
|
-
官方页面只公布 cache 命中价,没有 cache write 价。
|
|
192
|
-
|
|
193
|
-
## StepFun
|
|
194
|
-
|
|
195
|
-
来源:[StepFun Pricing Details](https://platform.stepfun.ai/docs/en/guides/pricing/details)(海外站)
|
|
196
|
-
|
|
197
|
-
| 模型 | 发布日期 | Input | Output | Cache Read | Cache Write |
|
|
198
|
-
| --- | --- | ---: | ---: | ---: | ---: |
|
|
199
|
-
| `step-5-preview` | 2026-09-21 | 1 | 2.7 | 0.05 | 1 |
|
|
200
|
-
| `step-3.7-flash` | 2026-05-28 | 0.20 | 1.15 | 0.04 | — |
|
|
201
|
-
|
|
202
|
-
Step 5 Preview 官方明确说明 cache-miss Input 包含首次缓存写入,因此 OpenCode 单独上报的 Cache Write 按同一 `$1 / M` 费率计算。按 7:2:1 的 Cache Read / Input / Output token 比例,综合价为 `(7 × 0.05 + 2 × 1 + 1 × 2.7) / 10 = $0.505 / M`,约 `$0.51 / M`;该数值仅用于场景比较,插件仍按每条消息的实际五类 token 计算。Step 3.7 Flash 没有公布独立 cache write 价。
|
|
203
|
-
|
|
204
|
-
## Meta(Muse Spark)
|
|
205
|
-
|
|
206
|
-
来源:[Meta Model API Pricing and rate limits](https://ai.developer.meta.com/docs/pricing-rate-limits)
|
|
207
|
-
|
|
208
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
209
|
-
| --- | --- | ---: | ---: | ---: |
|
|
210
|
-
| `muse-spark-1.1` | 2026-07-09 | 1.25 | 4.25 | 0.15 |
|
|
211
|
-
| `muse-spark-1.2` | 2026-08-05 | 1.25 | 4.25 | 0.15 |
|
|
212
|
-
| `muse-spark-1.3` | 2026-09-02 | 1.25 | 4.25 | 0.15 |
|
|
213
|
-
|
|
214
|
-
Contributor tier 以允许 Meta 使用提示词和回答进行训练为条件,按独立 tier 记录。官方没有公布 cache write token 价。
|
|
215
|
-
|
|
216
|
-
| Contributor 模型 | 发布日期 | Input | Output | Cache Read | Cache Write |
|
|
217
|
-
| --- | --- | ---: | ---: | ---: | ---: |
|
|
218
|
-
| `muse-spark-1.2-contributor` | 2026-08-05 | 0.10 | 0.20 | 0.002 | — |
|
|
219
|
-
| `muse-spark-1.3-contributor` | 2026-09-02 | 0.10 | 0.20 | 0.002 | — |
|
|
220
|
-
|
|
221
|
-
OpenCode Zen 的 `muse-spark-1.2-contributor-free` 和 `muse-spark-1.3-contributor-free` 会精确匹配各自 Contributor 条目;Est. Cost 因此按 Meta Contributor 费率估算。
|
|
222
|
-
|
|
223
|
-
## Inception
|
|
224
|
-
|
|
225
|
-
来源:[Inception Models](https://www.inceptionlabs.ai/models)
|
|
226
|
-
|
|
227
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
228
|
-
| --- | --- | ---: | ---: | ---: |
|
|
229
|
-
| `mercury-2.5`(别名 `mercury-2.5-preview`) | 2026-09-08 | 0.04 | 0.15 | 0.004 |
|
|
230
|
-
|
|
231
|
-
官网在核验日同时显示 `$0.20 / $0.75 / $0.02` 的刊例价和 80% off 的当前 API 价;快照采用当前实收的促销价,未使用 OpenRouter 自行报价。官方没有公布 cache write token 价。
|
|
232
|
-
|
|
233
|
-
## Upstage
|
|
234
|
-
|
|
235
|
-
来源:[Solar Pro 4 model page](https://console.upstage.ai/docs/models/solar-pro-4)
|
|
236
|
-
|
|
237
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
238
|
-
| --- | --- | ---: | ---: | ---: |
|
|
239
|
-
| `solar-pro4`(别名 `solar-pro4-260806`) | 2026-08-06 | 0.30 | 1.20 | 0.06 |
|
|
240
|
-
|
|
241
|
-
Solar Pro 4 的 90% off 活动已于 2026-09-10 结束,快照采用模型页当前标准 Console API 价;官方没有公布 cache write token 价。
|
|
242
|
-
|
|
243
|
-
## Arcee AI
|
|
244
|
-
|
|
245
|
-
来源:[Arcee Platform Pricing](https://docs.arcee.ai/get-started/pricing)
|
|
246
|
-
|
|
247
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
248
|
-
| --- | --- | ---: | ---: | ---: |
|
|
249
|
-
| `trinity-large-thinking` | 2026-04-01 | 0.25 | 0.80 | 0.06 |
|
|
250
|
-
|
|
251
|
-
该条目是 Arcee 托管 API 的标准推理价;模型同时提供开源权重,但本目录只记录 API 费用。官方没有公布 cache write token 价。
|
|
252
|
-
|
|
253
|
-
## ByteDance Seed
|
|
254
|
-
|
|
255
|
-
来源:[BytePlus ModelArk Pricing](https://docs.byteplus.com/en/docs/ModelArk/1099320)、[Seed2.1 release](https://seed.bytedance.com/en/blog/seed2-1-officially-released-advancing-ai-productivity)
|
|
256
|
-
|
|
257
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
258
|
-
| --- | --- | ---: | ---: | ---: |
|
|
259
|
-
| `dola-seed-2-1-turbo`(别名 `seed-2-1-turbo`、`dola-seed-2-1-turbo-260628`) | 2026-06-23 | 0.50 | 2.50 | 0.10 |
|
|
260
|
-
|
|
261
|
-
表中采用 BytePlus ModelArk 在线标准推理价。缓存存储按 token·小时另行收费,不是可由当前五类 token 统计表示的 Cache Write 单价,因此不收录。
|
|
262
|
-
|
|
263
|
-
## Sakana Fugu
|
|
264
|
-
|
|
265
|
-
来源:[Sakana Fugu Pricing](https://console.sakana.ai/pricing)、[Fugu Max and Fugu Ultra v2 release](https://sakana.ai/fugu-max-release)
|
|
266
|
-
|
|
267
|
-
| 模型 | 发布日期 | Input | Output | Cache Read | 长上下文档位 |
|
|
268
|
-
| --- | --- | ---: | ---: | ---: | --- |
|
|
269
|
-
| `fugu-ultra-v2.0`(别名 `fugu-ultra-v2`) | 2026-09-11 | 5 | 30 | 0.50 | >272K:10 / 45 / 1 |
|
|
270
|
-
| `fugu-max-v1.0`(别名 `fugu-max`) | 2026-09-11 | 2 | 6 | 0.25 | — |
|
|
271
|
-
|
|
272
|
-
Fugu Ultra 的编排 token 已包含在 API 返回的 input/output 用量中,按同一 token 价估算;web search/web fetch 等工具调用费不是五类 token,故不计入 Est. Cost。官方没有公布 cache write token 价。
|
|
273
|
-
|
|
274
|
-
## Aion Labs
|
|
275
|
-
|
|
276
|
-
来源:[Aion Labs Models](https://www.aionlabs.ai/docs/models)
|
|
277
|
-
|
|
278
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
279
|
-
| --- | --- | ---: | ---: | ---: |
|
|
280
|
-
| `aion-3.0`(别名 `aion-labs/aion-3.0`) | 2026-05-05 | 3.00 | 6.00 | 0.75 |
|
|
281
|
-
| `aion-3.0-mini`(别名 `aion-labs/aion-3.0-mini`) | 2026-05-14 | 0.70 | 1.40 | 0.18 |
|
|
282
|
-
|
|
283
|
-
表中是 Aion Labs 自家 API 目录公布的 per-token 价,不是 OpenRouter 网关价;官方没有公布 cache write token 价。Aion 3.0 与 3.0 Mini 是基于 GLM / DeepSeek 家族的多模型协作系统,按一次请求的输入输出 token 计费。
|
|
284
|
-
|
|
285
|
-
## 美团(LongCat)
|
|
286
|
-
|
|
287
|
-
来源:[LongCat API Docs — LongCat-2.0 Pricing](https://longcat.chat/platform/docs/Pricing/LongCat-2.0.html)、[LongCat-2.0 发布](https://www.meituan.com/news/NN260630164005904)
|
|
288
|
-
|
|
289
|
-
| 模型 | 发布日期 | Input | Output | Cache Read |
|
|
290
|
-
| --- | --- | ---: | ---: | ---: |
|
|
291
|
-
| `longcat-2.0` | 2026-06-30 | 0.30 | 1.20 | 0.006 |
|
|
292
|
-
|
|
293
|
-
官方页面同时列出刊例价($0.75 / $2.95 / $0.015)与限时活动价;与 MiniMax-M3、Mercury 2.5 相同,快照按核验日实际计收的限时价收录。官方没有公布 cache write token 价,缓存存储也不同 token 计费。
|
|
294
|
-
|
|
295
|
-
## 暂不收录
|
|
296
|
-
|
|
297
|
-
- Realtime、音频、图片、视频、embedding、按页、按分钟和按工具调用收费的模型无法仅由当前五类 token 用量准确计算。
|
|
298
|
-
- `grok-4.20`、`grok-4.20-multi-agent` 发布于 2026-03-09,早于目录收录窗口起点 2026-03-22。
|
|
299
|
-
- Fast/Priority 等其他未列出的加速档(例如 `claude-opus-4-7-fast`、`gpt-5.5-pro-fast`、`gpt-6-astra-pro` 和 MiniMax priority 档)不收录;上表列出当前快照中官方定价页明确支持的 GPT 与 Claude Fast 型号。
|
|
300
|
-
- 其他免费模型(Gemma 系列、`cohere/north-mini-code` 等开源或网关零价款)不设价格条目。
|
|
301
|
-
- 无法从厂商官方页面确认标准 token 价格的模型不猜价,包括 OpenRouter stealth/alpha 匿名模型、`z-ai/glm-5v-turbo`、`qwen3.6-plus-preview`、腾讯 `hy3-preview` 与 `hy-mt2-*`、`kwaipilot/kat-coder-pro-v2.5` 及其 Air 版本、除上表 OpenCode Zen SKU 外的 `inclusionai/ling-3.0-*`、`bytedance-seed/seed-2.0-code` 等。这些模型目前只能查到 OpenRouter、AtlasCloud、DeepInfra 等网关或第三方报价,不能据此推断厂商标准价。
|
|
302
|
-
- 浮动别名(`-latest` 指针与 OpenRouter `~` 前缀条目)随底层模型漂移,不收录固定价。
|
|
303
|
-
- 只有询价、托管部署价或无法从厂商官方页面确认标准 token 价格的模型不猜价。
|
|
37
|
+
**Est. Cost 仍只是估算,不代表提供商账单**:快照可能滞后,也不含网关加价、地域价、未记录的促销或折扣、工具费和税费。更新时应复核有时效性的人工例外。
|
package/docs/verification.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# 验证记录
|
|
2
2
|
|
|
3
|
+
## v0.4.3 开发验证(`/usage` 模型费率展示)
|
|
4
|
+
|
|
5
|
+
验证日期:2026-09-29。Node.js v22.23.2;SDK 2.0.11;真实宿主使用隔离的 `@opencode/cli-darwin-arm64@2.0.11`,包版本仍为 0.4.2。
|
|
6
|
+
|
|
7
|
+
| 检查 | 结果 |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `npm run typecheck` | 通过 |
|
|
10
|
+
| `npm test` | 69 项通过 |
|
|
11
|
+
| `npm run build` | 通过 |
|
|
12
|
+
| `npm run test:smoke` | 通过,打包产物 + 真实 OpenCode 2.0.11 + 本地模拟提供商 |
|
|
13
|
+
|
|
14
|
+
`/usage` 的 By Model 详细模式按逐消息估算实际采用的 OpenCode/内置快照价格及上下文档位列出五类 token 费率和调用数;紧凑模式不显示费率。自动化测试覆盖同模型跨来源/档位、Reasoning 沿用 Output、零价、缺价和 `partial`,并核对逐模型与全树费用。真实宿主测试验证 160 × 54 与 100 × 28 终端的展开/收起、48 × 28 终端的单列费率,以及内置快照回退来源;未向付费模型发送请求。测试产物保存在 `/var/folders/rw/bmx6c8hd737brl55m0_ff_b80000gn/T/token-usage-smoke-4RnnLf`。
|
|
15
|
+
|
|
16
|
+
## v0.4.2(正确性与刷新性能)
|
|
17
|
+
|
|
18
|
+
验证日期:2026-09-26。Node.js v22.23.2;SDK 2.0.11;真实宿主使用校验 npm SHA-512 完整性的 `@opencode/cli-darwin-arm64@2.0.11` 隔离二进制。
|
|
19
|
+
|
|
20
|
+
| 检查 | 结果 |
|
|
21
|
+
| --- | --- |
|
|
22
|
+
| `npm run typecheck` | 通过 |
|
|
23
|
+
| `npm test` | 67 项通过 |
|
|
24
|
+
| `npm run build` | 通过 |
|
|
25
|
+
| `npm run test:smoke` | 通过,打包产物 + 真实 OpenCode 2.0.11 + 本地模拟提供商;新增删除会话后的 context 清理断言 |
|
|
26
|
+
|
|
27
|
+
TTFT 的快照先到、step 结束先到,以及缺少结束事件三种情况都有保留期清理测试;快照后继续收到 delta 时恢复实时估算,不提前丢失 TTFT。无关会话的创建与分叉不触发当前树刷新;新子代理仍立即纳入,切换会话仍隔离旧请求。流式性能更新使用每次完整快照预计算的历史基线,不再为每个 delta 遍历全部历史。
|
|
28
|
+
|
|
29
|
+
大会话树测试包含根会话和 80 个子会话:首次完整读取 161 个消息页;单个子会话变化后的完整快照只重读该会话的 1 页,跨会话读取同时最多 4 个。每次仍重新枚举子会话,以发现新增与删除;分页失败或请求超时不会替换上一次完整快照,重试后恢复。被查看会话的 Context 按 `SessionInfo.revert.messageID` 截断有效消息,再应用最后一次已完成 compaction 边界;测试覆盖回退、重新生成和压缩,阶段性回退不会扣除已产生的全树费用。
|
|
30
|
+
|
|
31
|
+
`context` 钩子累计记录 MCP 等待与存储写入耗时;MCP 名称缓存 30 秒,并在连接状态变化时失效。存储写入按会话顺序异步执行,模型请求不等待持久化完成;删除事件会等待该会话未完成的写入后清理 `context/<sessionID>`。自动化测试验证缓存、写入顺序、延迟与删除竞争;打包集成测试确认真实宿主删除会话后 RPC 返回空估算。
|
|
32
|
+
|
|
3
33
|
## v0.4.0(子代理用量浮窗)
|
|
4
34
|
|
|
5
35
|
验证日期:2026-09-24。Node.js v22.23.2;SDK 2.0.11,隔离的真实 OpenCode 2.0.11 宿主。
|
|
@@ -218,3 +248,9 @@ Python 3 为真实 TUI 提供 160 × 54 的伪终端,终端输出经 xterm 解
|
|
|
218
248
|
- 多层分页、压缩与分叉去重、故障恢复由自动化逻辑测试覆盖;真实 TUI 验证覆盖加载、正常消息、一级真实子代理和模型切换。
|
|
219
249
|
|
|
220
250
|
重现时运行 README 中的检查命令。烟雾测试会输出临时产物目录,包含 `result.json`、`plugins.json`、各阶段终端捕获和已隐藏服务器密码的日志。
|
|
251
|
+
|
|
252
|
+
## 2026-09-25 · 原厂价格半自动更新
|
|
253
|
+
|
|
254
|
+
`npm run prices:update` 从 models.dev API 提取经审核的原厂 Provider 自家文本型号,生成离线 `src/prices.generated.ts`:本次为 283 条生成价格,叠加已核实例外后为 296 条。脚本重跑时确认生成内容不变(新增、删除、变化均为 0)。例外与原厂过滤在 `src/overrides.ts`,精确别名在 `src/aliases.ts`;网关/地域/订阅报价不作为数据源。
|
|
255
|
+
|
|
256
|
+
已通过 `npm run typecheck`、55 项 `npm test` 和 `npm run build`。使用临时安装的 OpenCode v2.0.11 运行 `npm run test:smoke`,打包安装后的插件通过侧边栏、`/usage`、真实子代理、模型切换、无 OpenCode 价格时的内置回退等检查;打包产物包含生成快照、别名和例外模块。当前机器默认 OpenCode v2.0.16 未参与本次集成验证。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chenlongapps/opencode-token-usage",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
4
|
"description": "Session-tree token usage, live performance, context window and estimated cost for OpenCode 2",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"opencode",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"typecheck": "tsc --noEmit",
|
|
50
50
|
"test": "tsx --test test/*.test.ts",
|
|
51
51
|
"test:smoke": "node scripts/smoke.mjs",
|
|
52
|
+
"prices:update": "tsx scripts/update-prices.ts",
|
|
52
53
|
"release:patch": "npm version patch",
|
|
53
54
|
"prepublishOnly": "npm run typecheck && npm test",
|
|
54
55
|
"prepack": "npm run build"
|