margin-meter 0.1.0 → 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/README.md +353 -8
- package/dist/batching.d.ts +94 -0
- package/dist/batching.d.ts.map +1 -0
- package/dist/batching.js +181 -0
- package/dist/batching.js.map +1 -0
- package/dist/braintrust.d.ts +153 -0
- package/dist/braintrust.d.ts.map +1 -0
- package/dist/braintrust.js +424 -0
- package/dist/braintrust.js.map +1 -0
- package/dist/index.d.ts +428 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +927 -9
- package/dist/index.js.map +1 -1
- package/dist/instrument.d.ts +74 -0
- package/dist/instrument.d.ts.map +1 -0
- package/dist/instrument.js +153 -0
- package/dist/instrument.js.map +1 -0
- package/dist/langsmith.d.ts +150 -0
- package/dist/langsmith.d.ts.map +1 -0
- package/dist/langsmith.js +415 -0
- package/dist/langsmith.js.map +1 -0
- package/dist/promptfoo.d.ts +161 -0
- package/dist/promptfoo.d.ts.map +1 -0
- package/dist/promptfoo.js +446 -0
- package/dist/promptfoo.js.map +1 -0
- package/dist/providers.d.ts +190 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +611 -0
- package/dist/providers.js.map +1 -0
- package/dist/substrate.d.ts +51 -0
- package/dist/substrate.d.ts.map +1 -0
- package/dist/substrate.js +132 -0
- package/dist/substrate.js.map +1 -0
- package/dist/vitest.d.ts +232 -0
- package/dist/vitest.d.ts.map +1 -0
- package/dist/vitest.js +502 -0
- package/dist/vitest.js.map +1 -0
- package/package.json +25 -7
|
@@ -0,0 +1,611 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the measured economics of one LLM call straight off a provider response.
|
|
3
|
+
*
|
|
4
|
+
* The TS twin of `margin_meter.providers`: given the object an OpenAI /
|
|
5
|
+
* Anthropic / Gemini JS client returns, recover the `(provider, model, tokens)`
|
|
6
|
+
* a Margin call row needs — so auto-instrumentation is a few lines with no
|
|
7
|
+
* manual token bookkeeping.
|
|
8
|
+
*
|
|
9
|
+
* Dependency-free and duck-typed on purpose: it never imports the provider SDKs,
|
|
10
|
+
* reading fields by shape so it works on a real SDK object, a plain object (the
|
|
11
|
+
* shape a mocked provider returns in tests), or JSON. The three shapes, as the
|
|
12
|
+
* current JS SDKs publish them:
|
|
13
|
+
*
|
|
14
|
+
* - **OpenAI** — `model`; `usage.prompt_tokens` / `completion_tokens`; cached
|
|
15
|
+
* reads at `usage.prompt_tokens_details.cached_tokens` (Responses API:
|
|
16
|
+
* `usage.input_tokens` / `output_tokens` / `input_tokens_details.cached_tokens`).
|
|
17
|
+
* - **Anthropic** — `model`; `usage.input_tokens` / `output_tokens`; cached
|
|
18
|
+
* reads at `usage.cache_read_input_tokens`; cache WRITES at
|
|
19
|
+
* `usage.cache_creation_input_tokens` (a ~1.25x premium bucket).
|
|
20
|
+
* - **Gemini** (`@google/generative-ai`) — `response.usageMetadata` (the
|
|
21
|
+
* `generateContent` result nests it under `.response`), with
|
|
22
|
+
* `promptTokenCount` / `candidatesTokenCount` / `cachedContentTokenCount`, plus
|
|
23
|
+
* `thoughtsTokenCount` (thinking tokens, billed as output and folded in).
|
|
24
|
+
* The model does not ride the response, so the caller passes it.
|
|
25
|
+
* - **Cohere** (v2 `/chat`) — billed counts nest under `usage.billed_units`
|
|
26
|
+
* (what is charged; raw `usage.tokens` is the fallback), each with
|
|
27
|
+
* `input_tokens` / `output_tokens`. Cohere publishes no chat prompt-cache
|
|
28
|
+
* discount, so cache reads bill as ordinary input (`cacheReadTokens` stays 0);
|
|
29
|
+
* the model does not ride the response, so the caller passes it.
|
|
30
|
+
* - **AWS Bedrock** (`@aws-sdk/client-bedrock-runtime`, Converse) — usage rides
|
|
31
|
+
* `usage.inputTokens` / `outputTokens` in camelCase, with ADDITIVE cache
|
|
32
|
+
* buckets `cacheReadInputTokens` / `cacheWriteInputTokens` (AWS documents
|
|
33
|
+
* `totalTokens = inputTokens + outputTokens + cacheReadInputTokens +
|
|
34
|
+
* cacheWriteInputTokens`), so the three input-side buckets are disjoint and
|
|
35
|
+
* each reads verbatim, no subtraction. The Converse response omits the model
|
|
36
|
+
* id, so the caller passes it (`instrumentBedrock` reads it off the command's
|
|
37
|
+
* `input.modelId`); its gateway form (`us.anthropic.claude-…-v1:0`) prices
|
|
38
|
+
* through the server's `normalize_model`.
|
|
39
|
+
*
|
|
40
|
+
* Numbers are read verbatim — never inflated. A field the provider didn't report
|
|
41
|
+
* reads 0; an unrecognised shape throws `UsageExtractionError` rather than
|
|
42
|
+
* emitting a silently-zero (free-looking) call.
|
|
43
|
+
*/
|
|
44
|
+
export const OPENAI = "openai";
|
|
45
|
+
export const ANTHROPIC = "anthropic";
|
|
46
|
+
export const GOOGLE = "google";
|
|
47
|
+
export const COHERE = "cohere";
|
|
48
|
+
export const BEDROCK = "bedrock";
|
|
49
|
+
/** The response object matched no provider shape we can meter. */
|
|
50
|
+
export class UsageExtractionError extends Error {
|
|
51
|
+
constructor(message) {
|
|
52
|
+
super(message);
|
|
53
|
+
this.name = "UsageExtractionError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Read `obj.name` from an object OR undefined — duck-typed, null-safe. */
|
|
57
|
+
function get(obj, name) {
|
|
58
|
+
if (obj === null || obj === undefined)
|
|
59
|
+
return undefined;
|
|
60
|
+
if (typeof obj !== "object")
|
|
61
|
+
return undefined;
|
|
62
|
+
return obj[name];
|
|
63
|
+
}
|
|
64
|
+
/** Walk a chain of field names, tolerating a missing hop. */
|
|
65
|
+
function getPath(obj, ...names) {
|
|
66
|
+
let cur = obj;
|
|
67
|
+
for (const name of names) {
|
|
68
|
+
cur = get(cur, name);
|
|
69
|
+
if (cur === null || cur === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
return cur;
|
|
73
|
+
}
|
|
74
|
+
/** Coerce a reported token count to a non-negative int; missing → 0. Reads
|
|
75
|
+
* verbatim — never rounds a real count up or invents one. */
|
|
76
|
+
function asInt(value) {
|
|
77
|
+
if (value === null || value === undefined)
|
|
78
|
+
return 0;
|
|
79
|
+
const n = Math.trunc(Number(value));
|
|
80
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
81
|
+
return 0;
|
|
82
|
+
return n;
|
|
83
|
+
}
|
|
84
|
+
/** First element of an array-shaped value, else undefined (duck-typed). OpenAI and
|
|
85
|
+
* Gemini nest their stop/finish reason under the first choice / candidate. */
|
|
86
|
+
function first(seq) {
|
|
87
|
+
if (Array.isArray(seq))
|
|
88
|
+
return seq.length > 0 ? seq[0] : undefined;
|
|
89
|
+
return undefined;
|
|
90
|
+
}
|
|
91
|
+
/** A provider's stop/finish reason as a clean string, or undefined (MAR-209).
|
|
92
|
+
* Read VERBATIM — never mapped, normalised, or inferred into a billing verdict.
|
|
93
|
+
* A missing, blank, or non-scalar value is undefined (UNKNOWN, first-class),
|
|
94
|
+
* never defaulted to a plausible value like "stop". A provider that reports an
|
|
95
|
+
* enum stringifies here; the value is stored, never interpreted. */
|
|
96
|
+
function asReason(value) {
|
|
97
|
+
if (value === null || value === undefined)
|
|
98
|
+
return undefined;
|
|
99
|
+
if (typeof value === "object")
|
|
100
|
+
return undefined;
|
|
101
|
+
const s = String(value).trim();
|
|
102
|
+
return s.length > 0 ? s : undefined;
|
|
103
|
+
}
|
|
104
|
+
/** The Gemini `generateContent` result nests usage under `.response`; unwrap it. */
|
|
105
|
+
function usageMetadata(response) {
|
|
106
|
+
const direct = get(response, "usageMetadata");
|
|
107
|
+
if (direct !== undefined)
|
|
108
|
+
return direct;
|
|
109
|
+
return getPath(response, "response", "usageMetadata");
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Best-effort provider inference from a response's shape. Prefers unambiguous
|
|
113
|
+
* signals: Gemini exposes `usageMetadata`; Anthropic's usage carries
|
|
114
|
+
* `input_tokens` while OpenAI's carries `prompt_tokens`. Returns undefined when
|
|
115
|
+
* nothing distinguishes it — the caller must then name the provider (the
|
|
116
|
+
* instrumenter always does).
|
|
117
|
+
*/
|
|
118
|
+
export function detectProvider(response) {
|
|
119
|
+
if (usageMetadata(response) !== undefined)
|
|
120
|
+
return GOOGLE;
|
|
121
|
+
const usage = get(response, "usage");
|
|
122
|
+
if (usage !== undefined && usage !== null) {
|
|
123
|
+
// Cohere nests billed counts under `billed_units` — a key no other provider
|
|
124
|
+
// carries, so it is an unambiguous signal. Checked before Anthropic so its
|
|
125
|
+
// NESTED input_tokens is never read as Anthropic's top-level one.
|
|
126
|
+
if (get(usage, "billed_units") !== undefined)
|
|
127
|
+
return COHERE;
|
|
128
|
+
// Bedrock's Converse usage is camelCase (`inputTokens`/`outputTokens`) — a
|
|
129
|
+
// shape every other provider spells snake_case, so it is unambiguous (like
|
|
130
|
+
// Cohere's `billed_units`). Checked before the snake_case branches so its
|
|
131
|
+
// camelCase keys are never read as a missing OpenAI/Anthropic usage.
|
|
132
|
+
if (get(usage, "inputTokens") !== undefined || get(usage, "outputTokens") !== undefined) {
|
|
133
|
+
return BEDROCK;
|
|
134
|
+
}
|
|
135
|
+
if (get(usage, "prompt_tokens") !== undefined || get(usage, "completion_tokens") !== undefined) {
|
|
136
|
+
return OPENAI;
|
|
137
|
+
}
|
|
138
|
+
if (get(usage, "input_tokens") !== undefined || get(usage, "output_tokens") !== undefined) {
|
|
139
|
+
return ANTHROPIC;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
// OpenRouter ROUTER slugs pick a different model per call, so the requested name has no
|
|
145
|
+
// single rate and would price at the server's $1/$3 fallback (MAR-1309). The response's
|
|
146
|
+
// own `model` is the one that served — and billed — the call.
|
|
147
|
+
const OPENROUTER_ROUTERS = new Set(["auto", "auto-beta", "pareto-code"]);
|
|
148
|
+
// FAN-OUT slugs run N panel calls plus an analyst call: no single served model prices
|
|
149
|
+
// them, and the analyst's name would under-state the bill several-fold. They keep their
|
|
150
|
+
// slug and carry OpenRouter's billed `usage.cost` instead.
|
|
151
|
+
const OPENROUTER_FANOUT = new Set(["fusion", "fusion-flash"]);
|
|
152
|
+
/** The route under `openrouter/` (however many prefixes were stacked), else undefined. */
|
|
153
|
+
function openrouterRoute(model) {
|
|
154
|
+
if (!model)
|
|
155
|
+
return undefined;
|
|
156
|
+
let rest = model.trim().toLowerCase();
|
|
157
|
+
if (!rest.startsWith("openrouter/"))
|
|
158
|
+
return undefined;
|
|
159
|
+
while (rest.startsWith("openrouter/"))
|
|
160
|
+
rest = rest.slice("openrouter/".length);
|
|
161
|
+
return rest;
|
|
162
|
+
}
|
|
163
|
+
/** True for `openrouter/fusion` and its siblings (many billed calls per request). */
|
|
164
|
+
export function isFanoutSlug(model) {
|
|
165
|
+
const route = openrouterRoute(model);
|
|
166
|
+
return route !== undefined && OPENROUTER_FANOUT.has(route);
|
|
167
|
+
}
|
|
168
|
+
/** The caller's model, unless it names a router and the response says what served it. */
|
|
169
|
+
function billedModel(requested, response) {
|
|
170
|
+
const served = get(response, "model");
|
|
171
|
+
const route = openrouterRoute(requested);
|
|
172
|
+
if (route !== undefined && OPENROUTER_ROUTERS.has(route) && typeof served === "string" && served.trim()) {
|
|
173
|
+
return served.trim();
|
|
174
|
+
}
|
|
175
|
+
return requested ?? served;
|
|
176
|
+
}
|
|
177
|
+
/** OpenRouter's billed `usage.cost` for a fan-out slug; undefined when absent or not a sane number. */
|
|
178
|
+
function fanoutBilledCost(requested, usage) {
|
|
179
|
+
if (!isFanoutSlug(requested))
|
|
180
|
+
return undefined;
|
|
181
|
+
const cost = saneCost(get(usage, "cost"));
|
|
182
|
+
if (cost === undefined)
|
|
183
|
+
return undefined;
|
|
184
|
+
// BRING-YOUR-OWN-KEY: `usage.cost` is then only OpenRouter's charge and the provider's
|
|
185
|
+
// bill is `cost_details.upstream_inference_cost` (0/absent otherwise). The spend is the
|
|
186
|
+
// sum; a present but garbled upstream figure makes the cost unknown, never half-counted.
|
|
187
|
+
const upstreamRaw = getPath(usage, "cost_details", "upstream_inference_cost");
|
|
188
|
+
if (upstreamRaw === undefined || upstreamRaw === null)
|
|
189
|
+
return cost;
|
|
190
|
+
const upstream = saneCost(upstreamRaw);
|
|
191
|
+
return upstream === undefined ? undefined : cost + upstream;
|
|
192
|
+
}
|
|
193
|
+
/** A finite, non-negative dollar figure, else undefined (never a guessed number). */
|
|
194
|
+
function saneCost(value) {
|
|
195
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0)
|
|
196
|
+
return undefined;
|
|
197
|
+
return value;
|
|
198
|
+
}
|
|
199
|
+
function extractOpenAI(response, model) {
|
|
200
|
+
const usage = get(response, "usage");
|
|
201
|
+
if (usage === undefined || usage === null) {
|
|
202
|
+
throw new UsageExtractionError("openai response carries no .usage");
|
|
203
|
+
}
|
|
204
|
+
const inputRaw = get(usage, "prompt_tokens") ?? get(usage, "input_tokens");
|
|
205
|
+
const outputRaw = get(usage, "completion_tokens") ?? get(usage, "output_tokens");
|
|
206
|
+
// DeepSeek-direct is OpenAI-compatible, so instrument reaches it through the same
|
|
207
|
+
// client — but it reports cache hits in its own prompt_cache_hit_tokens field, not
|
|
208
|
+
// prompt_tokens_details.cached_tokens, and prompt_tokens is inclusive of them. A
|
|
209
|
+
// genuine OpenAI/Azure response never carries this field (reads 0), so the direct
|
|
210
|
+
// path is unchanged; reading it captures DeepSeek's cache discount. Consulted last,
|
|
211
|
+
// so a provider reporting both is never double-counted.
|
|
212
|
+
const cachedRaw = getPath(usage, "prompt_tokens_details", "cached_tokens") ??
|
|
213
|
+
getPath(usage, "input_tokens_details", "cached_tokens") ??
|
|
214
|
+
get(usage, "prompt_cache_hit_tokens");
|
|
215
|
+
const cached = asInt(cachedRaw);
|
|
216
|
+
// prompt_tokens is INCLUSIVE of cached — split so cache reads are not
|
|
217
|
+
// double-billed as fresh input (the server bills the two separately).
|
|
218
|
+
const freshInput = asInt(inputRaw) - cached;
|
|
219
|
+
// A reasoning model (o-series, gpt-5) reports the hidden-thinking share under
|
|
220
|
+
// completion_tokens_details.reasoning_tokens — a BREAKDOWN of completion_tokens,
|
|
221
|
+
// not an addition. outputTokens already counts it; carry it only for the
|
|
222
|
+
// reasoning-share detector, clamped to output so the subset never exceeds the
|
|
223
|
+
// whole. 0 on a non-reasoning response.
|
|
224
|
+
const out = asInt(outputRaw);
|
|
225
|
+
const reasoning = asInt(getPath(usage, "completion_tokens_details", "reasoning_tokens"));
|
|
226
|
+
return {
|
|
227
|
+
provider: OPENAI,
|
|
228
|
+
model: billedModel(model, response),
|
|
229
|
+
inputTokens: freshInput > 0 ? freshInput : 0,
|
|
230
|
+
outputTokens: out,
|
|
231
|
+
cacheReadTokens: cached,
|
|
232
|
+
cacheCreationTokens: 0,
|
|
233
|
+
reasoningTokens: Math.min(reasoning, out),
|
|
234
|
+
// finish_reason nests under the first choice ("stop"/"length"/"content_filter"/
|
|
235
|
+
// "tool_calls"). Absent on a streaming final chunk whose choices is empty → undefined.
|
|
236
|
+
stopReason: asReason(get(first(get(response, "choices")), "finish_reason")),
|
|
237
|
+
billedCostUsd: fanoutBilledCost(model, usage),
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function extractAnthropic(response, model) {
|
|
241
|
+
const usage = get(response, "usage");
|
|
242
|
+
if (usage === undefined || usage === null) {
|
|
243
|
+
throw new UsageExtractionError("anthropic response carries no .usage");
|
|
244
|
+
}
|
|
245
|
+
// Anthropic's input_tokens EXCLUDES both cache reads and cache writes (each a
|
|
246
|
+
// separate field) — read them verbatim, no subtraction. Cache creation
|
|
247
|
+
// (cache_creation_input_tokens) is the write-premium bucket AGGREGATE. When a
|
|
248
|
+
// request pins a 1-hour TTL, Anthropic breaks that down under usage.cache_creation
|
|
249
|
+
// into ephemeral_5m/ephemeral_1h — the 1-hour writes bill ~2x input (vs 5-minute
|
|
250
|
+
// ~1.25x), so split them out. The 1-hour portion goes in its own bucket and the
|
|
251
|
+
// 5-minute bucket is the remainder; no breakdown → 1h is 0 and the whole aggregate
|
|
252
|
+
// stays 5-minute, byte-identical to before.
|
|
253
|
+
const totalCreation = asInt(get(usage, "cache_creation_input_tokens"));
|
|
254
|
+
const creation1h = asInt(getPath(usage, "cache_creation", "ephemeral_1h_input_tokens"));
|
|
255
|
+
const creation5m = totalCreation - creation1h;
|
|
256
|
+
return {
|
|
257
|
+
provider: ANTHROPIC,
|
|
258
|
+
model: model ?? get(response, "model"),
|
|
259
|
+
inputTokens: asInt(get(usage, "input_tokens")),
|
|
260
|
+
outputTokens: asInt(get(usage, "output_tokens")),
|
|
261
|
+
cacheReadTokens: asInt(get(usage, "cache_read_input_tokens")),
|
|
262
|
+
// Never let a malformed breakdown push the 5-minute remainder negative.
|
|
263
|
+
cacheCreationTokens: creation5m > 0 ? creation5m : 0,
|
|
264
|
+
cacheCreation1hTokens: creation1h,
|
|
265
|
+
// Non-streaming carries stop_reason top-level; a STREAMING message_delta carries
|
|
266
|
+
// it under delta.stop_reason — read both so a streamed Fable fallback (MAR-209)
|
|
267
|
+
// is captured either way.
|
|
268
|
+
stopReason: asReason(get(response, "stop_reason") ?? getPath(response, "delta", "stop_reason")),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
function extractGemini(response, model) {
|
|
272
|
+
const meta = usageMetadata(response);
|
|
273
|
+
if (meta === undefined || meta === null) {
|
|
274
|
+
throw new UsageExtractionError("gemini response carries no usageMetadata");
|
|
275
|
+
}
|
|
276
|
+
const cached = asInt(get(meta, "cachedContentTokenCount"));
|
|
277
|
+
const prompt = asInt(get(meta, "promptTokenCount"));
|
|
278
|
+
// promptTokenCount is INCLUSIVE of cached content — split it out.
|
|
279
|
+
const freshInput = prompt - cached;
|
|
280
|
+
// Gemini bills THINKING tokens (thoughtsTokenCount) at the output rate but
|
|
281
|
+
// reports them in a field DISJOINT from candidatesTokenCount (the visible
|
|
282
|
+
// completion). Billed output = candidates + thoughts, which also equals
|
|
283
|
+
// totalTokenCount - promptTokenCount. Take the max so a thinking-enabled call
|
|
284
|
+
// is never under-counted, whichever fields the response populates.
|
|
285
|
+
const candidates = asInt(get(meta, "candidatesTokenCount"));
|
|
286
|
+
const thoughts = asInt(get(meta, "thoughtsTokenCount"));
|
|
287
|
+
const total = asInt(get(meta, "totalTokenCount"));
|
|
288
|
+
const outputTokens = Math.max(candidates + thoughts, total ? total - prompt : 0);
|
|
289
|
+
return {
|
|
290
|
+
provider: GOOGLE,
|
|
291
|
+
model,
|
|
292
|
+
inputTokens: freshInput > 0 ? freshInput : 0,
|
|
293
|
+
outputTokens,
|
|
294
|
+
cacheReadTokens: cached,
|
|
295
|
+
cacheCreationTokens: 0,
|
|
296
|
+
// thoughts already sit inside outputTokens (billed at the output rate);
|
|
297
|
+
// carried here only for the reasoning-share detector, never above output.
|
|
298
|
+
reasoningTokens: Math.min(thoughts, outputTokens),
|
|
299
|
+
// finishReason nests under the first candidate ("STOP"/"MAX_TOKENS"/"SAFETY"/
|
|
300
|
+
// "RECITATION") and may be an enum — stringified verbatim, never interpreted. The
|
|
301
|
+
// generateContent result nests candidates under `.response` (like usageMetadata),
|
|
302
|
+
// so read both; the JS SDK spells the field camelCase.
|
|
303
|
+
stopReason: asReason(get(first(get(response, "candidates") ?? getPath(response, "response", "candidates")), "finishReason")),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function extractCohere(response, model) {
|
|
307
|
+
const usage = get(response, "usage");
|
|
308
|
+
if (usage === undefined || usage === null) {
|
|
309
|
+
throw new UsageExtractionError("cohere response carries no .usage");
|
|
310
|
+
}
|
|
311
|
+
// Cohere v2 /chat reports billed counts under `billed_units` (what is charged),
|
|
312
|
+
// with a raw `tokens` mirror as the fallback. input_tokens is read VERBATIM:
|
|
313
|
+
// Cohere publishes no chat prompt-cache discount, so a cache read bills at the
|
|
314
|
+
// input rate and is already inside billed_units.input — folding it into input
|
|
315
|
+
// (cacheReadTokens 0) is cost-exact and never over-states a caching win.
|
|
316
|
+
const units = get(usage, "billed_units") ?? get(usage, "tokens");
|
|
317
|
+
if (units === undefined || units === null) {
|
|
318
|
+
throw new UsageExtractionError("cohere usage carries no billed_units/tokens");
|
|
319
|
+
}
|
|
320
|
+
return {
|
|
321
|
+
provider: COHERE,
|
|
322
|
+
model: model ?? get(response, "model"),
|
|
323
|
+
inputTokens: asInt(get(units, "input_tokens")),
|
|
324
|
+
outputTokens: asInt(get(units, "output_tokens")),
|
|
325
|
+
cacheReadTokens: 0,
|
|
326
|
+
cacheCreationTokens: 0,
|
|
327
|
+
// Cohere v2 reports finish_reason top-level ("COMPLETE"/"MAX_TOKENS"/"ERROR").
|
|
328
|
+
stopReason: asReason(get(response, "finish_reason")),
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
function extractBedrock(response, model) {
|
|
332
|
+
const usage = get(response, "usage");
|
|
333
|
+
if (usage === undefined || usage === null) {
|
|
334
|
+
throw new UsageExtractionError("bedrock response carries no .usage");
|
|
335
|
+
}
|
|
336
|
+
// Bedrock's Converse usage is camelCase and — like Anthropic native —
|
|
337
|
+
// `inputTokens` EXCLUDES the cache buckets: AWS documents `totalTokens =
|
|
338
|
+
// inputTokens + outputTokens + cacheReadInputTokens + cacheWriteInputTokens`,
|
|
339
|
+
// so the three input-side buckets are disjoint and each reads verbatim, no
|
|
340
|
+
// subtraction. `cacheWriteInputTokens` is the write bucket (a cache-creation
|
|
341
|
+
// premium); `cacheReadInputTokens` the discounted hit. Both absent (→ 0) on a
|
|
342
|
+
// no-cache call. The response omits the model id, so the caller supplies it.
|
|
343
|
+
return {
|
|
344
|
+
provider: BEDROCK,
|
|
345
|
+
model: model ?? get(response, "model"),
|
|
346
|
+
inputTokens: asInt(get(usage, "inputTokens")),
|
|
347
|
+
outputTokens: asInt(get(usage, "outputTokens")),
|
|
348
|
+
cacheReadTokens: asInt(get(usage, "cacheReadInputTokens")),
|
|
349
|
+
cacheCreationTokens: asInt(get(usage, "cacheWriteInputTokens")),
|
|
350
|
+
// Converse reports stopReason ("end_turn"/"max_tokens"/"content_filtered"/
|
|
351
|
+
// "guardrail_intervened").
|
|
352
|
+
stopReason: asReason(get(response, "stopReason")),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
const EXTRACTORS = {
|
|
356
|
+
[OPENAI]: extractOpenAI,
|
|
357
|
+
[ANTHROPIC]: extractAnthropic,
|
|
358
|
+
[GOOGLE]: extractGemini,
|
|
359
|
+
[COHERE]: extractCohere,
|
|
360
|
+
[BEDROCK]: extractBedrock,
|
|
361
|
+
};
|
|
362
|
+
/**
|
|
363
|
+
* Recover the metered `Usage` of one call from its provider response. `provider`
|
|
364
|
+
* forces the shape (the instrumenter always knows which client it patched);
|
|
365
|
+
* omit it and the provider is inferred from the response's shape. `model`
|
|
366
|
+
* overrides a response that omits its model (Gemini). Throws
|
|
367
|
+
* `UsageExtractionError` when the shape matches no known provider or carries no
|
|
368
|
+
* usage block, so a silently-free call is never emitted.
|
|
369
|
+
*/
|
|
370
|
+
export function extractUsage(response, opts = {}) {
|
|
371
|
+
const prov = (opts.provider ?? detectProvider(response));
|
|
372
|
+
const extractor = prov ? EXTRACTORS[prov] : undefined;
|
|
373
|
+
if (!extractor) {
|
|
374
|
+
throw new UsageExtractionError(`unknown or undetectable provider ${String(opts.provider)}; ` +
|
|
375
|
+
"pass provider: 'openai' | 'anthropic' | 'google' | 'cohere' | 'bedrock'");
|
|
376
|
+
}
|
|
377
|
+
return extractor(response, opts.model);
|
|
378
|
+
}
|
|
379
|
+
// --------------------------------------------------------------------------- //
|
|
380
|
+
// Streaming — reunite the usage of one STREAMED call across its chunks.
|
|
381
|
+
//
|
|
382
|
+
// A `stream: true` call resolves to an async-iterable of chunks, not a `.usage`
|
|
383
|
+
// response, so `extractUsage` on the resolved value throws and the call would be
|
|
384
|
+
// dropped. Streaming is the DEFAULT mode for interactive JS agents (the Vercel
|
|
385
|
+
// AI SDK, LangChain.js, chat UIs), so that is a whole class of spend going
|
|
386
|
+
// unmetered. These primitives are the TS twin of `margin_meter.providers`'
|
|
387
|
+
// `StreamUsageAccumulator`: read whatever usage each chunk carries, max-merge it
|
|
388
|
+
// across the stream, and finalize to one `Usage` — or `undefined` when the stream
|
|
389
|
+
// carried no usage at all (never a fabricated zero-token, free-looking row).
|
|
390
|
+
// --------------------------------------------------------------------------- //
|
|
391
|
+
/**
|
|
392
|
+
* Read whatever usage ONE streaming chunk/event carries, or `undefined`.
|
|
393
|
+
*
|
|
394
|
+
* The three streamed shapes differ in WHERE (and whether) a chunk carries usage:
|
|
395
|
+
*
|
|
396
|
+
* - **OpenAI** (needs `stream_options: { include_usage: true }`): every content
|
|
397
|
+
* chunk has `usage: null`; only the FINAL chunk carries the full `.usage`.
|
|
398
|
+
* - **Gemini**: every chunk carries a CUMULATIVE `usageMetadata` — the last is
|
|
399
|
+
* authoritative, and the running max keeps it.
|
|
400
|
+
* - **Anthropic**: no single event is complete — `message_start` carries the
|
|
401
|
+
* input + cache counts nested under `event.message.usage`, while `message_delta`
|
|
402
|
+
* carries the final `event.usage.output_tokens`. This reads BOTH carriers so the
|
|
403
|
+
* merge can reunite them.
|
|
404
|
+
*
|
|
405
|
+
* Returns `undefined` (never throws) for a chunk with no usage, so an ordinary
|
|
406
|
+
* content chunk is skipped, not treated as an error.
|
|
407
|
+
*/
|
|
408
|
+
export function usageFromStreamChunk(chunk, provider, model) {
|
|
409
|
+
// Straightforward carriers: a top-level `usage` (OpenAI final chunk, Anthropic
|
|
410
|
+
// message_delta) or `usageMetadata` (Gemini) — extractUsage reads either.
|
|
411
|
+
try {
|
|
412
|
+
return extractUsage(chunk, { provider, model });
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
/* not a complete-usage chunk — try the nested Anthropic carrier below */
|
|
416
|
+
}
|
|
417
|
+
// Anthropic's message_start nests the input/cache counts under
|
|
418
|
+
// `event.message.usage`; extractUsage on the event itself misses them, so read
|
|
419
|
+
// the nested message carrier directly (its usage IS the top-level shape).
|
|
420
|
+
const message = get(chunk, "message");
|
|
421
|
+
if (message !== undefined && message !== null && get(message, "usage") !== undefined) {
|
|
422
|
+
try {
|
|
423
|
+
return extractUsage(message, { provider: provider ?? ANTHROPIC, model });
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
/* not a readable message_start either */
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return usageFromBedrockStreamEvent(chunk, model);
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* The usage a Bedrock STREAMING event carries, or `undefined` (MAR-1518).
|
|
433
|
+
*
|
|
434
|
+
* Both streaming calls put the counts one level below where `extractBedrock` looks:
|
|
435
|
+
* `converseStream`'s terminal `metadata` event nests the Converse usage block, and
|
|
436
|
+
* `invokeModelWithResponseStream`'s terminal `chunk.bytes` decodes to JSON carrying
|
|
437
|
+
* `amazon-bedrock-invocationMetrics` (no cache breakdown, so those buckets read 0).
|
|
438
|
+
* Ported from the Python SDK's `_usage_from_bedrock_stream_event`.
|
|
439
|
+
*/
|
|
440
|
+
function usageFromBedrockStreamEvent(event, model) {
|
|
441
|
+
const meta = get(event, "metadata");
|
|
442
|
+
if (meta !== undefined && meta !== null && get(meta, "usage") !== undefined) {
|
|
443
|
+
try {
|
|
444
|
+
return extractBedrock(meta, model);
|
|
445
|
+
}
|
|
446
|
+
catch {
|
|
447
|
+
return undefined;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
const raw = getPath(event, "chunk", "bytes");
|
|
451
|
+
if (raw === undefined || raw === null)
|
|
452
|
+
return undefined;
|
|
453
|
+
try {
|
|
454
|
+
const text = typeof raw === "string" ? raw : new TextDecoder().decode(raw);
|
|
455
|
+
return bedrockInvokePayloadUsage(JSON.parse(text), model);
|
|
456
|
+
}
|
|
457
|
+
catch {
|
|
458
|
+
return undefined;
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
/**
|
|
462
|
+
* The usage a decoded `invokeModelWithResponseStream` payload carries, or `undefined`
|
|
463
|
+
* (MAR-1535 #1).
|
|
464
|
+
*
|
|
465
|
+
* The payload carries `amazon-bedrock-invocationMetrics` (`inputTokenCount`/`outputTokenCount`).
|
|
466
|
+
* For an Anthropic model it ALSO wraps the Messages event the model streamed — `message_start`
|
|
467
|
+
* nests the input and CACHE counts under `message.usage`, and `message_delta` puts the final
|
|
468
|
+
* output tokens at the top level. Reading only the metrics block metered a cache-heavy call as
|
|
469
|
+
* `0` cache tokens, understating its cost; this reads both and max-merges them, and takes the
|
|
470
|
+
* cache buckets from the metrics block too when AWS reports them (`cacheReadInputTokenCount` /
|
|
471
|
+
* `cacheWriteInputTokenCount`).
|
|
472
|
+
*/
|
|
473
|
+
function bedrockInvokePayloadUsage(payload, model) {
|
|
474
|
+
let got;
|
|
475
|
+
const metrics = get(payload, "amazon-bedrock-invocationMetrics");
|
|
476
|
+
if (metrics !== undefined && metrics !== null) {
|
|
477
|
+
const inp = get(metrics, "inputTokenCount");
|
|
478
|
+
const out = get(metrics, "outputTokenCount");
|
|
479
|
+
const cr = get(metrics, "cacheReadInputTokenCount");
|
|
480
|
+
const cw = get(metrics, "cacheWriteInputTokenCount");
|
|
481
|
+
if (inp !== undefined || out !== undefined || cr !== undefined || cw !== undefined) {
|
|
482
|
+
got = {
|
|
483
|
+
provider: BEDROCK,
|
|
484
|
+
model,
|
|
485
|
+
inputTokens: asInt(inp),
|
|
486
|
+
outputTokens: asInt(out),
|
|
487
|
+
cacheReadTokens: asInt(cr),
|
|
488
|
+
cacheCreationTokens: asInt(cw),
|
|
489
|
+
};
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
const message = get(payload, "message");
|
|
493
|
+
const nested = message !== undefined && message !== null && get(message, "usage") !== undefined;
|
|
494
|
+
const evt = nested ? message : get(payload, "usage") !== undefined ? payload : undefined;
|
|
495
|
+
if (evt !== undefined) {
|
|
496
|
+
let anthropic;
|
|
497
|
+
try {
|
|
498
|
+
anthropic = extractUsage(evt, { provider: ANTHROPIC, model });
|
|
499
|
+
}
|
|
500
|
+
catch {
|
|
501
|
+
anthropic = undefined;
|
|
502
|
+
}
|
|
503
|
+
if (anthropic !== undefined) {
|
|
504
|
+
got = got === undefined ? anthropic : mergeStreamUsage(got, anthropic);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
return got;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Merge two per-chunk usages, taking the MAX of each token bucket.
|
|
511
|
+
*
|
|
512
|
+
* Every streamed token count is monotonic within one call — cumulative (Gemini),
|
|
513
|
+
* or populated exactly once (OpenAI's final chunk; Anthropic's input-here /
|
|
514
|
+
* output-there split) — so the running max reconstructs the final total no matter
|
|
515
|
+
* which chunk carried which field. The max never invents a token; it only keeps
|
|
516
|
+
* the largest REAL count each field reached.
|
|
517
|
+
*/
|
|
518
|
+
export function mergeStreamUsage(a, b) {
|
|
519
|
+
return {
|
|
520
|
+
provider: a.provider ?? b.provider,
|
|
521
|
+
model: a.model ?? b.model,
|
|
522
|
+
inputTokens: Math.max(a.inputTokens, b.inputTokens),
|
|
523
|
+
outputTokens: Math.max(a.outputTokens, b.outputTokens),
|
|
524
|
+
cacheReadTokens: Math.max(a.cacheReadTokens, b.cacheReadTokens),
|
|
525
|
+
cacheCreationTokens: Math.max(a.cacheCreationTokens, b.cacheCreationTokens),
|
|
526
|
+
cacheCreation1hTokens: Math.max(a.cacheCreation1hTokens ?? 0, b.cacheCreation1hTokens ?? 0),
|
|
527
|
+
reasoningTokens: Math.max(a.reasoningTokens ?? 0, b.reasoningTokens ?? 0),
|
|
528
|
+
// Only a usage-bearing chunk reaches this merge, so it sees only a reason that rode
|
|
529
|
+
// WITH usage (Anthropic's message_delta, Gemini's final chunk, a seller that puts
|
|
530
|
+
// finish_reason on its usage chunk). A reason on a usage-less chunk (OpenAI's finish
|
|
531
|
+
// chunk, Bedrock's messageStop) is read by StreamUsageAccumulator instead (MAR-1516).
|
|
532
|
+
stopReason: a.stopReason ?? b.stopReason,
|
|
533
|
+
// A fan-out stream's billed cost rides its final usage chunk (MAR-1309).
|
|
534
|
+
billedCostUsd: a.billedCostUsd ?? b.billedCostUsd,
|
|
535
|
+
};
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* The stop reason one stream chunk carries, if any. Never throws.
|
|
539
|
+
*
|
|
540
|
+
* A stream rarely puts the reason and the usage on the same chunk (MAR-1516). OpenAI's
|
|
541
|
+
* finish chunk has no `usage` and the usage chunk after it has empty `choices`; Bedrock
|
|
542
|
+
* `converseStream` sends `stopReason` in `messageStop` and usage in a separate
|
|
543
|
+
* `metadata` event. A reader that only looks at usage-bearing chunks records every
|
|
544
|
+
* streamed call with no reason, so this reads it from whichever chunk holds it.
|
|
545
|
+
*/
|
|
546
|
+
export function streamChunkStopReason(chunk) {
|
|
547
|
+
try {
|
|
548
|
+
let reason = get(first(get(chunk, "choices")), "finish_reason") ?? // OpenAI
|
|
549
|
+
getPath(chunk, "delta", "stop_reason") ?? // Anthropic message_delta
|
|
550
|
+
getPath(chunk, "messageStop", "stopReason"); // Bedrock converseStream
|
|
551
|
+
if (reason === undefined || reason === null) {
|
|
552
|
+
const raw = getPath(chunk, "chunk", "bytes"); // Bedrock invoke stream
|
|
553
|
+
if (raw !== undefined && raw !== null) {
|
|
554
|
+
const text = typeof raw === "string" ? raw : new TextDecoder().decode(raw);
|
|
555
|
+
const payload = JSON.parse(text);
|
|
556
|
+
reason =
|
|
557
|
+
getPath(payload, "delta", "stop_reason") ??
|
|
558
|
+
get(payload, "stop_reason") ??
|
|
559
|
+
get(payload, "completionReason");
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return asReason(reason);
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
return undefined;
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Accumulates the metered usage of one STREAMING call across its chunks.
|
|
570
|
+
*
|
|
571
|
+
* Feed every chunk to `observe` as the host iterates the stream, then call
|
|
572
|
+
* `finalize` once the stream is exhausted (or closed) to get the single `Usage`
|
|
573
|
+
* for the whole call — or `undefined` when the stream never carried a usage block
|
|
574
|
+
* (e.g. an OpenAI stream opened without `include_usage`, where there is genuinely
|
|
575
|
+
* no count to meter and inventing one would be a lie). Provider-agnostic: the
|
|
576
|
+
* per-chunk read + max-merge handles OpenAI, Anthropic and Gemini streams alike.
|
|
577
|
+
*/
|
|
578
|
+
export class StreamUsageAccumulator {
|
|
579
|
+
provider;
|
|
580
|
+
model;
|
|
581
|
+
usage = undefined;
|
|
582
|
+
stopReason = undefined;
|
|
583
|
+
// Explicit assignment (not constructor parameter properties) so the source is
|
|
584
|
+
// erasable TypeScript — `node --experimental-strip-types` runs it with no build.
|
|
585
|
+
constructor(provider, model) {
|
|
586
|
+
this.provider = provider;
|
|
587
|
+
this.model = model;
|
|
588
|
+
}
|
|
589
|
+
/** Fold one chunk's usage (if any) into the running total. Never throws. */
|
|
590
|
+
observe(chunk) {
|
|
591
|
+
this.stopReason = streamChunkStopReason(chunk) ?? this.stopReason;
|
|
592
|
+
let u;
|
|
593
|
+
try {
|
|
594
|
+
u = usageFromStreamChunk(chunk, this.provider, this.model);
|
|
595
|
+
}
|
|
596
|
+
catch {
|
|
597
|
+
return; // a malformed chunk must never break the host's stream
|
|
598
|
+
}
|
|
599
|
+
if (u === undefined)
|
|
600
|
+
return;
|
|
601
|
+
this.usage = this.usage === undefined ? u : mergeStreamUsage(this.usage, u);
|
|
602
|
+
}
|
|
603
|
+
/** The accumulated usage, or `undefined` if the stream carried no usage. */
|
|
604
|
+
finalize() {
|
|
605
|
+
if (this.usage === undefined)
|
|
606
|
+
return undefined;
|
|
607
|
+
// The usage-bearing chunk's own reason wins; otherwise the one another chunk carried.
|
|
608
|
+
return { ...this.usage, stopReason: this.usage.stopReason ?? this.stopReason };
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
//# sourceMappingURL=providers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"providers.js","sourceRoot":"","sources":["../src/providers.ts"],"names":[],"mappings":"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"}
|