ccus-cli 0.2.10 → 0.2.12

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.
@@ -0,0 +1,270 @@
1
+ {
2
+ "catalogVersion": "2026-08-17",
3
+ "currency": "USD",
4
+ "basis": "event-time-standard-api",
5
+ "entries": [
6
+ {
7
+ "provider": "claude",
8
+ "model": "claude-opus-3",
9
+ "effectiveFrom": "2024-02-29T00:00:00.000Z",
10
+ "effectiveTo": null,
11
+ "prices": { "inputUsdPerMillion": 15, "outputUsdPerMillion": 75, "cacheReadInputUsdPerMillion": 1.5, "cacheWrite5mInputUsdPerMillion": 18.75, "cacheWrite1hInputUsdPerMillion": 30 }
12
+ },
13
+ {
14
+ "provider": "claude",
15
+ "model": "claude-haiku-3",
16
+ "effectiveFrom": "2024-03-13T00:00:00.000Z",
17
+ "effectiveTo": null,
18
+ "prices": { "inputUsdPerMillion": 0.25, "outputUsdPerMillion": 1.25, "cacheReadInputUsdPerMillion": 0.025, "cacheWrite5mInputUsdPerMillion": 0.3125, "cacheWrite1hInputUsdPerMillion": 0.5 }
19
+ },
20
+ {
21
+ "provider": "claude",
22
+ "model": "claude-sonnet-3.5",
23
+ "effectiveFrom": "2024-06-20T00:00:00.000Z",
24
+ "effectiveTo": null,
25
+ "prices": { "inputUsdPerMillion": 3, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.3, "cacheWrite5mInputUsdPerMillion": 3.75, "cacheWrite1hInputUsdPerMillion": 6 }
26
+ },
27
+ {
28
+ "provider": "claude",
29
+ "model": "claude-haiku-3.5",
30
+ "effectiveFrom": "2024-10-22T00:00:00.000Z",
31
+ "effectiveTo": null,
32
+ "prices": { "inputUsdPerMillion": 0.8, "outputUsdPerMillion": 4, "cacheReadInputUsdPerMillion": 0.08, "cacheWrite5mInputUsdPerMillion": 1, "cacheWrite1hInputUsdPerMillion": 1.6 }
33
+ },
34
+ {
35
+ "provider": "claude",
36
+ "model": "claude-sonnet-3.7",
37
+ "effectiveFrom": "2025-02-24T00:00:00.000Z",
38
+ "effectiveTo": null,
39
+ "prices": { "inputUsdPerMillion": 3, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.3, "cacheWrite5mInputUsdPerMillion": 3.75, "cacheWrite1hInputUsdPerMillion": 6 }
40
+ },
41
+ {
42
+ "provider": "claude",
43
+ "model": "claude-opus-4",
44
+ "effectiveFrom": "2025-05-22T00:00:00.000Z",
45
+ "effectiveTo": null,
46
+ "prices": { "inputUsdPerMillion": 15, "outputUsdPerMillion": 75, "cacheReadInputUsdPerMillion": 1.5, "cacheWrite5mInputUsdPerMillion": 18.75, "cacheWrite1hInputUsdPerMillion": 30 }
47
+ },
48
+ {
49
+ "provider": "claude",
50
+ "model": "claude-sonnet-4",
51
+ "effectiveFrom": "2025-05-22T00:00:00.000Z",
52
+ "effectiveTo": null,
53
+ "prices": { "inputUsdPerMillion": 3, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.3, "cacheWrite5mInputUsdPerMillion": 3.75, "cacheWrite1hInputUsdPerMillion": 6 },
54
+ "longContext": {
55
+ "thresholdInputTokens": 200000,
56
+ "prices": { "inputUsdPerMillion": 6, "outputUsdPerMillion": 22.5, "cacheReadInputUsdPerMillion": 0.6, "cacheWrite5mInputUsdPerMillion": 7.5, "cacheWrite1hInputUsdPerMillion": 12 }
57
+ }
58
+ },
59
+ {
60
+ "provider": "claude",
61
+ "model": "claude-opus-4.1",
62
+ "effectiveFrom": "2025-08-05T00:00:00.000Z",
63
+ "effectiveTo": null,
64
+ "prices": { "inputUsdPerMillion": 15, "outputUsdPerMillion": 75, "cacheReadInputUsdPerMillion": 1.5, "cacheWrite5mInputUsdPerMillion": 18.75, "cacheWrite1hInputUsdPerMillion": 30 }
65
+ },
66
+ {
67
+ "provider": "claude",
68
+ "model": "claude-sonnet-4.5",
69
+ "effectiveFrom": "2025-09-29T00:00:00.000Z",
70
+ "effectiveTo": null,
71
+ "prices": { "inputUsdPerMillion": 3, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.3, "cacheWrite5mInputUsdPerMillion": 3.75, "cacheWrite1hInputUsdPerMillion": 6 },
72
+ "longContext": {
73
+ "thresholdInputTokens": 200000,
74
+ "prices": { "inputUsdPerMillion": 6, "outputUsdPerMillion": 22.5, "cacheReadInputUsdPerMillion": 0.6, "cacheWrite5mInputUsdPerMillion": 7.5, "cacheWrite1hInputUsdPerMillion": 12 }
75
+ }
76
+ },
77
+ {
78
+ "provider": "claude",
79
+ "model": "claude-haiku-4.5",
80
+ "effectiveFrom": "2025-10-15T00:00:00.000Z",
81
+ "effectiveTo": null,
82
+ "prices": { "inputUsdPerMillion": 1, "outputUsdPerMillion": 5, "cacheReadInputUsdPerMillion": 0.1, "cacheWrite5mInputUsdPerMillion": 1.25, "cacheWrite1hInputUsdPerMillion": 2 }
83
+ },
84
+ {
85
+ "provider": "claude",
86
+ "model": "claude-opus-4.5",
87
+ "effectiveFrom": "2025-11-24T00:00:00.000Z",
88
+ "effectiveTo": null,
89
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 25, "cacheReadInputUsdPerMillion": 0.5, "cacheWrite5mInputUsdPerMillion": 6.25, "cacheWrite1hInputUsdPerMillion": 10 }
90
+ },
91
+ {
92
+ "provider": "claude",
93
+ "model": "claude-opus-4.6",
94
+ "effectiveFrom": "2026-02-05T00:00:00.000Z",
95
+ "effectiveTo": null,
96
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 25, "cacheReadInputUsdPerMillion": 0.5, "cacheWrite5mInputUsdPerMillion": 6.25, "cacheWrite1hInputUsdPerMillion": 10 }
97
+ },
98
+ {
99
+ "provider": "claude",
100
+ "model": "claude-sonnet-4.6",
101
+ "effectiveFrom": "2026-02-17T00:00:00.000Z",
102
+ "effectiveTo": null,
103
+ "prices": { "inputUsdPerMillion": 3, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.3, "cacheWrite5mInputUsdPerMillion": 3.75, "cacheWrite1hInputUsdPerMillion": 6 },
104
+ "longContext": {
105
+ "thresholdInputTokens": 200000,
106
+ "prices": { "inputUsdPerMillion": 6, "outputUsdPerMillion": 22.5, "cacheReadInputUsdPerMillion": 0.6, "cacheWrite5mInputUsdPerMillion": 7.5, "cacheWrite1hInputUsdPerMillion": 12 }
107
+ }
108
+ },
109
+ {
110
+ "provider": "claude",
111
+ "model": "claude-opus-4.7",
112
+ "effectiveFrom": "2026-04-16T00:00:00.000Z",
113
+ "effectiveTo": null,
114
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 25, "cacheReadInputUsdPerMillion": 0.5, "cacheWrite5mInputUsdPerMillion": 6.25, "cacheWrite1hInputUsdPerMillion": 10 }
115
+ },
116
+ {
117
+ "provider": "claude",
118
+ "model": "claude-opus-4.8",
119
+ "effectiveFrom": "2026-05-28T00:00:00.000Z",
120
+ "effectiveTo": null,
121
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 25, "cacheReadInputUsdPerMillion": 0.5, "cacheWrite5mInputUsdPerMillion": 6.25, "cacheWrite1hInputUsdPerMillion": 10 }
122
+ },
123
+ {
124
+ "provider": "claude",
125
+ "model": "claude-fable-5",
126
+ "effectiveFrom": "2026-06-09T00:00:00.000Z",
127
+ "effectiveTo": null,
128
+ "prices": { "inputUsdPerMillion": 10, "outputUsdPerMillion": 50, "cacheReadInputUsdPerMillion": 1, "cacheWrite5mInputUsdPerMillion": 12.5, "cacheWrite1hInputUsdPerMillion": 20 }
129
+ },
130
+ {
131
+ "provider": "claude",
132
+ "model": "claude-sonnet-5",
133
+ "effectiveFrom": "2026-06-30T00:00:00.000Z",
134
+ "effectiveTo": "2026-09-01T00:00:00.000Z",
135
+ "prices": { "inputUsdPerMillion": 2, "outputUsdPerMillion": 10, "cacheReadInputUsdPerMillion": 0.2, "cacheWrite5mInputUsdPerMillion": 2.5, "cacheWrite1hInputUsdPerMillion": 4 }
136
+ },
137
+ {
138
+ "provider": "claude",
139
+ "model": "claude-sonnet-5",
140
+ "effectiveFrom": "2026-09-01T00:00:00.000Z",
141
+ "effectiveTo": null,
142
+ "prices": { "inputUsdPerMillion": 3, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.3, "cacheWrite5mInputUsdPerMillion": 3.75, "cacheWrite1hInputUsdPerMillion": 6 }
143
+ },
144
+ {
145
+ "provider": "claude",
146
+ "model": "claude-opus-5",
147
+ "effectiveFrom": "2026-07-24T00:00:00.000Z",
148
+ "effectiveTo": null,
149
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 25, "cacheReadInputUsdPerMillion": 0.5, "cacheWrite5mInputUsdPerMillion": 6.25, "cacheWrite1hInputUsdPerMillion": 10 }
150
+ },
151
+ {
152
+ "provider": "codex",
153
+ "model": "gpt-5",
154
+ "effectiveFrom": "2025-08-07T00:00:00.000Z",
155
+ "effectiveTo": null,
156
+ "prices": { "inputUsdPerMillion": 1.25, "outputUsdPerMillion": 10, "cacheReadInputUsdPerMillion": 0.125 }
157
+ },
158
+ {
159
+ "provider": "codex",
160
+ "model": "gpt-5-codex",
161
+ "effectiveFrom": "2025-09-23T00:00:00.000Z",
162
+ "effectiveTo": null,
163
+ "prices": { "inputUsdPerMillion": 1.25, "outputUsdPerMillion": 10, "cacheReadInputUsdPerMillion": 0.125 }
164
+ },
165
+ {
166
+ "provider": "codex",
167
+ "model": "gpt-5.1",
168
+ "effectiveFrom": "2025-11-13T00:00:00.000Z",
169
+ "effectiveTo": null,
170
+ "prices": { "inputUsdPerMillion": 1.25, "outputUsdPerMillion": 10, "cacheReadInputUsdPerMillion": 0.125 }
171
+ },
172
+ {
173
+ "provider": "codex",
174
+ "model": "gpt-5.1-codex",
175
+ "effectiveFrom": "2025-11-13T00:00:00.000Z",
176
+ "effectiveTo": null,
177
+ "prices": { "inputUsdPerMillion": 1.25, "outputUsdPerMillion": 10, "cacheReadInputUsdPerMillion": 0.125 }
178
+ },
179
+ {
180
+ "provider": "codex",
181
+ "model": "gpt-5.1-codex-mini",
182
+ "effectiveFrom": "2025-11-13T00:00:00.000Z",
183
+ "effectiveTo": null,
184
+ "prices": { "inputUsdPerMillion": 0.25, "outputUsdPerMillion": 2, "cacheReadInputUsdPerMillion": 0.025 }
185
+ },
186
+ {
187
+ "provider": "codex",
188
+ "model": "gpt-5.1-codex-max",
189
+ "effectiveFrom": "2025-12-04T00:00:00.000Z",
190
+ "effectiveTo": null,
191
+ "prices": { "inputUsdPerMillion": 1.25, "outputUsdPerMillion": 10, "cacheReadInputUsdPerMillion": 0.125 }
192
+ },
193
+ {
194
+ "provider": "codex",
195
+ "model": "gpt-5.2",
196
+ "effectiveFrom": "2025-12-11T00:00:00.000Z",
197
+ "effectiveTo": null,
198
+ "prices": { "inputUsdPerMillion": 1.75, "outputUsdPerMillion": 14, "cacheReadInputUsdPerMillion": 0.175 }
199
+ },
200
+ {
201
+ "provider": "codex",
202
+ "model": "gpt-5.2-codex",
203
+ "effectiveFrom": "2025-12-18T00:00:00.000Z",
204
+ "effectiveTo": null,
205
+ "prices": { "inputUsdPerMillion": 1.75, "outputUsdPerMillion": 14, "cacheReadInputUsdPerMillion": 0.175 }
206
+ },
207
+ {
208
+ "provider": "codex",
209
+ "model": "gpt-5.3-codex",
210
+ "effectiveFrom": "2026-02-05T00:00:00.000Z",
211
+ "effectiveTo": null,
212
+ "prices": { "inputUsdPerMillion": 1.75, "outputUsdPerMillion": 14, "cacheReadInputUsdPerMillion": 0.175 }
213
+ },
214
+ {
215
+ "provider": "codex",
216
+ "model": "gpt-5.4",
217
+ "effectiveFrom": "2026-03-05T00:00:00.000Z",
218
+ "effectiveTo": null,
219
+ "prices": { "inputUsdPerMillion": 2.5, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.25 },
220
+ "longContext": {
221
+ "thresholdInputTokens": 272000,
222
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 22.5, "cacheReadInputUsdPerMillion": 0.5 }
223
+ }
224
+ },
225
+ {
226
+ "provider": "codex",
227
+ "model": "gpt-5.5",
228
+ "effectiveFrom": "2026-05-01T00:00:00.000Z",
229
+ "effectiveTo": null,
230
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 30, "cacheReadInputUsdPerMillion": 0.5 },
231
+ "longContext": {
232
+ "thresholdInputTokens": 272000,
233
+ "prices": { "inputUsdPerMillion": 10, "outputUsdPerMillion": 45, "cacheReadInputUsdPerMillion": 1 }
234
+ }
235
+ },
236
+ {
237
+ "provider": "codex",
238
+ "model": "gpt-5.6-sol",
239
+ "effectiveFrom": "2026-08-01T00:00:00.000Z",
240
+ "effectiveTo": null,
241
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 30, "cacheReadInputUsdPerMillion": 0.5 },
242
+ "longContext": {
243
+ "thresholdInputTokens": 272000,
244
+ "prices": { "inputUsdPerMillion": 10, "outputUsdPerMillion": 45, "cacheReadInputUsdPerMillion": 1 }
245
+ }
246
+ },
247
+ {
248
+ "provider": "codex",
249
+ "model": "gpt-5.6-terra",
250
+ "effectiveFrom": "2026-08-01T00:00:00.000Z",
251
+ "effectiveTo": null,
252
+ "prices": { "inputUsdPerMillion": 2.5, "outputUsdPerMillion": 15, "cacheReadInputUsdPerMillion": 0.25 },
253
+ "longContext": {
254
+ "thresholdInputTokens": 272000,
255
+ "prices": { "inputUsdPerMillion": 5, "outputUsdPerMillion": 22.5, "cacheReadInputUsdPerMillion": 0.5 }
256
+ }
257
+ },
258
+ {
259
+ "provider": "codex",
260
+ "model": "gpt-5.6-luna",
261
+ "effectiveFrom": "2026-08-01T00:00:00.000Z",
262
+ "effectiveTo": null,
263
+ "prices": { "inputUsdPerMillion": 1, "outputUsdPerMillion": 6, "cacheReadInputUsdPerMillion": 0.1 },
264
+ "longContext": {
265
+ "thresholdInputTokens": 272000,
266
+ "prices": { "inputUsdPerMillion": 2, "outputUsdPerMillion": 9, "cacheReadInputUsdPerMillion": 0.2 }
267
+ }
268
+ }
269
+ ]
270
+ }
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.API_PRICING_PAGE_PATH = exports.API_PRICING_PAGE_FILE = void 0;
4
+ exports.renderCurrentApiPricingTable = renderCurrentApiPricingTable;
5
+ exports.buildApiPricingPage = buildApiPricingPage;
6
+ const api_equivalent_cost_1 = require("./api-equivalent-cost");
7
+ exports.API_PRICING_PAGE_FILE = "pricing.html";
8
+ exports.API_PRICING_PAGE_PATH = `/${exports.API_PRICING_PAGE_FILE}`;
9
+ function escapeHtml(value) {
10
+ return value
11
+ .replaceAll("&", "&")
12
+ .replaceAll("<", "&lt;")
13
+ .replaceAll(">", "&gt;")
14
+ .replaceAll('"', "&quot;")
15
+ .replaceAll("'", "&#39;");
16
+ }
17
+ function formatPrice(value) {
18
+ return value === undefined ? "--" : `$${value.toLocaleString("en-US", { maximumFractionDigits: 6 })}`;
19
+ }
20
+ function renderPriceRow(entry, tier, prices) {
21
+ return `
22
+ <tr>
23
+ <td>${entry.provider === "claude" ? "Claude" : "Codex"}</td>
24
+ <td><code>${escapeHtml(entry.model)}</code></td>
25
+ <td>${escapeHtml(tier)}</td>
26
+ <td>${escapeHtml(entry.effectiveFrom.slice(0, 10))}</td>
27
+ <td>${formatPrice(prices.inputUsdPerMillion)}</td>
28
+ <td>${formatPrice(prices.outputUsdPerMillion)}</td>
29
+ <td>${formatPrice(prices.cacheReadInputUsdPerMillion)}</td>
30
+ <td>${formatPrice(prices.cacheWrite5mInputUsdPerMillion)}</td>
31
+ <td>${formatPrice(prices.cacheWrite1hInputUsdPerMillion)}</td>
32
+ </tr>`;
33
+ }
34
+ function providerRank(provider) {
35
+ return provider === "codex" ? 0 : 1;
36
+ }
37
+ function compareModelVersionsDescending(left, right) {
38
+ const leftParts = left.match(/\d+(?:\.\d+)*/)?.[0].split(".").map(Number) ?? [];
39
+ const rightParts = right.match(/\d+(?:\.\d+)*/)?.[0].split(".").map(Number) ?? [];
40
+ const length = Math.max(leftParts.length, rightParts.length);
41
+ for (let index = 0; index < length; index += 1) {
42
+ const difference = (rightParts[index] ?? 0) - (leftParts[index] ?? 0);
43
+ if (difference !== 0) {
44
+ return difference;
45
+ }
46
+ }
47
+ return 0;
48
+ }
49
+ function comparePricingEntries(left, right) {
50
+ const providerDifference = providerRank(left.provider) - providerRank(right.provider);
51
+ if (providerDifference !== 0) {
52
+ return providerDifference;
53
+ }
54
+ return left.provider === "codex"
55
+ ? compareModelVersionsDescending(left.model, right.model)
56
+ : left.model.localeCompare(right.model);
57
+ }
58
+ /** 按页面生成时间渲染有效区间内的普通与长上下文价格。 */
59
+ function renderCurrentApiPricingTable(catalog = api_equivalent_cost_1.API_PRICING_CATALOG, generatedAt = new Date()) {
60
+ const generatedAtMs = generatedAt.getTime();
61
+ const entries = catalog.entries
62
+ .filter((entry) => {
63
+ const effectiveFromMs = new Date(entry.effectiveFrom).getTime();
64
+ const effectiveToMs = entry.effectiveTo === null ? Number.POSITIVE_INFINITY : new Date(entry.effectiveTo).getTime();
65
+ return generatedAtMs >= effectiveFromMs && generatedAtMs < effectiveToMs;
66
+ })
67
+ .sort(comparePricingEntries);
68
+ const rows = entries.flatMap((entry) => {
69
+ const itemRows = [renderPriceRow(entry, "普通", entry.prices)];
70
+ if (entry.longContext) {
71
+ itemRows.push(renderPriceRow(entry, `长上下文(输入类 token > ${entry.longContext.thresholdInputTokens.toLocaleString("en-US")})`, entry.longContext.prices));
72
+ }
73
+ return itemRows;
74
+ }).join("");
75
+ return `
76
+ <section class="panel table-panel">
77
+ <div class="panel-header">
78
+ <p class="muted">目录 ${escapeHtml(catalog.catalogVersion)} · USD / 百万 token · 标准同步 API</p>
79
+ </div>
80
+ <div class="table-wrap">
81
+ <table class="pricing-table">
82
+ <thead>
83
+ <tr>
84
+ <th>来源</th>
85
+ <th>模型</th>
86
+ <th>计价档位</th>
87
+ <th>生效日期</th>
88
+ <th>输入</th>
89
+ <th>输出</th>
90
+ <th>缓存读取</th>
91
+ <th>5 分钟缓存写入</th>
92
+ <th>1 小时缓存写入</th>
93
+ </tr>
94
+ </thead>
95
+ <tbody>${rows}</tbody>
96
+ </table>
97
+ </div>
98
+ </section>`;
99
+ }
100
+ /** 生成可独立打开的当前 API 价格页面。 */
101
+ function buildApiPricingPage(generatedAt = new Date(), catalog = api_equivalent_cost_1.API_PRICING_CATALOG) {
102
+ return `<!doctype html>
103
+ <html lang="zh-CN">
104
+ <head>
105
+ <meta charset="utf-8" />
106
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
107
+ <title>ccus 当前模型价格</title>
108
+ <style>
109
+ :root {
110
+ --bg: #0a0d12;
111
+ --panel: rgba(16, 21, 31, 0.84);
112
+ --panel-border: rgba(120, 141, 173, 0.18);
113
+ --text: #ecf3ff;
114
+ --muted: #91a0b8;
115
+ --accent: #5eead4;
116
+ --shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
117
+ }
118
+ * { box-sizing: border-box; }
119
+ body {
120
+ margin: 0;
121
+ min-height: 100vh;
122
+ font-family: Georgia, "Times New Roman", serif;
123
+ color: var(--text);
124
+ background:
125
+ radial-gradient(circle at top left, rgba(34, 197, 94, 0.18), transparent 30%),
126
+ radial-gradient(circle at top right, rgba(94, 234, 212, 0.16), transparent 28%),
127
+ linear-gradient(160deg, #06080c 0%, #0a0d12 48%, #101520 100%);
128
+ }
129
+ .shell { max-width: 1240px; margin: 0 auto; padding: 40px 24px 64px; }
130
+ .hero { display: grid; gap: 12px; padding: 28px 0 18px; }
131
+ .eyebrow { margin: 0 0 8px; color: var(--accent); text-transform: uppercase; letter-spacing: 0.14em; font-size: 12px; }
132
+ h1, p { margin: 0; }
133
+ h1 { font-size: clamp(36px, 5vw, 60px); line-height: 0.95; font-weight: 600; }
134
+ .muted { color: var(--muted); font-size: 14px; }
135
+ .panel { background: var(--panel); border: 1px solid var(--panel-border); border-radius: 24px; box-shadow: var(--shadow); }
136
+ .table-panel { margin-top: 22px; }
137
+ .panel-header { padding: 24px 24px 0; }
138
+ .table-wrap { overflow: auto; padding: 16px 20px 22px; }
139
+ table { width: 100%; min-width: 1080px; border-collapse: collapse; }
140
+ th, td { text-align: left; padding: 12px 10px; border-bottom: 1px solid rgba(145, 160, 184, 0.12); vertical-align: top; }
141
+ th { color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: 0.08em; font-weight: 500; }
142
+ td { font-size: 14px; }
143
+ code { font-family: "Cascadia Code", "SFMono-Regular", Consolas, monospace; font-size: 12px; }
144
+ @media (max-width: 720px) {
145
+ .shell { padding-inline: 16px; }
146
+ }
147
+ </style>
148
+ </head>
149
+ <body>
150
+ <main class="shell">
151
+ <section class="hero">
152
+ <div>
153
+ <p class="eyebrow">Current API Pricing</p>
154
+ <h1>当前模型价格</h1>
155
+ </div>
156
+ <p class="muted">标准同步 API 参考价格,不是订阅或实际账单。</p>
157
+ </section>
158
+ ${renderCurrentApiPricingTable(catalog, generatedAt)}
159
+ </main>
160
+ </body>
161
+ </html>`;
162
+ }
163
+ //# sourceMappingURL=api-pricing-table.js.map
@@ -8,6 +8,7 @@ exports.findActiveSessionFiles = findActiveSessionFiles;
8
8
  exports.summarizeClaudeProjectUsageByDay = summarizeClaudeProjectUsageByDay;
9
9
  const promises_1 = __importDefault(require("node:fs/promises"));
10
10
  const node_path_1 = __importDefault(require("node:path"));
11
+ const api_equivalent_cost_1 = require("./api-equivalent-cost");
11
12
  const paths_1 = require("./paths");
12
13
  function isRecord(value) {
13
14
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -18,6 +19,39 @@ function getNumber(value) {
18
19
  function getString(value) {
19
20
  return typeof value === "string" && value.length > 0 ? value : null;
20
21
  }
22
+ function hasOwn(record, key) {
23
+ return Object.prototype.hasOwnProperty.call(record, key);
24
+ }
25
+ function summarizeAssistantUsage(message, timestamp) {
26
+ const usage = message.usage;
27
+ const cacheCreation = isRecord(usage.cache_creation) ? usage.cache_creation : null;
28
+ const hasFiveMinuteDetail = cacheCreation !== null && hasOwn(cacheCreation, "ephemeral_5m_input_tokens");
29
+ const hasOneHourDetail = cacheCreation !== null && hasOwn(cacheCreation, "ephemeral_1h_input_tokens");
30
+ const cacheWrite5mInputTokens = hasFiveMinuteDetail || hasOneHourDetail
31
+ ? getNumber(cacheCreation?.ephemeral_5m_input_tokens)
32
+ : getNumber(usage.cache_creation_input_tokens);
33
+ const cacheWrite1hInputTokens = hasFiveMinuteDetail || hasOneHourDetail
34
+ ? getNumber(cacheCreation?.ephemeral_1h_input_tokens)
35
+ : 0;
36
+ const inputTokens = getNumber(usage.input_tokens);
37
+ const outputTokens = getNumber(usage.output_tokens);
38
+ const cacheReadInputTokens = getNumber(usage.cache_read_input_tokens);
39
+ return {
40
+ inputTokens,
41
+ outputTokens,
42
+ cacheReadInputTokens,
43
+ apiEquivalentCost: (0, api_equivalent_cost_1.priceApiRequest)({
44
+ provider: "claude",
45
+ timestamp,
46
+ model: getString(message.model),
47
+ inputTokens,
48
+ outputTokens,
49
+ cacheReadInputTokens,
50
+ cacheWrite5mInputTokens,
51
+ cacheWrite1hInputTokens,
52
+ }),
53
+ };
54
+ }
21
55
  async function collectProjectJsonlFiles(directoryPath) {
22
56
  try {
23
57
  const entries = await promises_1.default.readdir(directoryPath, { withFileTypes: true });
@@ -87,11 +121,13 @@ function summarizeProjectTranscript(content, start, end) {
87
121
  inputTokens: 0,
88
122
  outputTokens: 0,
89
123
  cacheReadInputTokens: 0,
124
+ apiEquivalentCost: (0, api_equivalent_cost_1.emptyApiEquivalentCost)(),
90
125
  };
91
126
  for (const line of lines) {
92
127
  try {
93
128
  const record = JSON.parse(line);
94
- if (!isRecord(record) || !timestampInRange(getString(record.timestamp), start, end)) {
129
+ const timestamp = isRecord(record) ? getString(record.timestamp) : null;
130
+ if (!isRecord(record) || !timestampInRange(timestamp, start, end)) {
95
131
  continue;
96
132
  }
97
133
  if (isHumanUserMessage(record)) {
@@ -100,10 +136,12 @@ function summarizeProjectTranscript(content, start, end) {
100
136
  if (record.type !== "assistant" || !isRecord(record.message) || !isRecord(record.message.usage)) {
101
137
  continue;
102
138
  }
139
+ const assistantUsage = summarizeAssistantUsage(record.message, timestamp);
103
140
  summary.apiRequestCount += 1;
104
- summary.inputTokens += getNumber(record.message.usage.input_tokens);
105
- summary.outputTokens += getNumber(record.message.usage.output_tokens);
106
- summary.cacheReadInputTokens += getNumber(record.message.usage.cache_read_input_tokens);
141
+ summary.inputTokens += assistantUsage.inputTokens;
142
+ summary.outputTokens += assistantUsage.outputTokens;
143
+ summary.cacheReadInputTokens += assistantUsage.cacheReadInputTokens;
144
+ summary.apiEquivalentCost = (0, api_equivalent_cost_1.mergeApiEquivalentCosts)([summary.apiEquivalentCost, assistantUsage.apiEquivalentCost]);
107
145
  }
108
146
  catch {
109
147
  continue;
@@ -112,7 +150,7 @@ function summarizeProjectTranscript(content, start, end) {
112
150
  return summary;
113
151
  }
114
152
  /**
115
- * 从 Claude 本地 project transcript 中统计本周消息数、请求数和 token 用量。
153
+ * 从 Claude 本地 project transcript 中统计本周消息数、请求数、token 用量和标准 API 等效成本。
116
154
  */
117
155
  async function summarizeClaudeProjectUsage(start, end) {
118
156
  const claudeDataDir = (0, paths_1.getClaudeDataDir)();
@@ -124,6 +162,7 @@ async function summarizeClaudeProjectUsage(start, end) {
124
162
  inputTokens: 0,
125
163
  outputTokens: 0,
126
164
  cacheReadInputTokens: 0,
165
+ apiEquivalentCost: (0, api_equivalent_cost_1.emptyApiEquivalentCost)(),
127
166
  matchedFileCount: files.length,
128
167
  claudeDataDir,
129
168
  };
@@ -136,6 +175,7 @@ async function summarizeClaudeProjectUsage(start, end) {
136
175
  totals.inputTokens += summary.inputTokens;
137
176
  totals.outputTokens += summary.outputTokens;
138
177
  totals.cacheReadInputTokens += summary.cacheReadInputTokens;
178
+ totals.apiEquivalentCost = (0, api_equivalent_cost_1.mergeApiEquivalentCosts)([totals.apiEquivalentCost, summary.apiEquivalentCost]);
139
179
  }
140
180
  catch {
141
181
  continue;
@@ -187,7 +227,7 @@ async function findActiveSessionFiles(start, end) {
187
227
  return result;
188
228
  }
189
229
  /**
190
- * 按天汇总 Claude project transcript 中的消息数、请求数和 token 用量。
230
+ * 按天汇总 Claude project transcript 中的消息数、请求数、token 用量和标准 API 等效成本。
191
231
  */
192
232
  async function summarizeClaudeProjectUsageByDay(start, end) {
193
233
  const claudeDataDir = (0, paths_1.getClaudeDataDir)();
@@ -221,15 +261,18 @@ async function summarizeClaudeProjectUsageByDay(start, end) {
221
261
  inputTokens: 0,
222
262
  outputTokens: 0,
223
263
  cacheReadInputTokens: 0,
264
+ apiEquivalentCost: (0, api_equivalent_cost_1.emptyApiEquivalentCost)(),
224
265
  };
225
266
  if (isHumanUserMessage(record)) {
226
267
  current.userMessageCount += 1;
227
268
  }
228
269
  if (record.type === "assistant" && isRecord(record.message) && isRecord(record.message.usage)) {
270
+ const assistantUsage = summarizeAssistantUsage(record.message, timestamp);
229
271
  current.apiRequestCount += 1;
230
- current.inputTokens += getNumber(record.message.usage.input_tokens);
231
- current.outputTokens += getNumber(record.message.usage.output_tokens);
232
- current.cacheReadInputTokens += getNumber(record.message.usage.cache_read_input_tokens);
272
+ current.inputTokens += assistantUsage.inputTokens;
273
+ current.outputTokens += assistantUsage.outputTokens;
274
+ current.cacheReadInputTokens += assistantUsage.cacheReadInputTokens;
275
+ current.apiEquivalentCost = (0, api_equivalent_cost_1.mergeApiEquivalentCosts)([current.apiEquivalentCost, assistantUsage.apiEquivalentCost]);
233
276
  }
234
277
  daily.set(date, current);
235
278
  }
@@ -17,8 +17,8 @@ const node_path_1 = require("node:path");
17
17
  const debug_1 = require("./debug");
18
18
  const api_mode_1 = require("./api-mode");
19
19
  const paths_1 = require("./paths");
20
- // app-server 子进程参数:read-only + untrusted,Codex 官方推荐的最低权限拉额度姿态。
21
- const CODEX_ARGS = ["-s", "read-only", "-a", "untrusted", "app-server"];
20
+ // app-server 子进程参数:read-only + never,避免新版 Codex 拒绝已移除的 untrusted 审批策略。
21
+ const CODEX_ARGS = ["-s", "read-only", "-a", "never", "app-server"];
22
22
  const DEFAULT_TIMEOUT_MS = 10_000;
23
23
  // notify 每 turn 触发,额度缓存 5 分钟,命中秒回避免阻塞 Codex 主流程。
24
24
  const DEFAULT_TTL_MS = 5 * 60 * 1000;