@roberttlange/agentlens 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +154 -20
- package/dist/browser.js.map +1 -1
- package/dist/main.test.js +138 -1
- package/dist/main.test.js.map +1 -1
- package/node_modules/@agentlens/contracts/dist/index.d.ts +120 -0
- package/node_modules/@agentlens/core/dist/__tests__/config.test.js +67 -2
- package/node_modules/@agentlens/core/dist/__tests__/config.test.js.map +1 -1
- package/node_modules/@agentlens/core/dist/__tests__/index.test.js +590 -2
- package/node_modules/@agentlens/core/dist/__tests__/index.test.js.map +1 -1
- package/node_modules/@agentlens/core/dist/config.js +95 -5
- package/node_modules/@agentlens/core/dist/config.js.map +1 -1
- package/node_modules/@agentlens/core/dist/generatedPricing.d.ts +3 -0
- package/node_modules/@agentlens/core/dist/generatedPricing.js +131 -0
- package/node_modules/@agentlens/core/dist/generatedPricing.js.map +1 -0
- package/node_modules/@agentlens/core/dist/metrics.d.ts +13 -0
- package/node_modules/@agentlens/core/dist/metrics.js +227 -54
- package/node_modules/@agentlens/core/dist/metrics.js.map +1 -1
- package/node_modules/@agentlens/core/dist/pricing.d.ts +15 -0
- package/node_modules/@agentlens/core/dist/pricing.js +133 -0
- package/node_modules/@agentlens/core/dist/pricing.js.map +1 -0
- package/node_modules/@agentlens/core/dist/pricing.test.d.ts +1 -0
- package/node_modules/@agentlens/core/dist/pricing.test.js +109 -0
- package/node_modules/@agentlens/core/dist/pricing.test.js.map +1 -0
- package/node_modules/@agentlens/core/dist/sourceProfiles.js +7 -67
- package/node_modules/@agentlens/core/dist/sourceProfiles.js.map +1 -1
- package/node_modules/@agentlens/core/dist/traceIndex.d.ts +34 -1
- package/node_modules/@agentlens/core/dist/traceIndex.js +374 -15
- package/node_modules/@agentlens/core/dist/traceIndex.js.map +1 -1
- package/node_modules/@agentlens/server/dist/activity-cache.d.ts +32 -0
- package/node_modules/@agentlens/server/dist/activity-cache.js +63 -0
- package/node_modules/@agentlens/server/dist/activity-cache.js.map +1 -0
- package/node_modules/@agentlens/server/dist/activity-cache.test.d.ts +1 -0
- package/node_modules/@agentlens/server/dist/activity-cache.test.js +170 -0
- package/node_modules/@agentlens/server/dist/activity-cache.test.js.map +1 -0
- package/node_modules/@agentlens/server/dist/activity.d.ts +31 -1
- package/node_modules/@agentlens/server/dist/activity.js +532 -34
- package/node_modules/@agentlens/server/dist/activity.js.map +1 -1
- package/node_modules/@agentlens/server/dist/app.d.ts +4 -2
- package/node_modules/@agentlens/server/dist/app.js +248 -5
- package/node_modules/@agentlens/server/dist/app.js.map +1 -1
- package/node_modules/@agentlens/server/dist/app.test.js +670 -9
- package/node_modules/@agentlens/server/dist/app.test.js.map +1 -1
- package/node_modules/@agentlens/server/dist/web/assets/index-CTFOBaBt.css +1 -0
- package/node_modules/@agentlens/server/dist/web/assets/index-CVf00w06.js +52 -0
- package/node_modules/@agentlens/server/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/node_modules/@agentlens/server/dist/web/assets/index-Ci8okH8M.js +0 -52
- package/node_modules/@agentlens/server/dist/web/assets/index-Cj3kmsFf.css +0 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
// Generated by scripts/sync-pricing.mjs on 2026-03-08T11:05:25.212Z.
|
|
2
|
+
// Sources: https://platform.claude.com/docs/en/about-claude/pricing, https://platform.claude.com/docs/en/about-claude/models/overview, https://developers.openai.com/api/docs/pricing, https://developers.openai.com/api/docs/models/gpt-5.2, https://developers.openai.com/api/docs/models/gpt-5.2-codex, https://developers.openai.com/api/docs/models/gpt-5.4, https://developers.openai.com/api/docs/models/gpt-5.3-codex
|
|
3
|
+
export const DEFAULT_PRICING_MODEL_RATES = [
|
|
4
|
+
{
|
|
5
|
+
model: "gpt-5.2-codex",
|
|
6
|
+
inputPer1MUsd: 1.75,
|
|
7
|
+
outputPer1MUsd: 14,
|
|
8
|
+
cachedReadPer1MUsd: 0.175,
|
|
9
|
+
cachedCreatePer1MUsd: 0,
|
|
10
|
+
reasoningOutputPer1MUsd: 0,
|
|
11
|
+
contextWindowTokens: 400000,
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
model: "gpt-5.3-codex",
|
|
15
|
+
inputPer1MUsd: 1.75,
|
|
16
|
+
outputPer1MUsd: 14,
|
|
17
|
+
cachedReadPer1MUsd: 0.175,
|
|
18
|
+
cachedCreatePer1MUsd: 0,
|
|
19
|
+
reasoningOutputPer1MUsd: 0,
|
|
20
|
+
contextWindowTokens: 400000,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
model: "gpt-5.2",
|
|
24
|
+
inputPer1MUsd: 0.875,
|
|
25
|
+
outputPer1MUsd: 7,
|
|
26
|
+
cachedReadPer1MUsd: 0.0875,
|
|
27
|
+
cachedCreatePer1MUsd: 0,
|
|
28
|
+
reasoningOutputPer1MUsd: 0,
|
|
29
|
+
contextWindowTokens: 400000,
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
model: "gpt-5.4",
|
|
33
|
+
inputPer1MUsd: 1.25,
|
|
34
|
+
outputPer1MUsd: 7.5,
|
|
35
|
+
cachedReadPer1MUsd: 0.13,
|
|
36
|
+
cachedCreatePer1MUsd: 0,
|
|
37
|
+
reasoningOutputPer1MUsd: 0,
|
|
38
|
+
longContextThresholdTokens: 272000,
|
|
39
|
+
longContextInputPer1MUsd: 2.5,
|
|
40
|
+
longContextOutputPer1MUsd: 11.25,
|
|
41
|
+
contextWindowTokens: 1050000,
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
model: "claude-opus-4.6",
|
|
45
|
+
inputPer1MUsd: 5,
|
|
46
|
+
outputPer1MUsd: 25,
|
|
47
|
+
cachedReadPer1MUsd: 0.5,
|
|
48
|
+
cachedCreatePer1MUsd: 6.25,
|
|
49
|
+
cachedCreate5mPer1MUsd: 6.25,
|
|
50
|
+
cachedCreate1hPer1MUsd: 10,
|
|
51
|
+
reasoningOutputPer1MUsd: 0,
|
|
52
|
+
longContextThresholdTokens: 200000,
|
|
53
|
+
longContextInputPer1MUsd: 10,
|
|
54
|
+
longContextOutputPer1MUsd: 37.5,
|
|
55
|
+
longContextCachedReadPer1MUsd: 1,
|
|
56
|
+
longContextCachedCreatePer1MUsd: 12.5,
|
|
57
|
+
longContextCachedCreate5mPer1MUsd: 12.5,
|
|
58
|
+
longContextCachedCreate1hPer1MUsd: 20,
|
|
59
|
+
contextWindowTokens: 200000,
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
model: "claude-opus-4-5-20251101",
|
|
63
|
+
inputPer1MUsd: 5,
|
|
64
|
+
outputPer1MUsd: 25,
|
|
65
|
+
cachedReadPer1MUsd: 0.5,
|
|
66
|
+
cachedCreatePer1MUsd: 6.25,
|
|
67
|
+
cachedCreate5mPer1MUsd: 6.25,
|
|
68
|
+
cachedCreate1hPer1MUsd: 10,
|
|
69
|
+
reasoningOutputPer1MUsd: 0,
|
|
70
|
+
contextWindowTokens: 200000,
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
model: "claude-sonnet-4.6",
|
|
74
|
+
inputPer1MUsd: 3,
|
|
75
|
+
outputPer1MUsd: 15,
|
|
76
|
+
cachedReadPer1MUsd: 0.3,
|
|
77
|
+
cachedCreatePer1MUsd: 3.75,
|
|
78
|
+
cachedCreate5mPer1MUsd: 3.75,
|
|
79
|
+
cachedCreate1hPer1MUsd: 6,
|
|
80
|
+
reasoningOutputPer1MUsd: 0,
|
|
81
|
+
longContextThresholdTokens: 200000,
|
|
82
|
+
longContextInputPer1MUsd: 6,
|
|
83
|
+
longContextOutputPer1MUsd: 22.5,
|
|
84
|
+
longContextCachedReadPer1MUsd: 0.6,
|
|
85
|
+
longContextCachedCreatePer1MUsd: 7.5,
|
|
86
|
+
longContextCachedCreate5mPer1MUsd: 7.5,
|
|
87
|
+
longContextCachedCreate1hPer1MUsd: 12,
|
|
88
|
+
contextWindowTokens: 200000,
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
model: "claude-sonnet-4-5-20250929",
|
|
92
|
+
inputPer1MUsd: 3,
|
|
93
|
+
outputPer1MUsd: 15,
|
|
94
|
+
cachedReadPer1MUsd: 0.3,
|
|
95
|
+
cachedCreatePer1MUsd: 3.75,
|
|
96
|
+
cachedCreate5mPer1MUsd: 3.75,
|
|
97
|
+
cachedCreate1hPer1MUsd: 6,
|
|
98
|
+
reasoningOutputPer1MUsd: 0,
|
|
99
|
+
longContextThresholdTokens: 200000,
|
|
100
|
+
longContextInputPer1MUsd: 6,
|
|
101
|
+
longContextOutputPer1MUsd: 22.5,
|
|
102
|
+
longContextCachedReadPer1MUsd: 0.6,
|
|
103
|
+
longContextCachedCreatePer1MUsd: 7.5,
|
|
104
|
+
longContextCachedCreate5mPer1MUsd: 7.5,
|
|
105
|
+
longContextCachedCreate1hPer1MUsd: 12,
|
|
106
|
+
contextWindowTokens: 200000,
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
model: "claude-haiku-4.5",
|
|
110
|
+
inputPer1MUsd: 1,
|
|
111
|
+
outputPer1MUsd: 5,
|
|
112
|
+
cachedReadPer1MUsd: 0.1,
|
|
113
|
+
cachedCreatePer1MUsd: 1.25,
|
|
114
|
+
cachedCreate5mPer1MUsd: 1.25,
|
|
115
|
+
cachedCreate1hPer1MUsd: 2,
|
|
116
|
+
reasoningOutputPer1MUsd: 0,
|
|
117
|
+
contextWindowTokens: 200000,
|
|
118
|
+
},
|
|
119
|
+
];
|
|
120
|
+
export const DEFAULT_CONTEXT_WINDOWS = [
|
|
121
|
+
{ model: "gpt-5.2-codex", contextWindowTokens: 400000 },
|
|
122
|
+
{ model: "gpt-5.3-codex", contextWindowTokens: 400000 },
|
|
123
|
+
{ model: "gpt-5.2", contextWindowTokens: 400000 },
|
|
124
|
+
{ model: "gpt-5.4", contextWindowTokens: 1050000 },
|
|
125
|
+
{ model: "claude-opus-4.6", contextWindowTokens: 200000 },
|
|
126
|
+
{ model: "claude-opus-4-5-20251101", contextWindowTokens: 200000 },
|
|
127
|
+
{ model: "claude-sonnet-4.6", contextWindowTokens: 200000 },
|
|
128
|
+
{ model: "claude-sonnet-4-5-20250929", contextWindowTokens: 200000 },
|
|
129
|
+
{ model: "claude-haiku-4.5", contextWindowTokens: 200000 },
|
|
130
|
+
];
|
|
131
|
+
//# sourceMappingURL=generatedPricing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generatedPricing.js","sourceRoot":"","sources":["../src/generatedPricing.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,23 @@
|
|
|
1
1
|
import type { AgentKind, AppConfig, ModelTokenShare, NormalizedEvent, TokenTotals } from "@agentlens/contracts";
|
|
2
|
+
export interface SessionUsagePoint {
|
|
3
|
+
timestampMs: number;
|
|
4
|
+
agent: AgentKind;
|
|
5
|
+
model: string;
|
|
6
|
+
inputTokens: number;
|
|
7
|
+
cachedReadTokens: number;
|
|
8
|
+
cachedCreateTokens: number;
|
|
9
|
+
outputTokens: number;
|
|
10
|
+
reasoningOutputTokens: number;
|
|
11
|
+
totalTokens: number;
|
|
12
|
+
costUsd: number;
|
|
13
|
+
}
|
|
2
14
|
interface SessionMetrics {
|
|
3
15
|
tokenTotals: TokenTotals;
|
|
4
16
|
modelTokenSharesTop: ModelTokenShare[];
|
|
5
17
|
modelTokenSharesEstimated: boolean;
|
|
6
18
|
contextWindowPct: number | null;
|
|
7
19
|
costEstimateUsd: number | null;
|
|
20
|
+
usagePoints: SessionUsagePoint[];
|
|
8
21
|
}
|
|
9
22
|
export declare function deriveSessionMetrics(events: NormalizedEvent[], agent: AgentKind, config: AppConfig): SessionMetrics;
|
|
10
23
|
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { estimateUsageCost, resolveContextWindowTokens } from "./pricing.js";
|
|
1
2
|
import { asRecord, asString } from "./utils.js";
|
|
2
3
|
function toNumber(value) {
|
|
3
4
|
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
@@ -59,6 +60,17 @@ function tokenTotalsFromUsageRecord(usageRecord) {
|
|
|
59
60
|
totals.totalTokens = toNumber(usageRecord.total_tokens);
|
|
60
61
|
return finalizeTokenTotals(totals);
|
|
61
62
|
}
|
|
63
|
+
function claudeCacheCreationBreakdown(usageRecord) {
|
|
64
|
+
const cacheCreation = asRecord(usageRecord.cache_creation);
|
|
65
|
+
const cachedCreate5mTokens = toNumber(cacheCreation.ephemeral_5m_input_tokens);
|
|
66
|
+
const cachedCreate1hTokens = toNumber(cacheCreation.ephemeral_1h_input_tokens);
|
|
67
|
+
const cachedCreateTokens = Math.max(toNumber(usageRecord.cache_creation_input_tokens), cachedCreate5mTokens + cachedCreate1hTokens);
|
|
68
|
+
return {
|
|
69
|
+
cachedCreateTokens,
|
|
70
|
+
cachedCreate5mTokens,
|
|
71
|
+
cachedCreate1hTokens,
|
|
72
|
+
};
|
|
73
|
+
}
|
|
62
74
|
function tokenTotalsFromCodexUsageRecord(record) {
|
|
63
75
|
const totals = emptyTokenTotals();
|
|
64
76
|
totals.inputTokens = toNumber(record.input_tokens);
|
|
@@ -69,6 +81,26 @@ function tokenTotalsFromCodexUsageRecord(record) {
|
|
|
69
81
|
totals.totalTokens = toNumber(record.total_tokens);
|
|
70
82
|
return finalizeTokenTotals(totals);
|
|
71
83
|
}
|
|
84
|
+
function codexInputIncludesCached(record) {
|
|
85
|
+
const inputTokens = toNumber(record.input_tokens);
|
|
86
|
+
const cachedReadTokens = toNumber(record.cached_input_tokens);
|
|
87
|
+
const outputTokens = toNumber(record.output_tokens);
|
|
88
|
+
const reasoningOutputTokens = toNumber(record.reasoning_output_tokens);
|
|
89
|
+
const totalTokens = toNumber(record.total_tokens);
|
|
90
|
+
if (cachedReadTokens <= 0 || totalTokens <= 0)
|
|
91
|
+
return false;
|
|
92
|
+
return inputTokens + cachedReadTokens + outputTokens + reasoningOutputTokens > totalTokens;
|
|
93
|
+
}
|
|
94
|
+
function codexPromptTokens(record) {
|
|
95
|
+
const inputTokens = toNumber(record.input_tokens);
|
|
96
|
+
const cachedReadTokens = toNumber(record.cached_input_tokens);
|
|
97
|
+
return codexInputIncludesCached(record) ? inputTokens : inputTokens + cachedReadTokens;
|
|
98
|
+
}
|
|
99
|
+
function codexBillableInputTokens(record) {
|
|
100
|
+
const inputTokens = toNumber(record.input_tokens);
|
|
101
|
+
const cachedReadTokens = toNumber(record.cached_input_tokens);
|
|
102
|
+
return codexInputIncludesCached(record) ? Math.max(0, inputTokens - cachedReadTokens) : inputTokens;
|
|
103
|
+
}
|
|
72
104
|
function tokenTotalsFromOpenCodeTokensRecord(record) {
|
|
73
105
|
const cache = asRecord(record.cache);
|
|
74
106
|
const totals = emptyTokenTotals();
|
|
@@ -101,20 +133,7 @@ function tokenTotalsFromPiUsageRecord(record) {
|
|
|
101
133
|
return finalizeTokenTotals(totals);
|
|
102
134
|
}
|
|
103
135
|
function contextWindowResolver(config) {
|
|
104
|
-
|
|
105
|
-
for (const entry of config.models.contextWindows) {
|
|
106
|
-
const model = entry.model.trim();
|
|
107
|
-
if (!model || !Number.isFinite(entry.contextWindowTokens) || entry.contextWindowTokens <= 0)
|
|
108
|
-
continue;
|
|
109
|
-
byModel.set(model, entry.contextWindowTokens);
|
|
110
|
-
}
|
|
111
|
-
const fallback = config.models.defaultContextWindowTokens;
|
|
112
|
-
return (model) => {
|
|
113
|
-
const direct = byModel.get(model);
|
|
114
|
-
if (direct)
|
|
115
|
-
return direct;
|
|
116
|
-
return fallback > 0 ? fallback : 0;
|
|
117
|
-
};
|
|
136
|
+
return (model) => resolveContextWindowTokens(model, config);
|
|
118
137
|
}
|
|
119
138
|
function buildTopModelShares(modelTokenTotals, topN) {
|
|
120
139
|
const ranked = [...modelTokenTotals.entries()]
|
|
@@ -132,20 +151,20 @@ function buildTopModelShares(modelTokenTotals, topN) {
|
|
|
132
151
|
function estimateCost(perModel, costConfig) {
|
|
133
152
|
if (!costConfig.enabled)
|
|
134
153
|
return null;
|
|
135
|
-
const rateByModel = new Map(costConfig.modelRates.map((rate) => [rate.model, rate]));
|
|
136
154
|
let total = 0;
|
|
137
155
|
for (const [model, tokens] of perModel) {
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
156
|
+
const cost = estimateUsageCost({
|
|
157
|
+
model,
|
|
158
|
+
promptTokens: tokens.inputTokens + tokens.cachedReadTokens + tokens.cachedCreateTokens,
|
|
159
|
+
inputTokens: tokens.inputTokens,
|
|
160
|
+
cachedReadTokens: tokens.cachedReadTokens,
|
|
161
|
+
cachedCreateTokens: tokens.cachedCreateTokens,
|
|
162
|
+
outputTokens: tokens.outputTokens,
|
|
163
|
+
reasoningOutputTokens: tokens.reasoningOutputTokens,
|
|
164
|
+
}, costConfig);
|
|
165
|
+
if (cost === null)
|
|
166
|
+
return null;
|
|
167
|
+
total += cost;
|
|
149
168
|
}
|
|
150
169
|
return Number(total.toFixed(6));
|
|
151
170
|
}
|
|
@@ -158,11 +177,25 @@ function buildClaudeUsageDedupKey(raw, message) {
|
|
|
158
177
|
return `message:${messageId}`;
|
|
159
178
|
return "";
|
|
160
179
|
}
|
|
161
|
-
function
|
|
180
|
+
function finalizeCostTotal(costKnown, total) {
|
|
181
|
+
if (!costKnown)
|
|
182
|
+
return null;
|
|
183
|
+
return Number(total.toFixed(6));
|
|
184
|
+
}
|
|
185
|
+
function usagePointFromTotals(event, agent, model, totals, costUsd) {
|
|
186
|
+
if (event.timestampMs === null || event.timestampMs <= 0)
|
|
187
|
+
return null;
|
|
162
188
|
return {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
189
|
+
timestampMs: event.timestampMs,
|
|
190
|
+
agent,
|
|
191
|
+
model,
|
|
192
|
+
inputTokens: totals.inputTokens,
|
|
193
|
+
cachedReadTokens: totals.cachedReadTokens,
|
|
194
|
+
cachedCreateTokens: totals.cachedCreateTokens,
|
|
195
|
+
outputTokens: totals.outputTokens,
|
|
196
|
+
reasoningOutputTokens: totals.reasoningOutputTokens,
|
|
197
|
+
totalTokens: totals.totalTokens,
|
|
198
|
+
costUsd: costUsd === null ? 0 : Number(costUsd.toFixed(6)),
|
|
166
199
|
};
|
|
167
200
|
}
|
|
168
201
|
function deriveClaudeMetrics(events, config) {
|
|
@@ -170,8 +203,11 @@ function deriveClaudeMetrics(events, config) {
|
|
|
170
203
|
const totals = emptyTokenTotals();
|
|
171
204
|
const modelBreakdown = new Map();
|
|
172
205
|
let maxContextPct = null;
|
|
206
|
+
let costTotal = 0;
|
|
207
|
+
let costKnown = config.cost.enabled;
|
|
173
208
|
const seenRows = new Set();
|
|
174
209
|
const seenUsageKeys = new Set();
|
|
210
|
+
const usagePoints = [];
|
|
175
211
|
for (const event of events) {
|
|
176
212
|
const raw = event.raw;
|
|
177
213
|
if (seenRows.has(raw))
|
|
@@ -191,6 +227,7 @@ function deriveClaudeMetrics(events, config) {
|
|
|
191
227
|
}
|
|
192
228
|
const model = asString(message.model) || "<unknown>";
|
|
193
229
|
const usageTotals = tokenTotalsFromUsageRecord(usage);
|
|
230
|
+
const cacheCreation = claudeCacheCreationBreakdown(usage);
|
|
194
231
|
addTokenTotals(totals, usageTotals);
|
|
195
232
|
const existing = modelBreakdown.get(model) ?? emptyTokenTotals();
|
|
196
233
|
addTokenTotals(existing, usageTotals);
|
|
@@ -201,6 +238,26 @@ function deriveClaudeMetrics(events, config) {
|
|
|
201
238
|
const pct = (promptTokens / window) * 100;
|
|
202
239
|
maxContextPct = maxContextPct === null ? pct : Math.max(maxContextPct, pct);
|
|
203
240
|
}
|
|
241
|
+
const cost = estimateUsageCost({
|
|
242
|
+
model,
|
|
243
|
+
promptTokens,
|
|
244
|
+
inputTokens: usageTotals.inputTokens,
|
|
245
|
+
cachedReadTokens: usageTotals.cachedReadTokens,
|
|
246
|
+
cachedCreateTokens: cacheCreation.cachedCreateTokens,
|
|
247
|
+
cachedCreate5mTokens: cacheCreation.cachedCreate5mTokens,
|
|
248
|
+
cachedCreate1hTokens: cacheCreation.cachedCreate1hTokens,
|
|
249
|
+
outputTokens: usageTotals.outputTokens,
|
|
250
|
+
reasoningOutputTokens: usageTotals.reasoningOutputTokens,
|
|
251
|
+
}, config.cost);
|
|
252
|
+
if (cost === null) {
|
|
253
|
+
costKnown = false;
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
costTotal += cost;
|
|
257
|
+
}
|
|
258
|
+
const usagePoint = usagePointFromTotals(event, "claude", model, usageTotals, cost);
|
|
259
|
+
if (usagePoint)
|
|
260
|
+
usagePoints.push(usagePoint);
|
|
204
261
|
}
|
|
205
262
|
for (const [model, modelTotals] of modelBreakdown) {
|
|
206
263
|
modelBreakdown.set(model, finalizeTokenTotals(modelTotals));
|
|
@@ -210,7 +267,8 @@ function deriveClaudeMetrics(events, config) {
|
|
|
210
267
|
modelTokenSharesTop: buildTopModelShares(new Map([...modelBreakdown.entries()].map(([model, modelTotals]) => [model, modelTotals.totalTokens])), config.traceInspector.topModelCount),
|
|
211
268
|
modelTokenSharesEstimated: false,
|
|
212
269
|
contextWindowPct: maxContextPct,
|
|
213
|
-
costEstimateUsd:
|
|
270
|
+
costEstimateUsd: finalizeCostTotal(costKnown, costTotal),
|
|
271
|
+
usagePoints,
|
|
214
272
|
};
|
|
215
273
|
}
|
|
216
274
|
function deriveCodexMetrics(events, config) {
|
|
@@ -221,14 +279,17 @@ function deriveCodexMetrics(events, config) {
|
|
|
221
279
|
if (seenRows.has(event.raw))
|
|
222
280
|
continue;
|
|
223
281
|
seenRows.add(event.raw);
|
|
224
|
-
rows.push(event.raw);
|
|
282
|
+
rows.push({ raw: event.raw, event });
|
|
225
283
|
}
|
|
226
284
|
let currentModel = "";
|
|
227
285
|
let latestTotals = emptyTokenTotals();
|
|
228
286
|
let prevTotalTokens = null;
|
|
229
287
|
let maxContextPct = null;
|
|
288
|
+
let costTotal = 0;
|
|
289
|
+
let costKnown = config.cost.enabled;
|
|
230
290
|
const modelTotalDeltas = new Map();
|
|
231
|
-
|
|
291
|
+
const usagePoints = [];
|
|
292
|
+
for (const { raw: row, event } of rows) {
|
|
232
293
|
const rowType = asString(row.type).toLowerCase();
|
|
233
294
|
if (rowType === "turn_context") {
|
|
234
295
|
const payload = asRecord(row.payload);
|
|
@@ -254,37 +315,50 @@ function deriveCodexMetrics(events, config) {
|
|
|
254
315
|
prevTotalTokens = latestTotals.totalTokens;
|
|
255
316
|
const windowFromEvent = toNumber(info.model_context_window);
|
|
256
317
|
const window = windowFromEvent > 0 ? windowFromEvent : resolveWindow(currentModel);
|
|
257
|
-
const
|
|
258
|
-
const
|
|
318
|
+
const pricedUsage = Object.keys(lastUsage).length > 0 ? lastUsage : totalUsage;
|
|
319
|
+
const promptTokens = codexPromptTokens(pricedUsage);
|
|
320
|
+
const fallbackPromptTokens = promptTokens > 0 ? promptTokens : toNumber(pricedUsage.total_tokens);
|
|
259
321
|
if (window > 0 && fallbackPromptTokens > 0) {
|
|
260
322
|
const pct = (fallbackPromptTokens / window) * 100;
|
|
261
323
|
maxContextPct = maxContextPct === null ? pct : Math.max(maxContextPct, pct);
|
|
262
324
|
}
|
|
325
|
+
if (currentModel) {
|
|
326
|
+
const cost = estimateUsageCost({
|
|
327
|
+
model: currentModel,
|
|
328
|
+
promptTokens: fallbackPromptTokens,
|
|
329
|
+
inputTokens: codexBillableInputTokens(pricedUsage),
|
|
330
|
+
cachedReadTokens: toNumber(pricedUsage.cached_input_tokens),
|
|
331
|
+
cachedCreateTokens: 0,
|
|
332
|
+
outputTokens: toNumber(pricedUsage.output_tokens),
|
|
333
|
+
reasoningOutputTokens: toNumber(pricedUsage.reasoning_output_tokens),
|
|
334
|
+
}, config.cost);
|
|
335
|
+
if (cost === null) {
|
|
336
|
+
costKnown = false;
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
costTotal += cost;
|
|
340
|
+
}
|
|
341
|
+
const usageTotals = tokenTotalsFromCodexUsageRecord(pricedUsage);
|
|
342
|
+
const usagePoint = usagePointFromTotals(event, "codex", currentModel, usageTotals, cost);
|
|
343
|
+
if (usagePoint)
|
|
344
|
+
usagePoints.push(usagePoint);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
const usageTotals = tokenTotalsFromCodexUsageRecord(pricedUsage);
|
|
348
|
+
const usagePoint = usagePointFromTotals(event, "codex", "<unknown>", usageTotals, null);
|
|
349
|
+
if (usagePoint)
|
|
350
|
+
usagePoints.push(usagePoint);
|
|
351
|
+
}
|
|
263
352
|
}
|
|
264
353
|
const tokenTotals = finalizeTokenTotals(latestTotals);
|
|
265
354
|
const topShares = buildTopModelShares(modelTotalDeltas, config.traceInspector.topModelCount);
|
|
266
|
-
const modelBreakdown = new Map();
|
|
267
|
-
const allModelShares = [...modelTotalDeltas.entries()].filter(([, tokens]) => tokens > 0);
|
|
268
|
-
const shareTotal = allModelShares.reduce((sum, [, tokens]) => sum + tokens, 0);
|
|
269
|
-
if (shareTotal > 0) {
|
|
270
|
-
for (const [model, modelTokens] of allModelShares) {
|
|
271
|
-
const ratio = modelTokens / shareTotal;
|
|
272
|
-
modelBreakdown.set(model, codexTokensForCost({
|
|
273
|
-
inputTokens: tokenTotals.inputTokens * ratio,
|
|
274
|
-
cachedReadTokens: tokenTotals.cachedReadTokens * ratio,
|
|
275
|
-
cachedCreateTokens: tokenTotals.cachedCreateTokens * ratio,
|
|
276
|
-
outputTokens: tokenTotals.outputTokens * ratio,
|
|
277
|
-
reasoningOutputTokens: tokenTotals.reasoningOutputTokens * ratio,
|
|
278
|
-
totalTokens: tokenTotals.totalTokens * ratio,
|
|
279
|
-
}));
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
355
|
return {
|
|
283
356
|
tokenTotals,
|
|
284
357
|
modelTokenSharesTop: topShares,
|
|
285
358
|
modelTokenSharesEstimated: topShares.length > 0,
|
|
286
359
|
contextWindowPct: maxContextPct,
|
|
287
|
-
costEstimateUsd:
|
|
360
|
+
costEstimateUsd: finalizeCostTotal(costKnown, costTotal),
|
|
361
|
+
usagePoints,
|
|
288
362
|
};
|
|
289
363
|
}
|
|
290
364
|
function deriveOpenCodeMetrics(events, config) {
|
|
@@ -292,7 +366,10 @@ function deriveOpenCodeMetrics(events, config) {
|
|
|
292
366
|
const totals = emptyTokenTotals();
|
|
293
367
|
const modelBreakdown = new Map();
|
|
294
368
|
let maxContextPct = null;
|
|
369
|
+
let costTotal = 0;
|
|
370
|
+
let costKnown = config.cost.enabled;
|
|
295
371
|
const seenAssistantMessageIds = new Set();
|
|
372
|
+
const usagePoints = [];
|
|
296
373
|
for (const event of events) {
|
|
297
374
|
const raw = asRecord(event.raw);
|
|
298
375
|
const nestedMessage = asRecord(raw.message);
|
|
@@ -321,6 +398,24 @@ function deriveOpenCodeMetrics(events, config) {
|
|
|
321
398
|
const pct = (promptTokens / window) * 100;
|
|
322
399
|
maxContextPct = maxContextPct === null ? pct : Math.max(maxContextPct, pct);
|
|
323
400
|
}
|
|
401
|
+
const cost = estimateUsageCost({
|
|
402
|
+
model: modelId || model,
|
|
403
|
+
promptTokens,
|
|
404
|
+
inputTokens: usageTotals.inputTokens,
|
|
405
|
+
cachedReadTokens: usageTotals.cachedReadTokens,
|
|
406
|
+
cachedCreateTokens: usageTotals.cachedCreateTokens,
|
|
407
|
+
outputTokens: usageTotals.outputTokens,
|
|
408
|
+
reasoningOutputTokens: usageTotals.reasoningOutputTokens,
|
|
409
|
+
}, config.cost);
|
|
410
|
+
if (cost === null) {
|
|
411
|
+
costKnown = false;
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
costTotal += cost;
|
|
415
|
+
}
|
|
416
|
+
const usagePoint = usagePointFromTotals(event, "opencode", modelId || model, usageTotals, cost);
|
|
417
|
+
if (usagePoint)
|
|
418
|
+
usagePoints.push(usagePoint);
|
|
324
419
|
}
|
|
325
420
|
for (const [model, modelTotals] of modelBreakdown) {
|
|
326
421
|
modelBreakdown.set(model, finalizeTokenTotals(modelTotals));
|
|
@@ -330,7 +425,8 @@ function deriveOpenCodeMetrics(events, config) {
|
|
|
330
425
|
modelTokenSharesTop: buildTopModelShares(new Map([...modelBreakdown.entries()].map(([model, modelTotals]) => [model, modelTotals.totalTokens])), config.traceInspector.topModelCount),
|
|
331
426
|
modelTokenSharesEstimated: false,
|
|
332
427
|
contextWindowPct: maxContextPct,
|
|
333
|
-
costEstimateUsd:
|
|
428
|
+
costEstimateUsd: finalizeCostTotal(costKnown, costTotal),
|
|
429
|
+
usagePoints,
|
|
334
430
|
};
|
|
335
431
|
}
|
|
336
432
|
function deriveCursorMetrics(events, config) {
|
|
@@ -338,6 +434,7 @@ function deriveCursorMetrics(events, config) {
|
|
|
338
434
|
const totals = emptyTokenTotals();
|
|
339
435
|
const modelBreakdown = new Map();
|
|
340
436
|
let maxContextPct = null;
|
|
437
|
+
const usagePoints = [];
|
|
341
438
|
const modelFallback = events
|
|
342
439
|
.map((event) => asString(asRecord(event.raw).model).trim())
|
|
343
440
|
.find((model) => model.length > 0) ?? "<unknown>";
|
|
@@ -363,6 +460,22 @@ function deriveCursorMetrics(events, config) {
|
|
|
363
460
|
modelTotals.inputTokens += estimatedTokens;
|
|
364
461
|
applyPromptWindowEstimate();
|
|
365
462
|
modelBreakdown.set(model, modelTotals);
|
|
463
|
+
const usageTotals = finalizeTokenTotals({
|
|
464
|
+
...emptyTokenTotals(),
|
|
465
|
+
inputTokens: estimatedTokens,
|
|
466
|
+
});
|
|
467
|
+
const cost = estimateUsageCost({
|
|
468
|
+
model,
|
|
469
|
+
promptTokens: usageTotals.inputTokens,
|
|
470
|
+
inputTokens: usageTotals.inputTokens,
|
|
471
|
+
cachedReadTokens: 0,
|
|
472
|
+
cachedCreateTokens: 0,
|
|
473
|
+
outputTokens: 0,
|
|
474
|
+
reasoningOutputTokens: 0,
|
|
475
|
+
}, config.cost);
|
|
476
|
+
const usagePoint = usagePointFromTotals(event, "cursor", model, usageTotals, cost);
|
|
477
|
+
if (usagePoint)
|
|
478
|
+
usagePoints.push(usagePoint);
|
|
366
479
|
continue;
|
|
367
480
|
}
|
|
368
481
|
if (event.eventKind === "assistant" || event.eventKind === "tool_use" || event.eventKind === "reasoning") {
|
|
@@ -373,6 +486,23 @@ function deriveCursorMetrics(events, config) {
|
|
|
373
486
|
modelTotals.reasoningOutputTokens += estimatedTokens;
|
|
374
487
|
}
|
|
375
488
|
modelBreakdown.set(model, modelTotals);
|
|
489
|
+
const usageTotals = finalizeTokenTotals({
|
|
490
|
+
...emptyTokenTotals(),
|
|
491
|
+
outputTokens: estimatedTokens,
|
|
492
|
+
reasoningOutputTokens: event.eventKind === "reasoning" ? estimatedTokens : 0,
|
|
493
|
+
});
|
|
494
|
+
const cost = estimateUsageCost({
|
|
495
|
+
model,
|
|
496
|
+
promptTokens: 0,
|
|
497
|
+
inputTokens: 0,
|
|
498
|
+
cachedReadTokens: 0,
|
|
499
|
+
cachedCreateTokens: 0,
|
|
500
|
+
outputTokens: usageTotals.outputTokens,
|
|
501
|
+
reasoningOutputTokens: usageTotals.reasoningOutputTokens,
|
|
502
|
+
}, config.cost);
|
|
503
|
+
const usagePoint = usagePointFromTotals(event, "cursor", model, usageTotals, cost);
|
|
504
|
+
if (usagePoint)
|
|
505
|
+
usagePoints.push(usagePoint);
|
|
376
506
|
}
|
|
377
507
|
}
|
|
378
508
|
for (const [model, modelTotals] of modelBreakdown) {
|
|
@@ -384,6 +514,7 @@ function deriveCursorMetrics(events, config) {
|
|
|
384
514
|
modelTokenSharesEstimated: modelBreakdown.size > 0,
|
|
385
515
|
contextWindowPct: maxContextPct,
|
|
386
516
|
costEstimateUsd: estimateCost(modelBreakdown, config.cost),
|
|
517
|
+
usagePoints,
|
|
387
518
|
};
|
|
388
519
|
}
|
|
389
520
|
function deriveGeminiMetrics(events, config) {
|
|
@@ -393,6 +524,7 @@ function deriveGeminiMetrics(events, config) {
|
|
|
393
524
|
let maxContextPct = null;
|
|
394
525
|
const seenMessageIds = new Set();
|
|
395
526
|
const seenRows = new Set();
|
|
527
|
+
const usagePoints = [];
|
|
396
528
|
for (const event of events) {
|
|
397
529
|
const raw = asRecord(event.raw);
|
|
398
530
|
if (seenRows.has(raw))
|
|
@@ -421,6 +553,18 @@ function deriveGeminiMetrics(events, config) {
|
|
|
421
553
|
const pct = (promptTokens / window) * 100;
|
|
422
554
|
maxContextPct = maxContextPct === null ? pct : Math.max(maxContextPct, pct);
|
|
423
555
|
}
|
|
556
|
+
const cost = estimateUsageCost({
|
|
557
|
+
model,
|
|
558
|
+
promptTokens,
|
|
559
|
+
inputTokens: usageTotals.inputTokens,
|
|
560
|
+
cachedReadTokens: usageTotals.cachedReadTokens,
|
|
561
|
+
cachedCreateTokens: usageTotals.cachedCreateTokens,
|
|
562
|
+
outputTokens: usageTotals.outputTokens,
|
|
563
|
+
reasoningOutputTokens: usageTotals.reasoningOutputTokens,
|
|
564
|
+
}, config.cost);
|
|
565
|
+
const usagePoint = usagePointFromTotals(event, "gemini", model, usageTotals, cost);
|
|
566
|
+
if (usagePoint)
|
|
567
|
+
usagePoints.push(usagePoint);
|
|
424
568
|
}
|
|
425
569
|
for (const [model, modelTotals] of modelBreakdown) {
|
|
426
570
|
modelBreakdown.set(model, finalizeTokenTotals(modelTotals));
|
|
@@ -431,6 +575,7 @@ function deriveGeminiMetrics(events, config) {
|
|
|
431
575
|
modelTokenSharesEstimated: false,
|
|
432
576
|
contextWindowPct: maxContextPct,
|
|
433
577
|
costEstimateUsd: estimateCost(modelBreakdown, config.cost),
|
|
578
|
+
usagePoints,
|
|
434
579
|
};
|
|
435
580
|
}
|
|
436
581
|
function derivePiMetrics(events, config) {
|
|
@@ -441,6 +586,9 @@ function derivePiMetrics(events, config) {
|
|
|
441
586
|
const seenRows = new Set();
|
|
442
587
|
let embeddedCostTotal = 0;
|
|
443
588
|
let embeddedCostKnown = false;
|
|
589
|
+
let estimatedCostTotal = 0;
|
|
590
|
+
let estimatedCostKnown = config.cost.enabled;
|
|
591
|
+
const usagePoints = [];
|
|
444
592
|
for (const event of events) {
|
|
445
593
|
const raw = asRecord(event.raw);
|
|
446
594
|
if (seenRows.has(raw))
|
|
@@ -475,6 +623,27 @@ function derivePiMetrics(events, config) {
|
|
|
475
623
|
embeddedCostKnown = true;
|
|
476
624
|
}
|
|
477
625
|
}
|
|
626
|
+
const estimatedCost = estimateUsageCost({
|
|
627
|
+
model,
|
|
628
|
+
promptTokens,
|
|
629
|
+
inputTokens: usageTotals.inputTokens,
|
|
630
|
+
cachedReadTokens: usageTotals.cachedReadTokens,
|
|
631
|
+
cachedCreateTokens: usageTotals.cachedCreateTokens,
|
|
632
|
+
outputTokens: usageTotals.outputTokens,
|
|
633
|
+
reasoningOutputTokens: usageTotals.reasoningOutputTokens,
|
|
634
|
+
}, config.cost);
|
|
635
|
+
if (estimatedCost === null) {
|
|
636
|
+
estimatedCostKnown = false;
|
|
637
|
+
}
|
|
638
|
+
else {
|
|
639
|
+
estimatedCostTotal += estimatedCost;
|
|
640
|
+
}
|
|
641
|
+
const preferredCost = Object.prototype.hasOwnProperty.call(cost, "total")
|
|
642
|
+
? Number(cost.total)
|
|
643
|
+
: estimatedCost;
|
|
644
|
+
const usagePoint = usagePointFromTotals(event, "pi", model, usageTotals, Number.isFinite(preferredCost) ? preferredCost : estimatedCost);
|
|
645
|
+
if (usagePoint)
|
|
646
|
+
usagePoints.push(usagePoint);
|
|
478
647
|
}
|
|
479
648
|
for (const [model, modelTotals] of modelBreakdown) {
|
|
480
649
|
modelBreakdown.set(model, finalizeTokenTotals(modelTotals));
|
|
@@ -484,7 +653,10 @@ function derivePiMetrics(events, config) {
|
|
|
484
653
|
modelTokenSharesTop: buildTopModelShares(new Map([...modelBreakdown.entries()].map(([model, modelTotals]) => [model, modelTotals.totalTokens])), config.traceInspector.topModelCount),
|
|
485
654
|
modelTokenSharesEstimated: false,
|
|
486
655
|
contextWindowPct: maxContextPct,
|
|
487
|
-
costEstimateUsd: embeddedCostKnown
|
|
656
|
+
costEstimateUsd: embeddedCostKnown
|
|
657
|
+
? Number(embeddedCostTotal.toFixed(6))
|
|
658
|
+
: finalizeCostTotal(estimatedCostKnown, estimatedCostTotal),
|
|
659
|
+
usagePoints,
|
|
488
660
|
};
|
|
489
661
|
}
|
|
490
662
|
export function deriveSessionMetrics(events, agent, config) {
|
|
@@ -506,6 +678,7 @@ export function deriveSessionMetrics(events, agent, config) {
|
|
|
506
678
|
modelTokenSharesEstimated: false,
|
|
507
679
|
contextWindowPct: null,
|
|
508
680
|
costEstimateUsd: null,
|
|
681
|
+
usagePoints: [],
|
|
509
682
|
};
|
|
510
683
|
}
|
|
511
684
|
//# sourceMappingURL=metrics.js.map
|