@ai-billing/core 0.0.5 → 0.0.7
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/index.cjs +20 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -1
- package/dist/index.d.ts +26 -1
- package/dist/index.js +20 -8
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -67,6 +67,7 @@ function buildMeterMetadata(event) {
|
|
|
67
67
|
addOptional("cache_read_tokens", u.cacheReadTokens);
|
|
68
68
|
addOptional("cache_write_tokens", u.cacheWriteTokens);
|
|
69
69
|
addOptional("request_count", u.requestCount);
|
|
70
|
+
addOptional("web_search_count", u.webSearchCount);
|
|
70
71
|
addOptional("raw_provider_cost", u.rawProviderCost);
|
|
71
72
|
addOptional("raw_upstream_inference_cost", u.rawUpstreamInferenceCost);
|
|
72
73
|
if (event.tags) {
|
|
@@ -86,7 +87,8 @@ function createV3BillingMiddleware(options) {
|
|
|
86
87
|
params,
|
|
87
88
|
usage,
|
|
88
89
|
providerMetadata,
|
|
89
|
-
responseId
|
|
90
|
+
responseId,
|
|
91
|
+
webSearchCount
|
|
90
92
|
}) => {
|
|
91
93
|
try {
|
|
92
94
|
const requestTags = params.providerOptions?.["ai-billing-tags"];
|
|
@@ -99,7 +101,8 @@ function createV3BillingMiddleware(options) {
|
|
|
99
101
|
model,
|
|
100
102
|
usage,
|
|
101
103
|
providerMetadata,
|
|
102
|
-
tags
|
|
104
|
+
tags,
|
|
105
|
+
webSearchCount
|
|
103
106
|
});
|
|
104
107
|
if (event && destinations && destinations?.length > 0) {
|
|
105
108
|
const dispatchDestinationsPromise = Promise.allSettled(
|
|
@@ -118,12 +121,16 @@ function createV3BillingMiddleware(options) {
|
|
|
118
121
|
specificationVersion: "v3",
|
|
119
122
|
wrapGenerate: async ({ doGenerate, model, params }) => {
|
|
120
123
|
const result = await doGenerate();
|
|
124
|
+
const webSearchCount = result.content.filter(
|
|
125
|
+
(c) => c.type === "source"
|
|
126
|
+
).length;
|
|
121
127
|
const event = await processEvent({
|
|
122
128
|
model,
|
|
123
129
|
params,
|
|
124
130
|
usage: result.usage,
|
|
125
131
|
providerMetadata: result.providerMetadata,
|
|
126
|
-
responseId: result.response?.id
|
|
132
|
+
responseId: result.response?.id,
|
|
133
|
+
webSearchCount
|
|
127
134
|
});
|
|
128
135
|
const providerMetadataWithBilling = {
|
|
129
136
|
...result.providerMetadata
|
|
@@ -142,6 +149,7 @@ function createV3BillingMiddleware(options) {
|
|
|
142
149
|
let usage;
|
|
143
150
|
let providerMetadata;
|
|
144
151
|
let finishChunk;
|
|
152
|
+
let webSearchCount = 0;
|
|
145
153
|
const billedStream = stream.pipeThrough(
|
|
146
154
|
new TransformStream({
|
|
147
155
|
transform(chunk, controller) {
|
|
@@ -149,6 +157,9 @@ function createV3BillingMiddleware(options) {
|
|
|
149
157
|
if (chunk.type === "response-metadata" && !responseId) {
|
|
150
158
|
responseId = chunk.id;
|
|
151
159
|
}
|
|
160
|
+
if (chunk.type === "source") {
|
|
161
|
+
webSearchCount++;
|
|
162
|
+
}
|
|
152
163
|
if (chunk.type === "finish") {
|
|
153
164
|
usage = chunk.usage;
|
|
154
165
|
providerMetadata = chunk.providerMetadata;
|
|
@@ -163,7 +174,8 @@ function createV3BillingMiddleware(options) {
|
|
|
163
174
|
params,
|
|
164
175
|
usage,
|
|
165
176
|
providerMetadata,
|
|
166
|
-
responseId
|
|
177
|
+
responseId,
|
|
178
|
+
webSearchCount
|
|
167
179
|
});
|
|
168
180
|
const providerMetadataWithBilling = {
|
|
169
181
|
...providerMetadata
|
|
@@ -398,8 +410,8 @@ function createNarevPriceResolver(options) {
|
|
|
398
410
|
subProvider
|
|
399
411
|
}) => {
|
|
400
412
|
const params = new URLSearchParams({ model_id: modelId });
|
|
401
|
-
if (providerId) params.set("
|
|
402
|
-
if (subProvider) params.set("
|
|
413
|
+
if (providerId) params.set("provider", providerId);
|
|
414
|
+
if (subProvider) params.set("subprovider", subProvider);
|
|
403
415
|
const url = `${apiUrl}/api/models/pricing?${params}`;
|
|
404
416
|
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
|
|
405
417
|
let data;
|
|
@@ -411,8 +423,8 @@ function createNarevPriceResolver(options) {
|
|
|
411
423
|
return void 0;
|
|
412
424
|
}
|
|
413
425
|
if (!data) return void 0;
|
|
414
|
-
const
|
|
415
|
-
const row =
|
|
426
|
+
const entry = data.find((e) => e.model_id === modelId);
|
|
427
|
+
const row = entry?.prices?.[0];
|
|
416
428
|
if (!row) return void 0;
|
|
417
429
|
return rowToModelPricing(row);
|
|
418
430
|
}
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/event/to-json-object.ts","../src/event/to-meter-metadata.ts","../src/ai-sdk/language-model-middleware/v3/language-model-v3-base-billing-middleware.ts","../src/error/ai-billing-error.ts","../src/error/extractor-error.ts","../src/error/destination-error.ts","../src/error/cost-error.ts","../src/destination/base-destination.ts","../src/destination/console-destination.ts","../src/cost/convert-cost.ts","../src/cost/op-cost.ts","../src/pricing/base-price-resolver.ts","../src/pricing/narev-price-resolver.ts","../src/pricing/object-price-resolver.ts"],"sourcesContent":["export * from './types/index.js';\nexport * from './ai-sdk/index.js';\nexport * from './destination/index.js';\nexport * from './error/index.js';\nexport * from './cost/index.js';\nexport * from './pricing/index.js';\nexport * from './event/index.js';\n","import { DefaultTags, BillingEvent } from '../types/index.js';\nimport type { JSONObject } from '@ai-sdk/provider';\n\n/**\n * Casts a billing event into a JSON object payload.\n * @param event - The billing event to cast.\n * @returns The billing event represented as a JSON object.\n */\nexport function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject {\n return event as unknown as JSONObject;\n}\n","import type {\n BillingEvent,\n DefaultTags,\n MeterMetadata,\n} from '../types/index.js';\n\n/**\n * Converts a billing event into a meter metadata object.\n * @param event - The billing event to convert.\n * @returns The meter metadata object.\n */\nexport function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(\n event: BillingEvent<TTags>,\n): MeterMetadata {\n const u = event.usage ?? {};\n\n // Initialize with required fields\n const dimensions: MeterMetadata = {\n generation_id: event.generationId,\n model_id: event.modelId,\n provider: event.provider,\n };\n\n const addOptional = <K extends keyof MeterMetadata>(\n key: K,\n value: MeterMetadata[K],\n ) => {\n if (value !== undefined && value !== null) {\n dimensions[key] = value;\n }\n };\n\n addOptional('sub_provider', u.subProvider);\n addOptional('input_tokens', u.inputTokens);\n addOptional('output_tokens', u.outputTokens);\n addOptional('total_tokens', u.totalTokens);\n addOptional('reasoning_tokens', u.reasoningTokens);\n addOptional('cache_read_tokens', u.cacheReadTokens);\n addOptional('cache_write_tokens', u.cacheWriteTokens);\n addOptional('request_count', u.requestCount);\n addOptional('raw_provider_cost', u.rawProviderCost);\n addOptional('raw_upstream_inference_cost', u.rawUpstreamInferenceCost);\n\n if (event.tags) {\n for (const [key, value] of Object.entries(event.tags)) {\n if (value == null) continue;\n dimensions[`tag_${key}`] =\n typeof value === 'object'\n ? JSON.stringify(value)\n : (value as string | number);\n }\n }\n\n return dimensions;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Usage,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3Middleware,\n SharedV3ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type {\n BaseBillingMiddlewareOptions,\n EventBuilder,\n BillingEvent,\n DefaultTags,\n} from '../../../types/index.js';\nimport { toJSONObject } from '../../../event/index.js';\n\nexport interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {\n responseId: string | undefined;\n model: LanguageModelV3;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n tags: TTags;\n}\n\n/**\n * Configuration for {@link createV3BillingMiddleware}.\n *\n * Extends {@link BaseBillingMiddlewareOptions} (`destinations`, `defaultTags`, `waitUntil`, `onError`) and\n * requires an {@link EventBuilder} to construct the {@link BillingEvent}.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n */\nexport interface BillingMiddlewareV3Options<\n TTags extends DefaultTags = DefaultTags,\n> extends BaseBillingMiddlewareOptions<TTags> {\n /** Builds a billing event from the model response data. */\n buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;\n}\n\n/**\n * Creates a billing middleware for the Language Model V3 API.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n * @param options - Billing options; see {@link BillingMiddlewareV3Options}.\n * @returns The billing middleware.\n */\nexport function createV3BillingMiddleware<\n TTags extends DefaultTags = DefaultTags,\n>(options: BillingMiddlewareV3Options<TTags>): LanguageModelV3Middleware {\n const { buildEvent, destinations, defaultTags, waitUntil, onError } = options;\n\n const processEvent = async ({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n }: {\n model: LanguageModelV3;\n params: LanguageModelV3CallOptions;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n responseId: string | undefined;\n }): Promise<BillingEvent<TTags> | null> => {\n try {\n const requestTags = params.providerOptions?.['ai-billing-tags'];\n\n const tags = {\n ...(defaultTags ?? {}),\n ...(requestTags ?? {}),\n } as TTags;\n\n const event = await buildEvent({\n responseId,\n model,\n usage,\n providerMetadata,\n tags,\n });\n\n if (event && destinations && destinations?.length > 0) {\n const dispatchDestinationsPromise = Promise.allSettled(\n destinations.map(d => Promise.resolve(d(event))),\n );\n if (waitUntil) waitUntil(dispatchDestinationsPromise);\n }\n return event;\n } catch (err) {\n if (onError) onError(err);\n else console.error('[ai-billing] Core Error:', err);\n return null;\n }\n };\n\n return {\n specificationVersion: 'v3',\n\n wrapGenerate: async ({ doGenerate, model, params }) => {\n const result: LanguageModelV3GenerateResult = await doGenerate();\n\n const event = await processEvent({\n model,\n params,\n usage: result.usage,\n providerMetadata: result.providerMetadata,\n responseId: result.response?.id,\n });\n\n const providerMetadataWithBilling = {\n ...result.providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n return {\n ...result,\n providerMetadata: providerMetadataWithBilling,\n };\n },\n\n wrapStream: async ({ doStream, model, params }) => {\n const { stream, ...rest } = await doStream();\n\n let responseId: string | undefined;\n let usage: LanguageModelV3Usage | undefined;\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n let finishChunk:\n | Extract<LanguageModelV3StreamPart, { type: 'finish' }>\n | undefined;\n\n const billedStream = stream.pipeThrough(\n new TransformStream<\n LanguageModelV3StreamPart,\n LanguageModelV3StreamPart\n >({\n transform(chunk, controller) {\n if (chunk.type === 'text-start') responseId = chunk.id;\n if (chunk.type === 'response-metadata' && !responseId) {\n responseId = chunk.id;\n }\n if (chunk.type === 'finish') {\n usage = chunk.usage;\n providerMetadata = chunk.providerMetadata;\n finishChunk = chunk;\n return; // held until flush\n }\n controller.enqueue(chunk);\n },\n async flush(controller) {\n const event = await processEvent({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n });\n\n const providerMetadataWithBilling = {\n ...providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n if (finishChunk) {\n controller.enqueue({\n ...finishChunk,\n providerMetadata: providerMetadataWithBilling,\n });\n }\n },\n }),\n );\n\n return { ...rest, stream: billedStream };\n },\n };\n}\n","const marker = 'ai-billing.error';\nconst symbol = Symbol.for(marker);\n\n/** Base error type for all ai-billing package errors. */\nexport class AIBillingError extends Error {\n private readonly [symbol] = true;\n\n readonly cause?: unknown;\n\n constructor({\n name,\n message,\n cause,\n }: {\n name: string;\n message: string;\n cause?: unknown;\n }) {\n super(message);\n this.name = name;\n this.cause = cause;\n }\n\n static isInstance(error: unknown): error is AIBillingError {\n return AIBillingError.hasMarker(error, marker);\n }\n\n protected static hasMarker(error: unknown, markerString: string): boolean {\n const markerSymbol = Symbol.for(markerString);\n return (\n error != null &&\n typeof error === 'object' &&\n markerSymbol in error &&\n typeof error[markerSymbol] === 'boolean' &&\n error[markerSymbol] === true\n );\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingExtractorError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when billing data extraction fails. */\nexport class AiBillingExtractorError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({\n message = `Failed to extract billing data.`,\n cause,\n }: {\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingExtractorError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingDestinationError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/**\n * Error raised when billing data processing fails for a destination.\n */\nexport class AiBillingDestinationError extends AIBillingError {\n private readonly [symbol] = true;\n\n /** The ID of the destination that failed to process billing data. */\n readonly destinationId?: string;\n\n constructor({\n destinationId,\n message = `Failed to process billing data for destination: '${destinationId}'.`,\n cause,\n }: {\n destinationId?: string;\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n this.destinationId = destinationId;\n }\n\n static isInstance(error: unknown): error is AiBillingDestinationError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingCostError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when a cost conversion or calculation fails. */\nexport class AiBillingCostError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({ message, cause }: { message: string; cause?: unknown }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingCostError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import type { Destination, BillingEvent, DefaultTags } from '../types/index.js';\nimport { AiBillingDestinationError } from '../error/index.js';\n\n/**\n * Creates a destination wrapper that normalizes destination handler errors.\n *\n * @param destinationId - Unique identifier for the destination.\n * @param handler - Destination implementation invoked for each billing event.\n * @returns A destination function that wraps thrown errors as AiBillingDestinationError.\n */\nexport function createDestination<TTags extends DefaultTags = DefaultTags>(\n destinationId: string,\n handler: (event: BillingEvent<TTags>) => Promise<void> | void,\n): Destination<TTags> {\n return async (event: BillingEvent<TTags>) => {\n try {\n await handler(event);\n } catch (error) {\n throw new AiBillingDestinationError({\n destinationId,\n cause: error,\n });\n }\n };\n}\n","import { createDestination } from './base-destination.js';\nimport type { DefaultTags, Destination } from '../types/index.js';\n\n/**\n * Creates a destination that logs billing events to the console.\n *\n * @returns A destination that prints each event with full depth formatting.\n */\nexport function consoleDestination<\n TTags extends DefaultTags = DefaultTags,\n>(): Destination<TTags> {\n return createDestination<TTags>('console-logger', event => {\n console.dir(event, {\n depth: null,\n colors: true,\n compact: false,\n });\n });\n}\n","import { AiBillingCostError } from '../index.js';\nimport type { Cost, CostUnit } from '../index.js';\n\nconst getNanos = (cost: Cost): number => {\n switch (cost.unit) {\n case 'base':\n return Math.round(cost.amount * 1_000_000_000);\n case 'cents':\n return Math.round(cost.amount * 10_000_000);\n case 'micros':\n return Math.round(cost.amount * 1_000);\n case 'nanos':\n return Math.round(cost.amount);\n default:\n throw new AiBillingCostError({\n message: `Failed to process cost. Unknown CostUnit: '${String(cost.unit)}'.`,\n });\n }\n};\n\n/**\n * Returns the numeric amount of `cost` expressed in `targetUnit`.\n *\n * Values are converted via an integer nanos intermediate so fractional `base` / `cents` / `micros` amounts\n * round consistently. Throws {@link AiBillingCostError} when `cost.unit` is not a known {@link CostUnit}.\n *\n * @param cost - Source {@link Cost} (amount + unit + currency).\n * @param targetUnit - Unit for the returned number (same scale as {@link Cost} amounts for that unit).\n * @returns The amount in `targetUnit`; for `nanos` this is a whole number of nanos.\n * @internal\n */\nexport const costToNumber = (cost: Cost, targetUnit: CostUnit): number => {\n const nanos = getNanos(cost);\n\n if (targetUnit === 'nanos') return nanos;\n if (targetUnit === 'micros') return nanos / 1_000;\n if (targetUnit === 'cents') return nanos / 10_000_000;\n return nanos / 1_000_000_000; // base\n};\n\n/**\n * Converts a {@link Cost} to the same amount in a different {@link CostUnit}, preserving `currency`.\n *\n * Implemented with {@link costToNumber}; the result is always a new object.\n *\n * @param cost - Source cost.\n * @param targetUnit - Desired unit for `amount` on the returned object.\n * @returns A new {@link Cost} with `unit: targetUnit` and `amount` in that unit's scale.\n * @internal\n */\nexport const convertCostUnit = (cost: Cost, targetUnit: CostUnit): Cost => {\n return {\n amount: costToNumber(cost, targetUnit),\n currency: cost.currency,\n unit: targetUnit,\n };\n};\n\n/**\n * Wraps a numeric rate as a {@link Cost} in `base` units and `USD` currency.\n *\n * Provider calculators pass per-token prices from {@link ModelPricing} here, then scale with\n * {@link multiplyCost} using token counts.\n *\n * @param amount - Rate amount in base USD units (defaults to `0` when omitted).\n * @returns A {@link Cost} with `unit: 'base'` and `currency: 'USD'`.\n * @internal\n */\nexport const rateToCost = (amount: number = 0): Cost => ({\n amount,\n unit: 'base',\n currency: 'USD',\n});\n","import { Cost } from '../types/index.js';\nimport { AiBillingCostError } from '../index.js';\nimport { convertCostUnit } from './convert-cost.js';\n\n/**\n * Scales a {@link Cost} by `multiplier` (for example token count × per-token rate).\n *\n * Converts to {@link CostUnit} `nanos`, multiplies the integer nanos amount (rounded), and returns a\n * {@link Cost} with `unit: 'nanos'` and the same `currency` as the input.\n *\n * @param cost - Base cost to scale.\n * @param multiplier - Factor applied to the nanos amount (often a non-negative token count).\n * @returns The scaled cost in nanos.\n * @internal\n */\nexport const multiplyCost = (cost: Cost, multiplier: number): Cost => {\n const nanosCost = convertCostUnit(cost, 'nanos');\n return {\n ...nanosCost,\n amount: Math.round(nanosCost.amount * multiplier),\n };\n};\n\n/**\n * Adds any number of {@link Cost} values after converting each to nanos.\n *\n * All arguments must share the same `currency`; otherwise throws {@link AiBillingCostError}. With no\n * arguments, returns a zero USD cost in nanos. With a single cost, still normalizes to nanos.\n *\n * @param costs - Costs to sum (variadic).\n * @returns The total as a {@link Cost} with `unit: 'nanos'` and the shared `currency`.\n * @internal\n */\nexport const addCosts = (...costs: Cost[]): Cost => {\n if (costs.length === 0) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const firstCost = costs[0];\n\n if (!firstCost) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const baseCurrency = firstCost.currency;\n\n const totalNanos = costs.reduce((sum, currentCost) => {\n if (currentCost.currency !== baseCurrency) {\n throw new AiBillingCostError({\n message: `Currency mismatch: Cannot add ${baseCurrency} to ${currentCost.currency}`,\n });\n }\n return sum + convertCostUnit(currentCost, 'nanos').amount;\n }, 0);\n\n return { amount: totalNanos, unit: 'nanos', currency: baseCurrency };\n};\n\n/**\n * Applies a fractional discount to `cost` in nanos: `amount * (1 - discount)`.\n *\n * If `discount` is falsy or `<= 0`, returns `cost` unchanged (same unit and amount). Otherwise converts to\n * nanos, subtracts `round(amount * discount)`, and clamps the result at zero. Typical `discount` values are\n * between `0` and `1` (for example `0.1` for 10% off).\n *\n * @param cost - Original cost.\n * @param discount - Fraction of the nanos amount to remove (not a percentage label).\n * @returns Either the original `cost` or a discounted {@link Cost} in nanos.\n * @internal\n */\nexport const applyDiscount = (cost: Cost, discount: number): Cost => {\n if (!discount || discount <= 0) return cost;\n\n const nanosCost = convertCostUnit(cost, 'nanos');\n const discountAmount = Math.round(nanosCost.amount * discount);\n\n return {\n ...nanosCost,\n amount: Math.max(0, nanosCost.amount - discountAmount),\n };\n};\n","import type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a base price resolver that wraps a handler function.\n * @param handler - The function that resolves model pricing.\n * @returns A price resolver that wraps the handler function.\n */\nexport function createBasePriceResolver(\n handler: (\n context: PriceResolverContext,\n ) => ModelPricing | undefined | Promise<ModelPricing | undefined>,\n): PriceResolver {\n return async (context: PriceResolverContext) => {\n return handler(context);\n };\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\ntype PricingRow = Record<string, number | string>;\ntype PricingMap = Record<string, PricingRow[]>;\n\nfunction rowToModelPricing(row: PricingRow): ModelPricing {\n return {\n promptTokens: row['price_prompt'] as number,\n completionTokens: row['price_completion'] as number,\n ...(row['price_request'] != null && {\n request: row['price_request'] as number,\n }),\n ...(row['price_input_cache_read'] != null && {\n inputCacheReadTokens: row['price_input_cache_read'] as number,\n }),\n ...(row['price_input_cache_write'] != null && {\n inputCacheWriteTokens: row['price_input_cache_write'] as number,\n }),\n ...(row['price_internal_reasoning'] != null && {\n internalReasoningTokens: row['price_internal_reasoning'] as number,\n }),\n ...(row['pricing_discount'] != null && {\n discount: row['pricing_discount'] as number,\n }),\n };\n}\n\n/**\n * Configuration for {@link createNarevPriceResolver}.\n */\nexport type NarevPriceResolverOptions = {\n /** API key used for authenticated pricing requests. */\n apiKey: string;\n /** Optional base URL for the Narev API. */\n apiUrl?: string;\n};\n\n/**\n * Creates a price resolver that fetches model pricing from the Narev API.\n *\n * @param options - Resolver options; see {@link NarevPriceResolverOptions}.\n * @returns A base price resolver that resolves model pricing from Narev.\n */\nexport function createNarevPriceResolver(\n options: NarevPriceResolverOptions,\n): PriceResolver {\n const { apiKey, apiUrl = 'https://narev.ai' } = options;\n\n return createBasePriceResolver(\n async ({\n modelId,\n providerId,\n subProvider,\n }: PriceResolverContext): Promise<ModelPricing | undefined> => {\n const params = new URLSearchParams({ model_id: modelId });\n if (providerId) params.set('gateway', providerId);\n if (subProvider) params.set('provider', subProvider);\n\n const url = `${apiUrl}/api/models/pricing?${params}`;\n const headers: Record<string, string> = apiKey\n ? { Authorization: `Bearer ${apiKey}` }\n : {};\n\n let data: PricingMap | null;\n try {\n const res = await fetch(url, { headers });\n if (!res.ok) return undefined;\n data = (await res.json()) as PricingMap | null;\n } catch {\n return undefined;\n }\n\n if (!data) return undefined;\n\n const rows = data[modelId];\n const row = rows?.[0];\n if (!row) return undefined;\n\n return rowToModelPricing(row);\n },\n );\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a price resolver that uses a static pricing map.\n * @param pricingMap - A mapping of model IDs to model pricing.\n * @returns A price resolver that uses the static pricing map.\n */\nexport function createObjectPriceResolver(\n pricingMap: Record<string, ModelPricing>,\n): PriceResolver {\n return createBasePriceResolver(({ modelId }: PriceResolverContext) => {\n return pricingMap[modelId];\n });\n}\n"],"mappings":"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","names":["name","marker","symbol","name","marker","symbol","name","marker","symbol"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/event/to-json-object.ts","../src/event/to-meter-metadata.ts","../src/ai-sdk/language-model-middleware/v3/language-model-v3-base-billing-middleware.ts","../src/error/ai-billing-error.ts","../src/error/extractor-error.ts","../src/error/destination-error.ts","../src/error/cost-error.ts","../src/destination/base-destination.ts","../src/destination/console-destination.ts","../src/cost/convert-cost.ts","../src/cost/op-cost.ts","../src/pricing/base-price-resolver.ts","../src/pricing/narev-price-resolver.ts","../src/pricing/object-price-resolver.ts"],"sourcesContent":["export * from './types/index.js';\nexport * from './ai-sdk/index.js';\nexport * from './destination/index.js';\nexport * from './error/index.js';\nexport * from './cost/index.js';\nexport * from './pricing/index.js';\nexport * from './event/index.js';\n","import { DefaultTags, BillingEvent } from '../types/index.js';\nimport type { JSONObject } from '@ai-sdk/provider';\n\n/**\n * Casts a billing event into a JSON object payload.\n * @param event - The billing event to cast.\n * @returns The billing event represented as a JSON object.\n */\nexport function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject {\n return event as unknown as JSONObject;\n}\n","import type {\n BillingEvent,\n DefaultTags,\n MeterMetadata,\n} from '../types/index.js';\n\n/**\n * Converts a billing event into a meter metadata object.\n * @param event - The billing event to convert.\n * @returns The meter metadata object.\n */\nexport function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(\n event: BillingEvent<TTags>,\n): MeterMetadata {\n const u = event.usage ?? {};\n\n // Initialize with required fields\n const dimensions: MeterMetadata = {\n generation_id: event.generationId,\n model_id: event.modelId,\n provider: event.provider,\n };\n\n const addOptional = <K extends keyof MeterMetadata>(\n key: K,\n value: MeterMetadata[K],\n ) => {\n if (value !== undefined && value !== null) {\n dimensions[key] = value;\n }\n };\n\n addOptional('sub_provider', u.subProvider);\n addOptional('input_tokens', u.inputTokens);\n addOptional('output_tokens', u.outputTokens);\n addOptional('total_tokens', u.totalTokens);\n addOptional('reasoning_tokens', u.reasoningTokens);\n addOptional('cache_read_tokens', u.cacheReadTokens);\n addOptional('cache_write_tokens', u.cacheWriteTokens);\n addOptional('request_count', u.requestCount);\n addOptional('web_search_count', u.webSearchCount);\n addOptional('raw_provider_cost', u.rawProviderCost);\n addOptional('raw_upstream_inference_cost', u.rawUpstreamInferenceCost);\n\n if (event.tags) {\n for (const [key, value] of Object.entries(event.tags)) {\n if (value == null) continue;\n dimensions[`tag_${key}`] =\n typeof value === 'object'\n ? JSON.stringify(value)\n : (value as string | number);\n }\n }\n\n return dimensions;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Usage,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3Middleware,\n SharedV3ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type {\n BaseBillingMiddlewareOptions,\n EventBuilder,\n BillingEvent,\n DefaultTags,\n} from '../../../types/index.js';\nimport { toJSONObject } from '../../../event/index.js';\n\nexport interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {\n responseId: string | undefined;\n model: LanguageModelV3;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n tags: TTags;\n webSearchCount: number;\n}\n\n/**\n * Configuration for {@link createV3BillingMiddleware}.\n *\n * Extends {@link BaseBillingMiddlewareOptions} (`destinations`, `defaultTags`, `waitUntil`, `onError`) and\n * requires an {@link EventBuilder} to construct the {@link BillingEvent}.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n */\nexport interface BillingMiddlewareV3Options<\n TTags extends DefaultTags = DefaultTags,\n> extends BaseBillingMiddlewareOptions<TTags> {\n /** Builds a billing event from the model response data. */\n buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;\n}\n\n/**\n * Creates a billing middleware for the Language Model V3 API.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n * @param options - Billing options; see {@link BillingMiddlewareV3Options}.\n * @returns The billing middleware.\n */\nexport function createV3BillingMiddleware<\n TTags extends DefaultTags = DefaultTags,\n>(options: BillingMiddlewareV3Options<TTags>): LanguageModelV3Middleware {\n const { buildEvent, destinations, defaultTags, waitUntil, onError } = options;\n\n const processEvent = async ({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n webSearchCount,\n }: {\n model: LanguageModelV3;\n params: LanguageModelV3CallOptions;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n responseId: string | undefined;\n webSearchCount: number;\n }): Promise<BillingEvent<TTags> | null> => {\n try {\n const requestTags = params.providerOptions?.['ai-billing-tags'];\n\n const tags = {\n ...(defaultTags ?? {}),\n ...(requestTags ?? {}),\n } as TTags;\n\n const event = await buildEvent({\n responseId,\n model,\n usage,\n providerMetadata,\n tags,\n webSearchCount,\n });\n\n if (event && destinations && destinations?.length > 0) {\n const dispatchDestinationsPromise = Promise.allSettled(\n destinations.map(d => Promise.resolve(d(event))),\n );\n if (waitUntil) waitUntil(dispatchDestinationsPromise);\n }\n return event;\n } catch (err) {\n if (onError) onError(err);\n else console.error('[ai-billing] Core Error:', err);\n return null;\n }\n };\n\n return {\n specificationVersion: 'v3',\n\n wrapGenerate: async ({ doGenerate, model, params }) => {\n const result: LanguageModelV3GenerateResult = await doGenerate();\n\n const webSearchCount = result.content.filter(\n c => c.type === 'source',\n ).length;\n\n const event = await processEvent({\n model,\n params,\n usage: result.usage,\n providerMetadata: result.providerMetadata,\n responseId: result.response?.id,\n webSearchCount,\n });\n\n const providerMetadataWithBilling = {\n ...result.providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n return {\n ...result,\n providerMetadata: providerMetadataWithBilling,\n };\n },\n\n wrapStream: async ({ doStream, model, params }) => {\n const { stream, ...rest } = await doStream();\n\n let responseId: string | undefined;\n let usage: LanguageModelV3Usage | undefined;\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n let finishChunk:\n | Extract<LanguageModelV3StreamPart, { type: 'finish' }>\n | undefined;\n let webSearchCount = 0;\n\n const billedStream = stream.pipeThrough(\n new TransformStream<\n LanguageModelV3StreamPart,\n LanguageModelV3StreamPart\n >({\n transform(chunk, controller) {\n if (chunk.type === 'text-start') responseId = chunk.id;\n if (chunk.type === 'response-metadata' && !responseId) {\n responseId = chunk.id;\n }\n if (chunk.type === 'source') {\n webSearchCount++;\n }\n if (chunk.type === 'finish') {\n usage = chunk.usage;\n providerMetadata = chunk.providerMetadata;\n finishChunk = chunk;\n return; // held until flush\n }\n controller.enqueue(chunk);\n },\n async flush(controller) {\n const event = await processEvent({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n webSearchCount,\n });\n\n const providerMetadataWithBilling = {\n ...providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n if (finishChunk) {\n controller.enqueue({\n ...finishChunk,\n providerMetadata: providerMetadataWithBilling,\n });\n }\n },\n }),\n );\n\n return { ...rest, stream: billedStream };\n },\n };\n}\n","const marker = 'ai-billing.error';\nconst symbol = Symbol.for(marker);\n\n/** Base error type for all ai-billing package errors. */\nexport class AIBillingError extends Error {\n private readonly [symbol] = true;\n\n readonly cause?: unknown;\n\n constructor({\n name,\n message,\n cause,\n }: {\n name: string;\n message: string;\n cause?: unknown;\n }) {\n super(message);\n this.name = name;\n this.cause = cause;\n }\n\n static isInstance(error: unknown): error is AIBillingError {\n return AIBillingError.hasMarker(error, marker);\n }\n\n protected static hasMarker(error: unknown, markerString: string): boolean {\n const markerSymbol = Symbol.for(markerString);\n return (\n error != null &&\n typeof error === 'object' &&\n markerSymbol in error &&\n typeof error[markerSymbol] === 'boolean' &&\n error[markerSymbol] === true\n );\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingExtractorError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when billing data extraction fails. */\nexport class AiBillingExtractorError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({\n message = `Failed to extract billing data.`,\n cause,\n }: {\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingExtractorError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingDestinationError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/**\n * Error raised when billing data processing fails for a destination.\n */\nexport class AiBillingDestinationError extends AIBillingError {\n private readonly [symbol] = true;\n\n /** The ID of the destination that failed to process billing data. */\n readonly destinationId?: string;\n\n constructor({\n destinationId,\n message = `Failed to process billing data for destination: '${destinationId}'.`,\n cause,\n }: {\n destinationId?: string;\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n this.destinationId = destinationId;\n }\n\n static isInstance(error: unknown): error is AiBillingDestinationError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingCostError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when a cost conversion or calculation fails. */\nexport class AiBillingCostError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({ message, cause }: { message: string; cause?: unknown }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingCostError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import type { Destination, BillingEvent, DefaultTags } from '../types/index.js';\nimport { AiBillingDestinationError } from '../error/index.js';\n\n/**\n * Creates a destination wrapper that normalizes destination handler errors.\n *\n * @param destinationId - Unique identifier for the destination.\n * @param handler - Destination implementation invoked for each billing event.\n * @returns A destination function that wraps thrown errors as AiBillingDestinationError.\n */\nexport function createDestination<TTags extends DefaultTags = DefaultTags>(\n destinationId: string,\n handler: (event: BillingEvent<TTags>) => Promise<void> | void,\n): Destination<TTags> {\n return async (event: BillingEvent<TTags>) => {\n try {\n await handler(event);\n } catch (error) {\n throw new AiBillingDestinationError({\n destinationId,\n cause: error,\n });\n }\n };\n}\n","import { createDestination } from './base-destination.js';\nimport type { DefaultTags, Destination } from '../types/index.js';\n\n/**\n * Creates a destination that logs billing events to the console.\n *\n * @returns A destination that prints each event with full depth formatting.\n */\nexport function consoleDestination<\n TTags extends DefaultTags = DefaultTags,\n>(): Destination<TTags> {\n return createDestination<TTags>('console-logger', event => {\n console.dir(event, {\n depth: null,\n colors: true,\n compact: false,\n });\n });\n}\n","import { AiBillingCostError } from '../index.js';\nimport type { Cost, CostUnit } from '../index.js';\n\nconst getNanos = (cost: Cost): number => {\n switch (cost.unit) {\n case 'base':\n return Math.round(cost.amount * 1_000_000_000);\n case 'cents':\n return Math.round(cost.amount * 10_000_000);\n case 'micros':\n return Math.round(cost.amount * 1_000);\n case 'nanos':\n return Math.round(cost.amount);\n default:\n throw new AiBillingCostError({\n message: `Failed to process cost. Unknown CostUnit: '${String(cost.unit)}'.`,\n });\n }\n};\n\n/**\n * Returns the numeric amount of `cost` expressed in `targetUnit`.\n *\n * Values are converted via an integer nanos intermediate so fractional `base` / `cents` / `micros` amounts\n * round consistently. Throws {@link AiBillingCostError} when `cost.unit` is not a known {@link CostUnit}.\n *\n * @param cost - Source {@link Cost} (amount + unit + currency).\n * @param targetUnit - Unit for the returned number (same scale as {@link Cost} amounts for that unit).\n * @returns The amount in `targetUnit`; for `nanos` this is a whole number of nanos.\n * @internal\n */\nexport const costToNumber = (cost: Cost, targetUnit: CostUnit): number => {\n const nanos = getNanos(cost);\n\n if (targetUnit === 'nanos') return nanos;\n if (targetUnit === 'micros') return nanos / 1_000;\n if (targetUnit === 'cents') return nanos / 10_000_000;\n return nanos / 1_000_000_000; // base\n};\n\n/**\n * Converts a {@link Cost} to the same amount in a different {@link CostUnit}, preserving `currency`.\n *\n * Implemented with {@link costToNumber}; the result is always a new object.\n *\n * @param cost - Source cost.\n * @param targetUnit - Desired unit for `amount` on the returned object.\n * @returns A new {@link Cost} with `unit: targetUnit` and `amount` in that unit's scale.\n * @internal\n */\nexport const convertCostUnit = (cost: Cost, targetUnit: CostUnit): Cost => {\n return {\n amount: costToNumber(cost, targetUnit),\n currency: cost.currency,\n unit: targetUnit,\n };\n};\n\n/**\n * Wraps a numeric rate as a {@link Cost} in `base` units and `USD` currency.\n *\n * Provider calculators pass per-token prices from {@link ModelPricing} here, then scale with\n * {@link multiplyCost} using token counts.\n *\n * @param amount - Rate amount in base USD units (defaults to `0` when omitted).\n * @returns A {@link Cost} with `unit: 'base'` and `currency: 'USD'`.\n * @internal\n */\nexport const rateToCost = (amount: number = 0): Cost => ({\n amount,\n unit: 'base',\n currency: 'USD',\n});\n","import { Cost } from '../types/index.js';\nimport { AiBillingCostError } from '../index.js';\nimport { convertCostUnit } from './convert-cost.js';\n\n/**\n * Scales a {@link Cost} by `multiplier` (for example token count × per-token rate).\n *\n * Converts to {@link CostUnit} `nanos`, multiplies the integer nanos amount (rounded), and returns a\n * {@link Cost} with `unit: 'nanos'` and the same `currency` as the input.\n *\n * @param cost - Base cost to scale.\n * @param multiplier - Factor applied to the nanos amount (often a non-negative token count).\n * @returns The scaled cost in nanos.\n * @internal\n */\nexport const multiplyCost = (cost: Cost, multiplier: number): Cost => {\n const nanosCost = convertCostUnit(cost, 'nanos');\n return {\n ...nanosCost,\n amount: Math.round(nanosCost.amount * multiplier),\n };\n};\n\n/**\n * Adds any number of {@link Cost} values after converting each to nanos.\n *\n * All arguments must share the same `currency`; otherwise throws {@link AiBillingCostError}. With no\n * arguments, returns a zero USD cost in nanos. With a single cost, still normalizes to nanos.\n *\n * @param costs - Costs to sum (variadic).\n * @returns The total as a {@link Cost} with `unit: 'nanos'` and the shared `currency`.\n * @internal\n */\nexport const addCosts = (...costs: Cost[]): Cost => {\n if (costs.length === 0) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const firstCost = costs[0];\n\n if (!firstCost) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const baseCurrency = firstCost.currency;\n\n const totalNanos = costs.reduce((sum, currentCost) => {\n if (currentCost.currency !== baseCurrency) {\n throw new AiBillingCostError({\n message: `Currency mismatch: Cannot add ${baseCurrency} to ${currentCost.currency}`,\n });\n }\n return sum + convertCostUnit(currentCost, 'nanos').amount;\n }, 0);\n\n return { amount: totalNanos, unit: 'nanos', currency: baseCurrency };\n};\n\n/**\n * Applies a fractional discount to `cost` in nanos: `amount * (1 - discount)`.\n *\n * If `discount` is falsy or `<= 0`, returns `cost` unchanged (same unit and amount). Otherwise converts to\n * nanos, subtracts `round(amount * discount)`, and clamps the result at zero. Typical `discount` values are\n * between `0` and `1` (for example `0.1` for 10% off).\n *\n * @param cost - Original cost.\n * @param discount - Fraction of the nanos amount to remove (not a percentage label).\n * @returns Either the original `cost` or a discounted {@link Cost} in nanos.\n * @internal\n */\nexport const applyDiscount = (cost: Cost, discount: number): Cost => {\n if (!discount || discount <= 0) return cost;\n\n const nanosCost = convertCostUnit(cost, 'nanos');\n const discountAmount = Math.round(nanosCost.amount * discount);\n\n return {\n ...nanosCost,\n amount: Math.max(0, nanosCost.amount - discountAmount),\n };\n};\n","import type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a base price resolver that wraps a handler function.\n * @param handler - The function that resolves model pricing.\n * @returns A price resolver that wraps the handler function.\n */\nexport function createBasePriceResolver(\n handler: (\n context: PriceResolverContext,\n ) => ModelPricing | undefined | Promise<ModelPricing | undefined>,\n): PriceResolver {\n return async (context: PriceResolverContext) => {\n return handler(context);\n };\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\ntype PricingRow = Record<string, number | string>;\ntype PricingEntry = { model_id: string; prices: PricingRow[] };\ntype PricingResponse = PricingEntry[];\n\nfunction rowToModelPricing(row: PricingRow): ModelPricing {\n return {\n promptTokens: row['price_prompt'] as number,\n completionTokens: row['price_completion'] as number,\n ...(row['price_request'] != null && {\n request: row['price_request'] as number,\n }),\n ...(row['price_input_cache_read'] != null && {\n inputCacheReadTokens: row['price_input_cache_read'] as number,\n }),\n ...(row['price_input_cache_write'] != null && {\n inputCacheWriteTokens: row['price_input_cache_write'] as number,\n }),\n ...(row['price_internal_reasoning'] != null && {\n internalReasoningTokens: row['price_internal_reasoning'] as number,\n }),\n ...(row['pricing_discount'] != null && {\n discount: row['pricing_discount'] as number,\n }),\n };\n}\n\n/**\n * Configuration for {@link createNarevPriceResolver}.\n */\nexport type NarevPriceResolverOptions = {\n /** API key used for authenticated pricing requests. */\n apiKey: string;\n /** Optional base URL for the Narev API. */\n apiUrl?: string;\n};\n\n/**\n * Creates a price resolver that fetches model pricing from the Narev API.\n *\n * @param options - Resolver options; see {@link NarevPriceResolverOptions}.\n * @returns A base price resolver that resolves model pricing from Narev.\n */\nexport function createNarevPriceResolver(\n options: NarevPriceResolverOptions,\n): PriceResolver {\n const { apiKey, apiUrl = 'https://narev.ai' } = options;\n\n return createBasePriceResolver(\n async ({\n modelId,\n providerId,\n subProvider,\n }: PriceResolverContext): Promise<ModelPricing | undefined> => {\n const params = new URLSearchParams({ model_id: modelId });\n if (providerId) params.set('provider', providerId);\n if (subProvider) params.set('subprovider', subProvider);\n\n const url = `${apiUrl}/api/models/pricing?${params}`;\n const headers: Record<string, string> = apiKey\n ? { Authorization: `Bearer ${apiKey}` }\n : {};\n\n let data: PricingResponse | null;\n try {\n const res = await fetch(url, { headers });\n if (!res.ok) return undefined;\n data = (await res.json()) as PricingResponse | null;\n } catch {\n return undefined;\n }\n\n if (!data) return undefined;\n\n const entry = data.find(e => e.model_id === modelId);\n const row = entry?.prices?.[0];\n if (!row) return undefined;\n\n return rowToModelPricing(row);\n },\n );\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a price resolver that uses a static pricing map.\n * @param pricingMap - A mapping of model IDs to model pricing.\n * @returns A price resolver that uses the static pricing map.\n */\nexport function createObjectPriceResolver(\n pricingMap: Record<string, ModelPricing>,\n): PriceResolver {\n return createBasePriceResolver(({ modelId }: PriceResolverContext) => {\n return pricingMap[modelId];\n });\n}\n"],"mappings":"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","names":["name","marker","symbol","name","marker","symbol","name","marker","symbol"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -11,6 +11,7 @@ interface Usage {
|
|
|
11
11
|
readonly cacheReadTokens?: number;
|
|
12
12
|
readonly cacheWriteTokens?: number;
|
|
13
13
|
readonly requestCount?: number;
|
|
14
|
+
readonly webSearchCount?: number;
|
|
14
15
|
readonly rawProviderCost?: number;
|
|
15
16
|
readonly rawUpstreamInferenceCost?: number;
|
|
16
17
|
}
|
|
@@ -46,6 +47,27 @@ interface Cost {
|
|
|
46
47
|
readonly unit: CostUnit;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Token usage passed into a provider cost calculation function.
|
|
52
|
+
*/
|
|
53
|
+
interface CostInputs {
|
|
54
|
+
/** Number of prompt (input) tokens. */
|
|
55
|
+
promptTokens: number;
|
|
56
|
+
/** Number of completion (output) tokens. */
|
|
57
|
+
completionTokens: number;
|
|
58
|
+
/** Number of tokens served from the prompt cache. */
|
|
59
|
+
cacheReadTokens: number;
|
|
60
|
+
/** Number of tokens written to the prompt cache. */
|
|
61
|
+
cacheWriteTokens: number;
|
|
62
|
+
/**
|
|
63
|
+
* Number of reasoning tokens (priced with `internalReasoningTokens` when present in `ModelPricing`,
|
|
64
|
+
* otherwise at the completion rate).
|
|
65
|
+
*/
|
|
66
|
+
reasoningTokens: number;
|
|
67
|
+
/** Number of web search calls (each billed at `pricing.webSearch` when set). */
|
|
68
|
+
webSearchCount?: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
49
71
|
interface ModelPricing {
|
|
50
72
|
promptTokens: number;
|
|
51
73
|
completionTokens: number;
|
|
@@ -53,6 +75,7 @@ interface ModelPricing {
|
|
|
53
75
|
inputCacheWriteTokens?: number;
|
|
54
76
|
internalReasoningTokens?: number;
|
|
55
77
|
request?: number;
|
|
78
|
+
webSearch?: number;
|
|
56
79
|
discount?: number;
|
|
57
80
|
}
|
|
58
81
|
type PriceResolverContext = {
|
|
@@ -75,6 +98,7 @@ interface MeterMetadata {
|
|
|
75
98
|
cache_read_tokens?: number;
|
|
76
99
|
cache_write_tokens?: number;
|
|
77
100
|
request_count?: number;
|
|
101
|
+
web_search_count?: number;
|
|
78
102
|
raw_provider_cost?: number;
|
|
79
103
|
raw_upstream_inference_cost?: number;
|
|
80
104
|
[key: string]: string | number | undefined;
|
|
@@ -86,6 +110,7 @@ interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {
|
|
|
86
110
|
usage: LanguageModelV3Usage | undefined;
|
|
87
111
|
providerMetadata: SharedV3ProviderMetadata | undefined;
|
|
88
112
|
tags: TTags;
|
|
113
|
+
webSearchCount: number;
|
|
89
114
|
}
|
|
90
115
|
/**
|
|
91
116
|
* Configuration for {@link createV3BillingMiddleware}.
|
|
@@ -293,4 +318,4 @@ declare function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject;
|
|
|
293
318
|
*/
|
|
294
319
|
declare function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(event: BillingEvent<TTags>): MeterMetadata;
|
|
295
320
|
|
|
296
|
-
export { AIBillingError, AiBillingCostError, AiBillingDestinationError, AiBillingExtractorError, type BaseBillingMiddlewareOptions, type BillingEvent, type BillingMiddlewareV3Options, type BuildV3EventPayload, type Cost, type CostUnit, type DefaultTags, type Destination, type EventBuilder, type MeterMetadata, type ModelPricing, type NarevPriceResolverOptions, type PriceResolver, type PriceResolverContext, type Usage, addCosts, applyDiscount, buildMeterMetadata, consoleDestination, convertCostUnit, costToNumber, createBasePriceResolver, createDestination, createNarevPriceResolver, createObjectPriceResolver, createV3BillingMiddleware, multiplyCost, rateToCost, toJSONObject };
|
|
321
|
+
export { AIBillingError, AiBillingCostError, AiBillingDestinationError, AiBillingExtractorError, type BaseBillingMiddlewareOptions, type BillingEvent, type BillingMiddlewareV3Options, type BuildV3EventPayload, type Cost, type CostInputs, type CostUnit, type DefaultTags, type Destination, type EventBuilder, type MeterMetadata, type ModelPricing, type NarevPriceResolverOptions, type PriceResolver, type PriceResolverContext, type Usage, addCosts, applyDiscount, buildMeterMetadata, consoleDestination, convertCostUnit, costToNumber, createBasePriceResolver, createDestination, createNarevPriceResolver, createObjectPriceResolver, createV3BillingMiddleware, multiplyCost, rateToCost, toJSONObject };
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ interface Usage {
|
|
|
11
11
|
readonly cacheReadTokens?: number;
|
|
12
12
|
readonly cacheWriteTokens?: number;
|
|
13
13
|
readonly requestCount?: number;
|
|
14
|
+
readonly webSearchCount?: number;
|
|
14
15
|
readonly rawProviderCost?: number;
|
|
15
16
|
readonly rawUpstreamInferenceCost?: number;
|
|
16
17
|
}
|
|
@@ -46,6 +47,27 @@ interface Cost {
|
|
|
46
47
|
readonly unit: CostUnit;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
/**
|
|
51
|
+
* Token usage passed into a provider cost calculation function.
|
|
52
|
+
*/
|
|
53
|
+
interface CostInputs {
|
|
54
|
+
/** Number of prompt (input) tokens. */
|
|
55
|
+
promptTokens: number;
|
|
56
|
+
/** Number of completion (output) tokens. */
|
|
57
|
+
completionTokens: number;
|
|
58
|
+
/** Number of tokens served from the prompt cache. */
|
|
59
|
+
cacheReadTokens: number;
|
|
60
|
+
/** Number of tokens written to the prompt cache. */
|
|
61
|
+
cacheWriteTokens: number;
|
|
62
|
+
/**
|
|
63
|
+
* Number of reasoning tokens (priced with `internalReasoningTokens` when present in `ModelPricing`,
|
|
64
|
+
* otherwise at the completion rate).
|
|
65
|
+
*/
|
|
66
|
+
reasoningTokens: number;
|
|
67
|
+
/** Number of web search calls (each billed at `pricing.webSearch` when set). */
|
|
68
|
+
webSearchCount?: number;
|
|
69
|
+
}
|
|
70
|
+
|
|
49
71
|
interface ModelPricing {
|
|
50
72
|
promptTokens: number;
|
|
51
73
|
completionTokens: number;
|
|
@@ -53,6 +75,7 @@ interface ModelPricing {
|
|
|
53
75
|
inputCacheWriteTokens?: number;
|
|
54
76
|
internalReasoningTokens?: number;
|
|
55
77
|
request?: number;
|
|
78
|
+
webSearch?: number;
|
|
56
79
|
discount?: number;
|
|
57
80
|
}
|
|
58
81
|
type PriceResolverContext = {
|
|
@@ -75,6 +98,7 @@ interface MeterMetadata {
|
|
|
75
98
|
cache_read_tokens?: number;
|
|
76
99
|
cache_write_tokens?: number;
|
|
77
100
|
request_count?: number;
|
|
101
|
+
web_search_count?: number;
|
|
78
102
|
raw_provider_cost?: number;
|
|
79
103
|
raw_upstream_inference_cost?: number;
|
|
80
104
|
[key: string]: string | number | undefined;
|
|
@@ -86,6 +110,7 @@ interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {
|
|
|
86
110
|
usage: LanguageModelV3Usage | undefined;
|
|
87
111
|
providerMetadata: SharedV3ProviderMetadata | undefined;
|
|
88
112
|
tags: TTags;
|
|
113
|
+
webSearchCount: number;
|
|
89
114
|
}
|
|
90
115
|
/**
|
|
91
116
|
* Configuration for {@link createV3BillingMiddleware}.
|
|
@@ -293,4 +318,4 @@ declare function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject;
|
|
|
293
318
|
*/
|
|
294
319
|
declare function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(event: BillingEvent<TTags>): MeterMetadata;
|
|
295
320
|
|
|
296
|
-
export { AIBillingError, AiBillingCostError, AiBillingDestinationError, AiBillingExtractorError, type BaseBillingMiddlewareOptions, type BillingEvent, type BillingMiddlewareV3Options, type BuildV3EventPayload, type Cost, type CostUnit, type DefaultTags, type Destination, type EventBuilder, type MeterMetadata, type ModelPricing, type NarevPriceResolverOptions, type PriceResolver, type PriceResolverContext, type Usage, addCosts, applyDiscount, buildMeterMetadata, consoleDestination, convertCostUnit, costToNumber, createBasePriceResolver, createDestination, createNarevPriceResolver, createObjectPriceResolver, createV3BillingMiddleware, multiplyCost, rateToCost, toJSONObject };
|
|
321
|
+
export { AIBillingError, AiBillingCostError, AiBillingDestinationError, AiBillingExtractorError, type BaseBillingMiddlewareOptions, type BillingEvent, type BillingMiddlewareV3Options, type BuildV3EventPayload, type Cost, type CostInputs, type CostUnit, type DefaultTags, type Destination, type EventBuilder, type MeterMetadata, type ModelPricing, type NarevPriceResolverOptions, type PriceResolver, type PriceResolverContext, type Usage, addCosts, applyDiscount, buildMeterMetadata, consoleDestination, convertCostUnit, costToNumber, createBasePriceResolver, createDestination, createNarevPriceResolver, createObjectPriceResolver, createV3BillingMiddleware, multiplyCost, rateToCost, toJSONObject };
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,7 @@ function buildMeterMetadata(event) {
|
|
|
24
24
|
addOptional("cache_read_tokens", u.cacheReadTokens);
|
|
25
25
|
addOptional("cache_write_tokens", u.cacheWriteTokens);
|
|
26
26
|
addOptional("request_count", u.requestCount);
|
|
27
|
+
addOptional("web_search_count", u.webSearchCount);
|
|
27
28
|
addOptional("raw_provider_cost", u.rawProviderCost);
|
|
28
29
|
addOptional("raw_upstream_inference_cost", u.rawUpstreamInferenceCost);
|
|
29
30
|
if (event.tags) {
|
|
@@ -43,7 +44,8 @@ function createV3BillingMiddleware(options) {
|
|
|
43
44
|
params,
|
|
44
45
|
usage,
|
|
45
46
|
providerMetadata,
|
|
46
|
-
responseId
|
|
47
|
+
responseId,
|
|
48
|
+
webSearchCount
|
|
47
49
|
}) => {
|
|
48
50
|
try {
|
|
49
51
|
const requestTags = params.providerOptions?.["ai-billing-tags"];
|
|
@@ -56,7 +58,8 @@ function createV3BillingMiddleware(options) {
|
|
|
56
58
|
model,
|
|
57
59
|
usage,
|
|
58
60
|
providerMetadata,
|
|
59
|
-
tags
|
|
61
|
+
tags,
|
|
62
|
+
webSearchCount
|
|
60
63
|
});
|
|
61
64
|
if (event && destinations && destinations?.length > 0) {
|
|
62
65
|
const dispatchDestinationsPromise = Promise.allSettled(
|
|
@@ -75,12 +78,16 @@ function createV3BillingMiddleware(options) {
|
|
|
75
78
|
specificationVersion: "v3",
|
|
76
79
|
wrapGenerate: async ({ doGenerate, model, params }) => {
|
|
77
80
|
const result = await doGenerate();
|
|
81
|
+
const webSearchCount = result.content.filter(
|
|
82
|
+
(c) => c.type === "source"
|
|
83
|
+
).length;
|
|
78
84
|
const event = await processEvent({
|
|
79
85
|
model,
|
|
80
86
|
params,
|
|
81
87
|
usage: result.usage,
|
|
82
88
|
providerMetadata: result.providerMetadata,
|
|
83
|
-
responseId: result.response?.id
|
|
89
|
+
responseId: result.response?.id,
|
|
90
|
+
webSearchCount
|
|
84
91
|
});
|
|
85
92
|
const providerMetadataWithBilling = {
|
|
86
93
|
...result.providerMetadata
|
|
@@ -99,6 +106,7 @@ function createV3BillingMiddleware(options) {
|
|
|
99
106
|
let usage;
|
|
100
107
|
let providerMetadata;
|
|
101
108
|
let finishChunk;
|
|
109
|
+
let webSearchCount = 0;
|
|
102
110
|
const billedStream = stream.pipeThrough(
|
|
103
111
|
new TransformStream({
|
|
104
112
|
transform(chunk, controller) {
|
|
@@ -106,6 +114,9 @@ function createV3BillingMiddleware(options) {
|
|
|
106
114
|
if (chunk.type === "response-metadata" && !responseId) {
|
|
107
115
|
responseId = chunk.id;
|
|
108
116
|
}
|
|
117
|
+
if (chunk.type === "source") {
|
|
118
|
+
webSearchCount++;
|
|
119
|
+
}
|
|
109
120
|
if (chunk.type === "finish") {
|
|
110
121
|
usage = chunk.usage;
|
|
111
122
|
providerMetadata = chunk.providerMetadata;
|
|
@@ -120,7 +131,8 @@ function createV3BillingMiddleware(options) {
|
|
|
120
131
|
params,
|
|
121
132
|
usage,
|
|
122
133
|
providerMetadata,
|
|
123
|
-
responseId
|
|
134
|
+
responseId,
|
|
135
|
+
webSearchCount
|
|
124
136
|
});
|
|
125
137
|
const providerMetadataWithBilling = {
|
|
126
138
|
...providerMetadata
|
|
@@ -355,8 +367,8 @@ function createNarevPriceResolver(options) {
|
|
|
355
367
|
subProvider
|
|
356
368
|
}) => {
|
|
357
369
|
const params = new URLSearchParams({ model_id: modelId });
|
|
358
|
-
if (providerId) params.set("
|
|
359
|
-
if (subProvider) params.set("
|
|
370
|
+
if (providerId) params.set("provider", providerId);
|
|
371
|
+
if (subProvider) params.set("subprovider", subProvider);
|
|
360
372
|
const url = `${apiUrl}/api/models/pricing?${params}`;
|
|
361
373
|
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
|
|
362
374
|
let data;
|
|
@@ -368,8 +380,8 @@ function createNarevPriceResolver(options) {
|
|
|
368
380
|
return void 0;
|
|
369
381
|
}
|
|
370
382
|
if (!data) return void 0;
|
|
371
|
-
const
|
|
372
|
-
const row =
|
|
383
|
+
const entry = data.find((e) => e.model_id === modelId);
|
|
384
|
+
const row = entry?.prices?.[0];
|
|
373
385
|
if (!row) return void 0;
|
|
374
386
|
return rowToModelPricing(row);
|
|
375
387
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event/to-json-object.ts","../src/event/to-meter-metadata.ts","../src/ai-sdk/language-model-middleware/v3/language-model-v3-base-billing-middleware.ts","../src/error/ai-billing-error.ts","../src/error/extractor-error.ts","../src/error/destination-error.ts","../src/error/cost-error.ts","../src/destination/base-destination.ts","../src/destination/console-destination.ts","../src/cost/convert-cost.ts","../src/cost/op-cost.ts","../src/pricing/base-price-resolver.ts","../src/pricing/narev-price-resolver.ts","../src/pricing/object-price-resolver.ts"],"sourcesContent":["import { DefaultTags, BillingEvent } from '../types/index.js';\nimport type { JSONObject } from '@ai-sdk/provider';\n\n/**\n * Casts a billing event into a JSON object payload.\n * @param event - The billing event to cast.\n * @returns The billing event represented as a JSON object.\n */\nexport function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject {\n return event as unknown as JSONObject;\n}\n","import type {\n BillingEvent,\n DefaultTags,\n MeterMetadata,\n} from '../types/index.js';\n\n/**\n * Converts a billing event into a meter metadata object.\n * @param event - The billing event to convert.\n * @returns The meter metadata object.\n */\nexport function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(\n event: BillingEvent<TTags>,\n): MeterMetadata {\n const u = event.usage ?? {};\n\n // Initialize with required fields\n const dimensions: MeterMetadata = {\n generation_id: event.generationId,\n model_id: event.modelId,\n provider: event.provider,\n };\n\n const addOptional = <K extends keyof MeterMetadata>(\n key: K,\n value: MeterMetadata[K],\n ) => {\n if (value !== undefined && value !== null) {\n dimensions[key] = value;\n }\n };\n\n addOptional('sub_provider', u.subProvider);\n addOptional('input_tokens', u.inputTokens);\n addOptional('output_tokens', u.outputTokens);\n addOptional('total_tokens', u.totalTokens);\n addOptional('reasoning_tokens', u.reasoningTokens);\n addOptional('cache_read_tokens', u.cacheReadTokens);\n addOptional('cache_write_tokens', u.cacheWriteTokens);\n addOptional('request_count', u.requestCount);\n addOptional('raw_provider_cost', u.rawProviderCost);\n addOptional('raw_upstream_inference_cost', u.rawUpstreamInferenceCost);\n\n if (event.tags) {\n for (const [key, value] of Object.entries(event.tags)) {\n if (value == null) continue;\n dimensions[`tag_${key}`] =\n typeof value === 'object'\n ? JSON.stringify(value)\n : (value as string | number);\n }\n }\n\n return dimensions;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Usage,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3Middleware,\n SharedV3ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type {\n BaseBillingMiddlewareOptions,\n EventBuilder,\n BillingEvent,\n DefaultTags,\n} from '../../../types/index.js';\nimport { toJSONObject } from '../../../event/index.js';\n\nexport interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {\n responseId: string | undefined;\n model: LanguageModelV3;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n tags: TTags;\n}\n\n/**\n * Configuration for {@link createV3BillingMiddleware}.\n *\n * Extends {@link BaseBillingMiddlewareOptions} (`destinations`, `defaultTags`, `waitUntil`, `onError`) and\n * requires an {@link EventBuilder} to construct the {@link BillingEvent}.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n */\nexport interface BillingMiddlewareV3Options<\n TTags extends DefaultTags = DefaultTags,\n> extends BaseBillingMiddlewareOptions<TTags> {\n /** Builds a billing event from the model response data. */\n buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;\n}\n\n/**\n * Creates a billing middleware for the Language Model V3 API.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n * @param options - Billing options; see {@link BillingMiddlewareV3Options}.\n * @returns The billing middleware.\n */\nexport function createV3BillingMiddleware<\n TTags extends DefaultTags = DefaultTags,\n>(options: BillingMiddlewareV3Options<TTags>): LanguageModelV3Middleware {\n const { buildEvent, destinations, defaultTags, waitUntil, onError } = options;\n\n const processEvent = async ({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n }: {\n model: LanguageModelV3;\n params: LanguageModelV3CallOptions;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n responseId: string | undefined;\n }): Promise<BillingEvent<TTags> | null> => {\n try {\n const requestTags = params.providerOptions?.['ai-billing-tags'];\n\n const tags = {\n ...(defaultTags ?? {}),\n ...(requestTags ?? {}),\n } as TTags;\n\n const event = await buildEvent({\n responseId,\n model,\n usage,\n providerMetadata,\n tags,\n });\n\n if (event && destinations && destinations?.length > 0) {\n const dispatchDestinationsPromise = Promise.allSettled(\n destinations.map(d => Promise.resolve(d(event))),\n );\n if (waitUntil) waitUntil(dispatchDestinationsPromise);\n }\n return event;\n } catch (err) {\n if (onError) onError(err);\n else console.error('[ai-billing] Core Error:', err);\n return null;\n }\n };\n\n return {\n specificationVersion: 'v3',\n\n wrapGenerate: async ({ doGenerate, model, params }) => {\n const result: LanguageModelV3GenerateResult = await doGenerate();\n\n const event = await processEvent({\n model,\n params,\n usage: result.usage,\n providerMetadata: result.providerMetadata,\n responseId: result.response?.id,\n });\n\n const providerMetadataWithBilling = {\n ...result.providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n return {\n ...result,\n providerMetadata: providerMetadataWithBilling,\n };\n },\n\n wrapStream: async ({ doStream, model, params }) => {\n const { stream, ...rest } = await doStream();\n\n let responseId: string | undefined;\n let usage: LanguageModelV3Usage | undefined;\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n let finishChunk:\n | Extract<LanguageModelV3StreamPart, { type: 'finish' }>\n | undefined;\n\n const billedStream = stream.pipeThrough(\n new TransformStream<\n LanguageModelV3StreamPart,\n LanguageModelV3StreamPart\n >({\n transform(chunk, controller) {\n if (chunk.type === 'text-start') responseId = chunk.id;\n if (chunk.type === 'response-metadata' && !responseId) {\n responseId = chunk.id;\n }\n if (chunk.type === 'finish') {\n usage = chunk.usage;\n providerMetadata = chunk.providerMetadata;\n finishChunk = chunk;\n return; // held until flush\n }\n controller.enqueue(chunk);\n },\n async flush(controller) {\n const event = await processEvent({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n });\n\n const providerMetadataWithBilling = {\n ...providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n if (finishChunk) {\n controller.enqueue({\n ...finishChunk,\n providerMetadata: providerMetadataWithBilling,\n });\n }\n },\n }),\n );\n\n return { ...rest, stream: billedStream };\n },\n };\n}\n","const marker = 'ai-billing.error';\nconst symbol = Symbol.for(marker);\n\n/** Base error type for all ai-billing package errors. */\nexport class AIBillingError extends Error {\n private readonly [symbol] = true;\n\n readonly cause?: unknown;\n\n constructor({\n name,\n message,\n cause,\n }: {\n name: string;\n message: string;\n cause?: unknown;\n }) {\n super(message);\n this.name = name;\n this.cause = cause;\n }\n\n static isInstance(error: unknown): error is AIBillingError {\n return AIBillingError.hasMarker(error, marker);\n }\n\n protected static hasMarker(error: unknown, markerString: string): boolean {\n const markerSymbol = Symbol.for(markerString);\n return (\n error != null &&\n typeof error === 'object' &&\n markerSymbol in error &&\n typeof error[markerSymbol] === 'boolean' &&\n error[markerSymbol] === true\n );\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingExtractorError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when billing data extraction fails. */\nexport class AiBillingExtractorError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({\n message = `Failed to extract billing data.`,\n cause,\n }: {\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingExtractorError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingDestinationError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/**\n * Error raised when billing data processing fails for a destination.\n */\nexport class AiBillingDestinationError extends AIBillingError {\n private readonly [symbol] = true;\n\n /** The ID of the destination that failed to process billing data. */\n readonly destinationId?: string;\n\n constructor({\n destinationId,\n message = `Failed to process billing data for destination: '${destinationId}'.`,\n cause,\n }: {\n destinationId?: string;\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n this.destinationId = destinationId;\n }\n\n static isInstance(error: unknown): error is AiBillingDestinationError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingCostError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when a cost conversion or calculation fails. */\nexport class AiBillingCostError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({ message, cause }: { message: string; cause?: unknown }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingCostError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import type { Destination, BillingEvent, DefaultTags } from '../types/index.js';\nimport { AiBillingDestinationError } from '../error/index.js';\n\n/**\n * Creates a destination wrapper that normalizes destination handler errors.\n *\n * @param destinationId - Unique identifier for the destination.\n * @param handler - Destination implementation invoked for each billing event.\n * @returns A destination function that wraps thrown errors as AiBillingDestinationError.\n */\nexport function createDestination<TTags extends DefaultTags = DefaultTags>(\n destinationId: string,\n handler: (event: BillingEvent<TTags>) => Promise<void> | void,\n): Destination<TTags> {\n return async (event: BillingEvent<TTags>) => {\n try {\n await handler(event);\n } catch (error) {\n throw new AiBillingDestinationError({\n destinationId,\n cause: error,\n });\n }\n };\n}\n","import { createDestination } from './base-destination.js';\nimport type { DefaultTags, Destination } from '../types/index.js';\n\n/**\n * Creates a destination that logs billing events to the console.\n *\n * @returns A destination that prints each event with full depth formatting.\n */\nexport function consoleDestination<\n TTags extends DefaultTags = DefaultTags,\n>(): Destination<TTags> {\n return createDestination<TTags>('console-logger', event => {\n console.dir(event, {\n depth: null,\n colors: true,\n compact: false,\n });\n });\n}\n","import { AiBillingCostError } from '../index.js';\nimport type { Cost, CostUnit } from '../index.js';\n\nconst getNanos = (cost: Cost): number => {\n switch (cost.unit) {\n case 'base':\n return Math.round(cost.amount * 1_000_000_000);\n case 'cents':\n return Math.round(cost.amount * 10_000_000);\n case 'micros':\n return Math.round(cost.amount * 1_000);\n case 'nanos':\n return Math.round(cost.amount);\n default:\n throw new AiBillingCostError({\n message: `Failed to process cost. Unknown CostUnit: '${String(cost.unit)}'.`,\n });\n }\n};\n\n/**\n * Returns the numeric amount of `cost` expressed in `targetUnit`.\n *\n * Values are converted via an integer nanos intermediate so fractional `base` / `cents` / `micros` amounts\n * round consistently. Throws {@link AiBillingCostError} when `cost.unit` is not a known {@link CostUnit}.\n *\n * @param cost - Source {@link Cost} (amount + unit + currency).\n * @param targetUnit - Unit for the returned number (same scale as {@link Cost} amounts for that unit).\n * @returns The amount in `targetUnit`; for `nanos` this is a whole number of nanos.\n * @internal\n */\nexport const costToNumber = (cost: Cost, targetUnit: CostUnit): number => {\n const nanos = getNanos(cost);\n\n if (targetUnit === 'nanos') return nanos;\n if (targetUnit === 'micros') return nanos / 1_000;\n if (targetUnit === 'cents') return nanos / 10_000_000;\n return nanos / 1_000_000_000; // base\n};\n\n/**\n * Converts a {@link Cost} to the same amount in a different {@link CostUnit}, preserving `currency`.\n *\n * Implemented with {@link costToNumber}; the result is always a new object.\n *\n * @param cost - Source cost.\n * @param targetUnit - Desired unit for `amount` on the returned object.\n * @returns A new {@link Cost} with `unit: targetUnit` and `amount` in that unit's scale.\n * @internal\n */\nexport const convertCostUnit = (cost: Cost, targetUnit: CostUnit): Cost => {\n return {\n amount: costToNumber(cost, targetUnit),\n currency: cost.currency,\n unit: targetUnit,\n };\n};\n\n/**\n * Wraps a numeric rate as a {@link Cost} in `base` units and `USD` currency.\n *\n * Provider calculators pass per-token prices from {@link ModelPricing} here, then scale with\n * {@link multiplyCost} using token counts.\n *\n * @param amount - Rate amount in base USD units (defaults to `0` when omitted).\n * @returns A {@link Cost} with `unit: 'base'` and `currency: 'USD'`.\n * @internal\n */\nexport const rateToCost = (amount: number = 0): Cost => ({\n amount,\n unit: 'base',\n currency: 'USD',\n});\n","import { Cost } from '../types/index.js';\nimport { AiBillingCostError } from '../index.js';\nimport { convertCostUnit } from './convert-cost.js';\n\n/**\n * Scales a {@link Cost} by `multiplier` (for example token count × per-token rate).\n *\n * Converts to {@link CostUnit} `nanos`, multiplies the integer nanos amount (rounded), and returns a\n * {@link Cost} with `unit: 'nanos'` and the same `currency` as the input.\n *\n * @param cost - Base cost to scale.\n * @param multiplier - Factor applied to the nanos amount (often a non-negative token count).\n * @returns The scaled cost in nanos.\n * @internal\n */\nexport const multiplyCost = (cost: Cost, multiplier: number): Cost => {\n const nanosCost = convertCostUnit(cost, 'nanos');\n return {\n ...nanosCost,\n amount: Math.round(nanosCost.amount * multiplier),\n };\n};\n\n/**\n * Adds any number of {@link Cost} values after converting each to nanos.\n *\n * All arguments must share the same `currency`; otherwise throws {@link AiBillingCostError}. With no\n * arguments, returns a zero USD cost in nanos. With a single cost, still normalizes to nanos.\n *\n * @param costs - Costs to sum (variadic).\n * @returns The total as a {@link Cost} with `unit: 'nanos'` and the shared `currency`.\n * @internal\n */\nexport const addCosts = (...costs: Cost[]): Cost => {\n if (costs.length === 0) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const firstCost = costs[0];\n\n if (!firstCost) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const baseCurrency = firstCost.currency;\n\n const totalNanos = costs.reduce((sum, currentCost) => {\n if (currentCost.currency !== baseCurrency) {\n throw new AiBillingCostError({\n message: `Currency mismatch: Cannot add ${baseCurrency} to ${currentCost.currency}`,\n });\n }\n return sum + convertCostUnit(currentCost, 'nanos').amount;\n }, 0);\n\n return { amount: totalNanos, unit: 'nanos', currency: baseCurrency };\n};\n\n/**\n * Applies a fractional discount to `cost` in nanos: `amount * (1 - discount)`.\n *\n * If `discount` is falsy or `<= 0`, returns `cost` unchanged (same unit and amount). Otherwise converts to\n * nanos, subtracts `round(amount * discount)`, and clamps the result at zero. Typical `discount` values are\n * between `0` and `1` (for example `0.1` for 10% off).\n *\n * @param cost - Original cost.\n * @param discount - Fraction of the nanos amount to remove (not a percentage label).\n * @returns Either the original `cost` or a discounted {@link Cost} in nanos.\n * @internal\n */\nexport const applyDiscount = (cost: Cost, discount: number): Cost => {\n if (!discount || discount <= 0) return cost;\n\n const nanosCost = convertCostUnit(cost, 'nanos');\n const discountAmount = Math.round(nanosCost.amount * discount);\n\n return {\n ...nanosCost,\n amount: Math.max(0, nanosCost.amount - discountAmount),\n };\n};\n","import type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a base price resolver that wraps a handler function.\n * @param handler - The function that resolves model pricing.\n * @returns A price resolver that wraps the handler function.\n */\nexport function createBasePriceResolver(\n handler: (\n context: PriceResolverContext,\n ) => ModelPricing | undefined | Promise<ModelPricing | undefined>,\n): PriceResolver {\n return async (context: PriceResolverContext) => {\n return handler(context);\n };\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\ntype PricingRow = Record<string, number | string>;\ntype PricingMap = Record<string, PricingRow[]>;\n\nfunction rowToModelPricing(row: PricingRow): ModelPricing {\n return {\n promptTokens: row['price_prompt'] as number,\n completionTokens: row['price_completion'] as number,\n ...(row['price_request'] != null && {\n request: row['price_request'] as number,\n }),\n ...(row['price_input_cache_read'] != null && {\n inputCacheReadTokens: row['price_input_cache_read'] as number,\n }),\n ...(row['price_input_cache_write'] != null && {\n inputCacheWriteTokens: row['price_input_cache_write'] as number,\n }),\n ...(row['price_internal_reasoning'] != null && {\n internalReasoningTokens: row['price_internal_reasoning'] as number,\n }),\n ...(row['pricing_discount'] != null && {\n discount: row['pricing_discount'] as number,\n }),\n };\n}\n\n/**\n * Configuration for {@link createNarevPriceResolver}.\n */\nexport type NarevPriceResolverOptions = {\n /** API key used for authenticated pricing requests. */\n apiKey: string;\n /** Optional base URL for the Narev API. */\n apiUrl?: string;\n};\n\n/**\n * Creates a price resolver that fetches model pricing from the Narev API.\n *\n * @param options - Resolver options; see {@link NarevPriceResolverOptions}.\n * @returns A base price resolver that resolves model pricing from Narev.\n */\nexport function createNarevPriceResolver(\n options: NarevPriceResolverOptions,\n): PriceResolver {\n const { apiKey, apiUrl = 'https://narev.ai' } = options;\n\n return createBasePriceResolver(\n async ({\n modelId,\n providerId,\n subProvider,\n }: PriceResolverContext): Promise<ModelPricing | undefined> => {\n const params = new URLSearchParams({ model_id: modelId });\n if (providerId) params.set('gateway', providerId);\n if (subProvider) params.set('provider', subProvider);\n\n const url = `${apiUrl}/api/models/pricing?${params}`;\n const headers: Record<string, string> = apiKey\n ? { Authorization: `Bearer ${apiKey}` }\n : {};\n\n let data: PricingMap | null;\n try {\n const res = await fetch(url, { headers });\n if (!res.ok) return undefined;\n data = (await res.json()) as PricingMap | null;\n } catch {\n return undefined;\n }\n\n if (!data) return undefined;\n\n const rows = data[modelId];\n const row = rows?.[0];\n if (!row) return undefined;\n\n return rowToModelPricing(row);\n },\n );\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a price resolver that uses a static pricing map.\n * @param pricingMap - A mapping of model IDs to model pricing.\n * @returns A price resolver that uses the static pricing map.\n */\nexport function createObjectPriceResolver(\n pricingMap: Record<string, ModelPricing>,\n): PriceResolver {\n return createBasePriceResolver(({ modelId }: PriceResolverContext) => {\n return pricingMap[modelId];\n });\n}\n"],"mappings":"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","names":["name","marker","symbol","name","marker","symbol","name","marker","symbol"]}
|
|
1
|
+
{"version":3,"sources":["../src/event/to-json-object.ts","../src/event/to-meter-metadata.ts","../src/ai-sdk/language-model-middleware/v3/language-model-v3-base-billing-middleware.ts","../src/error/ai-billing-error.ts","../src/error/extractor-error.ts","../src/error/destination-error.ts","../src/error/cost-error.ts","../src/destination/base-destination.ts","../src/destination/console-destination.ts","../src/cost/convert-cost.ts","../src/cost/op-cost.ts","../src/pricing/base-price-resolver.ts","../src/pricing/narev-price-resolver.ts","../src/pricing/object-price-resolver.ts"],"sourcesContent":["import { DefaultTags, BillingEvent } from '../types/index.js';\nimport type { JSONObject } from '@ai-sdk/provider';\n\n/**\n * Casts a billing event into a JSON object payload.\n * @param event - The billing event to cast.\n * @returns The billing event represented as a JSON object.\n */\nexport function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject {\n return event as unknown as JSONObject;\n}\n","import type {\n BillingEvent,\n DefaultTags,\n MeterMetadata,\n} from '../types/index.js';\n\n/**\n * Converts a billing event into a meter metadata object.\n * @param event - The billing event to convert.\n * @returns The meter metadata object.\n */\nexport function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(\n event: BillingEvent<TTags>,\n): MeterMetadata {\n const u = event.usage ?? {};\n\n // Initialize with required fields\n const dimensions: MeterMetadata = {\n generation_id: event.generationId,\n model_id: event.modelId,\n provider: event.provider,\n };\n\n const addOptional = <K extends keyof MeterMetadata>(\n key: K,\n value: MeterMetadata[K],\n ) => {\n if (value !== undefined && value !== null) {\n dimensions[key] = value;\n }\n };\n\n addOptional('sub_provider', u.subProvider);\n addOptional('input_tokens', u.inputTokens);\n addOptional('output_tokens', u.outputTokens);\n addOptional('total_tokens', u.totalTokens);\n addOptional('reasoning_tokens', u.reasoningTokens);\n addOptional('cache_read_tokens', u.cacheReadTokens);\n addOptional('cache_write_tokens', u.cacheWriteTokens);\n addOptional('request_count', u.requestCount);\n addOptional('web_search_count', u.webSearchCount);\n addOptional('raw_provider_cost', u.rawProviderCost);\n addOptional('raw_upstream_inference_cost', u.rawUpstreamInferenceCost);\n\n if (event.tags) {\n for (const [key, value] of Object.entries(event.tags)) {\n if (value == null) continue;\n dimensions[`tag_${key}`] =\n typeof value === 'object'\n ? JSON.stringify(value)\n : (value as string | number);\n }\n }\n\n return dimensions;\n}\n","import type {\n LanguageModelV3,\n LanguageModelV3CallOptions,\n LanguageModelV3Usage,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV3Middleware,\n SharedV3ProviderMetadata,\n} from '@ai-sdk/provider';\nimport type {\n BaseBillingMiddlewareOptions,\n EventBuilder,\n BillingEvent,\n DefaultTags,\n} from '../../../types/index.js';\nimport { toJSONObject } from '../../../event/index.js';\n\nexport interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {\n responseId: string | undefined;\n model: LanguageModelV3;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n tags: TTags;\n webSearchCount: number;\n}\n\n/**\n * Configuration for {@link createV3BillingMiddleware}.\n *\n * Extends {@link BaseBillingMiddlewareOptions} (`destinations`, `defaultTags`, `waitUntil`, `onError`) and\n * requires an {@link EventBuilder} to construct the {@link BillingEvent}.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n */\nexport interface BillingMiddlewareV3Options<\n TTags extends DefaultTags = DefaultTags,\n> extends BaseBillingMiddlewareOptions<TTags> {\n /** Builds a billing event from the model response data. */\n buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;\n}\n\n/**\n * Creates a billing middleware for the Language Model V3 API.\n *\n * @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.\n * @param options - Billing options; see {@link BillingMiddlewareV3Options}.\n * @returns The billing middleware.\n */\nexport function createV3BillingMiddleware<\n TTags extends DefaultTags = DefaultTags,\n>(options: BillingMiddlewareV3Options<TTags>): LanguageModelV3Middleware {\n const { buildEvent, destinations, defaultTags, waitUntil, onError } = options;\n\n const processEvent = async ({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n webSearchCount,\n }: {\n model: LanguageModelV3;\n params: LanguageModelV3CallOptions;\n usage: LanguageModelV3Usage | undefined;\n providerMetadata: SharedV3ProviderMetadata | undefined;\n responseId: string | undefined;\n webSearchCount: number;\n }): Promise<BillingEvent<TTags> | null> => {\n try {\n const requestTags = params.providerOptions?.['ai-billing-tags'];\n\n const tags = {\n ...(defaultTags ?? {}),\n ...(requestTags ?? {}),\n } as TTags;\n\n const event = await buildEvent({\n responseId,\n model,\n usage,\n providerMetadata,\n tags,\n webSearchCount,\n });\n\n if (event && destinations && destinations?.length > 0) {\n const dispatchDestinationsPromise = Promise.allSettled(\n destinations.map(d => Promise.resolve(d(event))),\n );\n if (waitUntil) waitUntil(dispatchDestinationsPromise);\n }\n return event;\n } catch (err) {\n if (onError) onError(err);\n else console.error('[ai-billing] Core Error:', err);\n return null;\n }\n };\n\n return {\n specificationVersion: 'v3',\n\n wrapGenerate: async ({ doGenerate, model, params }) => {\n const result: LanguageModelV3GenerateResult = await doGenerate();\n\n const webSearchCount = result.content.filter(\n c => c.type === 'source',\n ).length;\n\n const event = await processEvent({\n model,\n params,\n usage: result.usage,\n providerMetadata: result.providerMetadata,\n responseId: result.response?.id,\n webSearchCount,\n });\n\n const providerMetadataWithBilling = {\n ...result.providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n return {\n ...result,\n providerMetadata: providerMetadataWithBilling,\n };\n },\n\n wrapStream: async ({ doStream, model, params }) => {\n const { stream, ...rest } = await doStream();\n\n let responseId: string | undefined;\n let usage: LanguageModelV3Usage | undefined;\n let providerMetadata: SharedV3ProviderMetadata | undefined;\n let finishChunk:\n | Extract<LanguageModelV3StreamPart, { type: 'finish' }>\n | undefined;\n let webSearchCount = 0;\n\n const billedStream = stream.pipeThrough(\n new TransformStream<\n LanguageModelV3StreamPart,\n LanguageModelV3StreamPart\n >({\n transform(chunk, controller) {\n if (chunk.type === 'text-start') responseId = chunk.id;\n if (chunk.type === 'response-metadata' && !responseId) {\n responseId = chunk.id;\n }\n if (chunk.type === 'source') {\n webSearchCount++;\n }\n if (chunk.type === 'finish') {\n usage = chunk.usage;\n providerMetadata = chunk.providerMetadata;\n finishChunk = chunk;\n return; // held until flush\n }\n controller.enqueue(chunk);\n },\n async flush(controller) {\n const event = await processEvent({\n model,\n params,\n usage,\n providerMetadata,\n responseId,\n webSearchCount,\n });\n\n const providerMetadataWithBilling = {\n ...providerMetadata,\n } as SharedV3ProviderMetadata;\n\n if (event) {\n providerMetadataWithBilling['ai-billing'] = toJSONObject(event);\n }\n\n if (finishChunk) {\n controller.enqueue({\n ...finishChunk,\n providerMetadata: providerMetadataWithBilling,\n });\n }\n },\n }),\n );\n\n return { ...rest, stream: billedStream };\n },\n };\n}\n","const marker = 'ai-billing.error';\nconst symbol = Symbol.for(marker);\n\n/** Base error type for all ai-billing package errors. */\nexport class AIBillingError extends Error {\n private readonly [symbol] = true;\n\n readonly cause?: unknown;\n\n constructor({\n name,\n message,\n cause,\n }: {\n name: string;\n message: string;\n cause?: unknown;\n }) {\n super(message);\n this.name = name;\n this.cause = cause;\n }\n\n static isInstance(error: unknown): error is AIBillingError {\n return AIBillingError.hasMarker(error, marker);\n }\n\n protected static hasMarker(error: unknown, markerString: string): boolean {\n const markerSymbol = Symbol.for(markerString);\n return (\n error != null &&\n typeof error === 'object' &&\n markerSymbol in error &&\n typeof error[markerSymbol] === 'boolean' &&\n error[markerSymbol] === true\n );\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingExtractorError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when billing data extraction fails. */\nexport class AiBillingExtractorError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({\n message = `Failed to extract billing data.`,\n cause,\n }: {\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingExtractorError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingDestinationError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/**\n * Error raised when billing data processing fails for a destination.\n */\nexport class AiBillingDestinationError extends AIBillingError {\n private readonly [symbol] = true;\n\n /** The ID of the destination that failed to process billing data. */\n readonly destinationId?: string;\n\n constructor({\n destinationId,\n message = `Failed to process billing data for destination: '${destinationId}'.`,\n cause,\n }: {\n destinationId?: string;\n message?: string;\n cause?: unknown;\n }) {\n super({ name, message, cause });\n this.destinationId = destinationId;\n }\n\n static isInstance(error: unknown): error is AiBillingDestinationError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import { AIBillingError } from './ai-billing-error.js';\n\nconst name = 'AiBillingCostError';\nconst marker = `ai-billing.error.${name}`;\nconst symbol = Symbol.for(marker);\n\n/** Error thrown when a cost conversion or calculation fails. */\nexport class AiBillingCostError extends AIBillingError {\n private readonly [symbol] = true;\n\n constructor({ message, cause }: { message: string; cause?: unknown }) {\n super({ name, message, cause });\n }\n\n static isInstance(error: unknown): error is AiBillingCostError {\n return AIBillingError.hasMarker(error, marker);\n }\n}\n","import type { Destination, BillingEvent, DefaultTags } from '../types/index.js';\nimport { AiBillingDestinationError } from '../error/index.js';\n\n/**\n * Creates a destination wrapper that normalizes destination handler errors.\n *\n * @param destinationId - Unique identifier for the destination.\n * @param handler - Destination implementation invoked for each billing event.\n * @returns A destination function that wraps thrown errors as AiBillingDestinationError.\n */\nexport function createDestination<TTags extends DefaultTags = DefaultTags>(\n destinationId: string,\n handler: (event: BillingEvent<TTags>) => Promise<void> | void,\n): Destination<TTags> {\n return async (event: BillingEvent<TTags>) => {\n try {\n await handler(event);\n } catch (error) {\n throw new AiBillingDestinationError({\n destinationId,\n cause: error,\n });\n }\n };\n}\n","import { createDestination } from './base-destination.js';\nimport type { DefaultTags, Destination } from '../types/index.js';\n\n/**\n * Creates a destination that logs billing events to the console.\n *\n * @returns A destination that prints each event with full depth formatting.\n */\nexport function consoleDestination<\n TTags extends DefaultTags = DefaultTags,\n>(): Destination<TTags> {\n return createDestination<TTags>('console-logger', event => {\n console.dir(event, {\n depth: null,\n colors: true,\n compact: false,\n });\n });\n}\n","import { AiBillingCostError } from '../index.js';\nimport type { Cost, CostUnit } from '../index.js';\n\nconst getNanos = (cost: Cost): number => {\n switch (cost.unit) {\n case 'base':\n return Math.round(cost.amount * 1_000_000_000);\n case 'cents':\n return Math.round(cost.amount * 10_000_000);\n case 'micros':\n return Math.round(cost.amount * 1_000);\n case 'nanos':\n return Math.round(cost.amount);\n default:\n throw new AiBillingCostError({\n message: `Failed to process cost. Unknown CostUnit: '${String(cost.unit)}'.`,\n });\n }\n};\n\n/**\n * Returns the numeric amount of `cost` expressed in `targetUnit`.\n *\n * Values are converted via an integer nanos intermediate so fractional `base` / `cents` / `micros` amounts\n * round consistently. Throws {@link AiBillingCostError} when `cost.unit` is not a known {@link CostUnit}.\n *\n * @param cost - Source {@link Cost} (amount + unit + currency).\n * @param targetUnit - Unit for the returned number (same scale as {@link Cost} amounts for that unit).\n * @returns The amount in `targetUnit`; for `nanos` this is a whole number of nanos.\n * @internal\n */\nexport const costToNumber = (cost: Cost, targetUnit: CostUnit): number => {\n const nanos = getNanos(cost);\n\n if (targetUnit === 'nanos') return nanos;\n if (targetUnit === 'micros') return nanos / 1_000;\n if (targetUnit === 'cents') return nanos / 10_000_000;\n return nanos / 1_000_000_000; // base\n};\n\n/**\n * Converts a {@link Cost} to the same amount in a different {@link CostUnit}, preserving `currency`.\n *\n * Implemented with {@link costToNumber}; the result is always a new object.\n *\n * @param cost - Source cost.\n * @param targetUnit - Desired unit for `amount` on the returned object.\n * @returns A new {@link Cost} with `unit: targetUnit` and `amount` in that unit's scale.\n * @internal\n */\nexport const convertCostUnit = (cost: Cost, targetUnit: CostUnit): Cost => {\n return {\n amount: costToNumber(cost, targetUnit),\n currency: cost.currency,\n unit: targetUnit,\n };\n};\n\n/**\n * Wraps a numeric rate as a {@link Cost} in `base` units and `USD` currency.\n *\n * Provider calculators pass per-token prices from {@link ModelPricing} here, then scale with\n * {@link multiplyCost} using token counts.\n *\n * @param amount - Rate amount in base USD units (defaults to `0` when omitted).\n * @returns A {@link Cost} with `unit: 'base'` and `currency: 'USD'`.\n * @internal\n */\nexport const rateToCost = (amount: number = 0): Cost => ({\n amount,\n unit: 'base',\n currency: 'USD',\n});\n","import { Cost } from '../types/index.js';\nimport { AiBillingCostError } from '../index.js';\nimport { convertCostUnit } from './convert-cost.js';\n\n/**\n * Scales a {@link Cost} by `multiplier` (for example token count × per-token rate).\n *\n * Converts to {@link CostUnit} `nanos`, multiplies the integer nanos amount (rounded), and returns a\n * {@link Cost} with `unit: 'nanos'` and the same `currency` as the input.\n *\n * @param cost - Base cost to scale.\n * @param multiplier - Factor applied to the nanos amount (often a non-negative token count).\n * @returns The scaled cost in nanos.\n * @internal\n */\nexport const multiplyCost = (cost: Cost, multiplier: number): Cost => {\n const nanosCost = convertCostUnit(cost, 'nanos');\n return {\n ...nanosCost,\n amount: Math.round(nanosCost.amount * multiplier),\n };\n};\n\n/**\n * Adds any number of {@link Cost} values after converting each to nanos.\n *\n * All arguments must share the same `currency`; otherwise throws {@link AiBillingCostError}. With no\n * arguments, returns a zero USD cost in nanos. With a single cost, still normalizes to nanos.\n *\n * @param costs - Costs to sum (variadic).\n * @returns The total as a {@link Cost} with `unit: 'nanos'` and the shared `currency`.\n * @internal\n */\nexport const addCosts = (...costs: Cost[]): Cost => {\n if (costs.length === 0) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const firstCost = costs[0];\n\n if (!firstCost) {\n return { amount: 0, unit: 'nanos', currency: 'USD' };\n }\n\n const baseCurrency = firstCost.currency;\n\n const totalNanos = costs.reduce((sum, currentCost) => {\n if (currentCost.currency !== baseCurrency) {\n throw new AiBillingCostError({\n message: `Currency mismatch: Cannot add ${baseCurrency} to ${currentCost.currency}`,\n });\n }\n return sum + convertCostUnit(currentCost, 'nanos').amount;\n }, 0);\n\n return { amount: totalNanos, unit: 'nanos', currency: baseCurrency };\n};\n\n/**\n * Applies a fractional discount to `cost` in nanos: `amount * (1 - discount)`.\n *\n * If `discount` is falsy or `<= 0`, returns `cost` unchanged (same unit and amount). Otherwise converts to\n * nanos, subtracts `round(amount * discount)`, and clamps the result at zero. Typical `discount` values are\n * between `0` and `1` (for example `0.1` for 10% off).\n *\n * @param cost - Original cost.\n * @param discount - Fraction of the nanos amount to remove (not a percentage label).\n * @returns Either the original `cost` or a discounted {@link Cost} in nanos.\n * @internal\n */\nexport const applyDiscount = (cost: Cost, discount: number): Cost => {\n if (!discount || discount <= 0) return cost;\n\n const nanosCost = convertCostUnit(cost, 'nanos');\n const discountAmount = Math.round(nanosCost.amount * discount);\n\n return {\n ...nanosCost,\n amount: Math.max(0, nanosCost.amount - discountAmount),\n };\n};\n","import type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a base price resolver that wraps a handler function.\n * @param handler - The function that resolves model pricing.\n * @returns A price resolver that wraps the handler function.\n */\nexport function createBasePriceResolver(\n handler: (\n context: PriceResolverContext,\n ) => ModelPricing | undefined | Promise<ModelPricing | undefined>,\n): PriceResolver {\n return async (context: PriceResolverContext) => {\n return handler(context);\n };\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\ntype PricingRow = Record<string, number | string>;\ntype PricingEntry = { model_id: string; prices: PricingRow[] };\ntype PricingResponse = PricingEntry[];\n\nfunction rowToModelPricing(row: PricingRow): ModelPricing {\n return {\n promptTokens: row['price_prompt'] as number,\n completionTokens: row['price_completion'] as number,\n ...(row['price_request'] != null && {\n request: row['price_request'] as number,\n }),\n ...(row['price_input_cache_read'] != null && {\n inputCacheReadTokens: row['price_input_cache_read'] as number,\n }),\n ...(row['price_input_cache_write'] != null && {\n inputCacheWriteTokens: row['price_input_cache_write'] as number,\n }),\n ...(row['price_internal_reasoning'] != null && {\n internalReasoningTokens: row['price_internal_reasoning'] as number,\n }),\n ...(row['pricing_discount'] != null && {\n discount: row['pricing_discount'] as number,\n }),\n };\n}\n\n/**\n * Configuration for {@link createNarevPriceResolver}.\n */\nexport type NarevPriceResolverOptions = {\n /** API key used for authenticated pricing requests. */\n apiKey: string;\n /** Optional base URL for the Narev API. */\n apiUrl?: string;\n};\n\n/**\n * Creates a price resolver that fetches model pricing from the Narev API.\n *\n * @param options - Resolver options; see {@link NarevPriceResolverOptions}.\n * @returns A base price resolver that resolves model pricing from Narev.\n */\nexport function createNarevPriceResolver(\n options: NarevPriceResolverOptions,\n): PriceResolver {\n const { apiKey, apiUrl = 'https://narev.ai' } = options;\n\n return createBasePriceResolver(\n async ({\n modelId,\n providerId,\n subProvider,\n }: PriceResolverContext): Promise<ModelPricing | undefined> => {\n const params = new URLSearchParams({ model_id: modelId });\n if (providerId) params.set('provider', providerId);\n if (subProvider) params.set('subprovider', subProvider);\n\n const url = `${apiUrl}/api/models/pricing?${params}`;\n const headers: Record<string, string> = apiKey\n ? { Authorization: `Bearer ${apiKey}` }\n : {};\n\n let data: PricingResponse | null;\n try {\n const res = await fetch(url, { headers });\n if (!res.ok) return undefined;\n data = (await res.json()) as PricingResponse | null;\n } catch {\n return undefined;\n }\n\n if (!data) return undefined;\n\n const entry = data.find(e => e.model_id === modelId);\n const row = entry?.prices?.[0];\n if (!row) return undefined;\n\n return rowToModelPricing(row);\n },\n );\n}\n","import { createBasePriceResolver } from './base-price-resolver.js';\nimport type {\n ModelPricing,\n PriceResolver,\n PriceResolverContext,\n} from '../types/index.js';\n\n/**\n * Creates a price resolver that uses a static pricing map.\n * @param pricingMap - A mapping of model IDs to model pricing.\n * @returns A price resolver that uses the static pricing map.\n */\nexport function createObjectPriceResolver(\n pricingMap: Record<string, ModelPricing>,\n): PriceResolver {\n return createBasePriceResolver(({ modelId }: PriceResolverContext) => {\n return pricingMap[modelId];\n });\n}\n"],"mappings":"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","names":["name","marker","symbol","name","marker","symbol","name","marker","symbol"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-billing/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"typescript": "5.9.2",
|
|
39
39
|
"vitest": "4.1.1",
|
|
40
40
|
"zod": "^4.3.6",
|
|
41
|
-
"@ai-billing/testing": "0.0.
|
|
41
|
+
"@ai-billing/testing": "0.0.4",
|
|
42
42
|
"@ai-billing/typescript-config": "0.0.1"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|