@ai-billing/core 0.0.3 → 0.0.5
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 +43 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +162 -4
- package/dist/index.d.ts +162 -4
- package/dist/index.js +40 -7
- package/dist/index.js.map +1 -1
- package/package.json +6 -3
package/dist/index.cjs
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
AiBillingExtractorError: () => AiBillingExtractorError,
|
|
27
27
|
addCosts: () => addCosts,
|
|
28
28
|
applyDiscount: () => applyDiscount,
|
|
29
|
+
buildMeterMetadata: () => buildMeterMetadata,
|
|
29
30
|
consoleDestination: () => consoleDestination,
|
|
30
31
|
convertCostUnit: () => convertCostUnit,
|
|
31
32
|
costToNumber: () => costToNumber,
|
|
@@ -35,7 +36,8 @@ __export(index_exports, {
|
|
|
35
36
|
createObjectPriceResolver: () => createObjectPriceResolver,
|
|
36
37
|
createV3BillingMiddleware: () => createV3BillingMiddleware,
|
|
37
38
|
multiplyCost: () => multiplyCost,
|
|
38
|
-
rateToCost: () => rateToCost
|
|
39
|
+
rateToCost: () => rateToCost,
|
|
40
|
+
toJSONObject: () => toJSONObject
|
|
39
41
|
});
|
|
40
42
|
module.exports = __toCommonJS(index_exports);
|
|
41
43
|
|
|
@@ -44,6 +46,38 @@ function toJSONObject(event) {
|
|
|
44
46
|
return event;
|
|
45
47
|
}
|
|
46
48
|
|
|
49
|
+
// src/event/to-meter-metadata.ts
|
|
50
|
+
function buildMeterMetadata(event) {
|
|
51
|
+
const u = event.usage ?? {};
|
|
52
|
+
const dimensions = {
|
|
53
|
+
generation_id: event.generationId,
|
|
54
|
+
model_id: event.modelId,
|
|
55
|
+
provider: event.provider
|
|
56
|
+
};
|
|
57
|
+
const addOptional = (key, value) => {
|
|
58
|
+
if (value !== void 0 && value !== null) {
|
|
59
|
+
dimensions[key] = value;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
addOptional("sub_provider", u.subProvider);
|
|
63
|
+
addOptional("input_tokens", u.inputTokens);
|
|
64
|
+
addOptional("output_tokens", u.outputTokens);
|
|
65
|
+
addOptional("total_tokens", u.totalTokens);
|
|
66
|
+
addOptional("reasoning_tokens", u.reasoningTokens);
|
|
67
|
+
addOptional("cache_read_tokens", u.cacheReadTokens);
|
|
68
|
+
addOptional("cache_write_tokens", u.cacheWriteTokens);
|
|
69
|
+
addOptional("request_count", u.requestCount);
|
|
70
|
+
addOptional("raw_provider_cost", u.rawProviderCost);
|
|
71
|
+
addOptional("raw_upstream_inference_cost", u.rawUpstreamInferenceCost);
|
|
72
|
+
if (event.tags) {
|
|
73
|
+
for (const [key, value] of Object.entries(event.tags)) {
|
|
74
|
+
if (value == null) continue;
|
|
75
|
+
dimensions[`tag_${key}`] = typeof value === "object" ? JSON.stringify(value) : value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return dimensions;
|
|
79
|
+
}
|
|
80
|
+
|
|
47
81
|
// src/ai-sdk/language-model-middleware/v3/language-model-v3-base-billing-middleware.ts
|
|
48
82
|
function createV3BillingMiddleware(options) {
|
|
49
83
|
const { buildEvent, destinations, defaultTags, waitUntil, onError } = options;
|
|
@@ -198,6 +232,7 @@ var marker3 = `ai-billing.error.${name2}`;
|
|
|
198
232
|
var symbol3 = Symbol.for(marker3);
|
|
199
233
|
var AiBillingDestinationError = class extends AIBillingError {
|
|
200
234
|
[symbol3] = true;
|
|
235
|
+
/** The ID of the destination that failed to process billing data. */
|
|
201
236
|
destinationId;
|
|
202
237
|
constructor({
|
|
203
238
|
destinationId,
|
|
@@ -354,19 +389,17 @@ function rowToModelPricing(row) {
|
|
|
354
389
|
}
|
|
355
390
|
};
|
|
356
391
|
}
|
|
357
|
-
function createNarevPriceResolver({
|
|
358
|
-
apiKey,
|
|
359
|
-
apiUrl = "https://narev.ai"
|
|
360
|
-
}) {
|
|
392
|
+
function createNarevPriceResolver(options) {
|
|
393
|
+
const { apiKey, apiUrl = "https://narev.ai" } = options;
|
|
361
394
|
return createBasePriceResolver(
|
|
362
395
|
async ({
|
|
363
396
|
modelId,
|
|
364
397
|
providerId,
|
|
365
|
-
|
|
398
|
+
subProvider
|
|
366
399
|
}) => {
|
|
367
400
|
const params = new URLSearchParams({ model_id: modelId });
|
|
368
401
|
if (providerId) params.set("gateway", providerId);
|
|
369
|
-
if (
|
|
402
|
+
if (subProvider) params.set("provider", subProvider);
|
|
370
403
|
const url = `${apiUrl}/api/models/pricing?${params}`;
|
|
371
404
|
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
|
|
372
405
|
let data;
|
|
@@ -400,6 +433,7 @@ function createObjectPriceResolver(pricingMap) {
|
|
|
400
433
|
AiBillingExtractorError,
|
|
401
434
|
addCosts,
|
|
402
435
|
applyDiscount,
|
|
436
|
+
buildMeterMetadata,
|
|
403
437
|
consoleDestination,
|
|
404
438
|
convertCostUnit,
|
|
405
439
|
costToNumber,
|
|
@@ -409,6 +443,7 @@ function createObjectPriceResolver(pricingMap) {
|
|
|
409
443
|
createObjectPriceResolver,
|
|
410
444
|
createV3BillingMiddleware,
|
|
411
445
|
multiplyCost,
|
|
412
|
-
rateToCost
|
|
446
|
+
rateToCost,
|
|
447
|
+
toJSONObject
|
|
413
448
|
});
|
|
414
449
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/event/to-json-object.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';\n","import { DefaultTags, BillingEvent } from '../types/index.js';\nimport type { JSONObject } from '@ai-sdk/provider';\n\nexport function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject {\n return event as unknown as JSONObject;\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\nexport interface BillingMiddlewareV3Options<\n TTags extends DefaultTags = DefaultTags,\n> extends BaseBillingMiddlewareOptions<TTags> {\n buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;\n}\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\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\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\nexport class AiBillingDestinationError extends AIBillingError {\n private readonly [symbol] = true;\n\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\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\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';\nimport { JSONObject } from '@ai-sdk/provider';\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\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\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\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\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\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\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\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 { ModelPricing, PriceResolverContext } 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\nexport type NarevPriceResolverOptions = {\n apiKey: string;\n apiUrl?: string;\n};\n\nexport function createNarevPriceResolver({\n apiKey,\n apiUrl = 'https://narev.ai',\n}: NarevPriceResolverOptions): ReturnType<typeof createBasePriceResolver> {\n return createBasePriceResolver(\n async ({\n modelId,\n providerId,\n subProviderId,\n }: PriceResolverContext): Promise<ModelPricing | undefined> => {\n const params = new URLSearchParams({ model_id: modelId });\n if (providerId) params.set('gateway', providerId);\n if (subProviderId) params.set('provider', subProviderId);\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\nexport function createObjectPriceResolver(\n pricingMap: Record<string, ModelPricing>,\n): PriceResolver {\n return createBasePriceResolver(({ modelId }: PriceResolverContext) => {\n return pricingMap[modelId];\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACGO,SAAS,aAAa,OAA8C;AACzE,SAAO;AACT;;;AC0BO,SAAS,0BAEd,SAAuE;AACvE,QAAM,EAAE,YAAY,cAAc,aAAa,WAAW,QAAQ,IAAI;AAEtE,QAAM,eAAe,OAAO;AAAA,IAC1B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,MAM2C;AACzC,QAAI;AACF,YAAM,cAAc,OAAO,kBAAkB,iBAAiB;AAE9D,YAAM,OAAO;AAAA,QACX,GAAI,eAAe,CAAC;AAAA,QACpB,GAAI,eAAe,CAAC;AAAA,MACtB;AAEA,YAAM,QAAQ,MAAM,WAAW;AAAA,QAC7B;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,UAAI,SAAS,gBAAgB,cAAc,SAAS,GAAG;AACrD,cAAM,8BAA8B,QAAQ;AAAA,UAC1C,aAAa,IAAI,OAAK,QAAQ,QAAQ,EAAE,KAAK,CAAC,CAAC;AAAA,QACjD;AACA,YAAI,UAAW,WAAU,2BAA2B;AAAA,MACtD;AACA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,QAAS,SAAQ,GAAG;AAAA,UACnB,SAAQ,MAAM,4BAA4B,GAAG;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AAAA,IACL,sBAAsB;AAAA,IAEtB,cAAc,OAAO,EAAE,YAAY,OAAO,OAAO,MAAM;AACrD,YAAM,SAAwC,MAAM,WAAW;AAE/D,YAAM,QAAQ,MAAM,aAAa;AAAA,QAC/B;AAAA,QACA;AAAA,QACA,OAAO,OAAO;AAAA,QACd,kBAAkB,OAAO;AAAA,QACzB,YAAY,OAAO,UAAU;AAAA,MAC/B,CAAC;AAED,YAAM,8BAA8B;AAAA,QAClC,GAAG,OAAO;AAAA,MACZ;AAEA,UAAI,OAAO;AACT,oCAA4B,YAAY,IAAI,aAAa,KAAK;AAAA,MAChE;AAEA,aAAO;AAAA,QACL,GAAG;AAAA,QACH,kBAAkB;AAAA,MACpB;AAAA,IACF;AAAA,IAEA,YAAY,OAAO,EAAE,UAAU,OAAO,OAAO,MAAM;AACjD,YAAM,EAAE,QAAQ,GAAG,KAAK,IAAI,MAAM,SAAS;AAE3C,UAAI;AACJ,UAAI;AACJ,UAAI;AACJ,UAAI;AAIJ,YAAM,eAAe,OAAO;AAAA,QAC1B,IAAI,gBAGF;AAAA,UACA,UAAU,OAAO,YAAY;AAC3B,gBAAI,MAAM,SAAS,aAAc,cAAa,MAAM;AACpD,gBAAI,MAAM,SAAS,uBAAuB,CAAC,YAAY;AACrD,2BAAa,MAAM;AAAA,YACrB;AACA,gBAAI,MAAM,SAAS,UAAU;AAC3B,sBAAQ,MAAM;AACd,iCAAmB,MAAM;AACzB,4BAAc;AACd;AAAA,YACF;AACA,uBAAW,QAAQ,KAAK;AAAA,UAC1B;AAAA,UACA,MAAM,MAAM,YAAY;AACtB,kBAAM,QAAQ,MAAM,aAAa;AAAA,cAC/B;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YACF,CAAC;AAED,kBAAM,8BAA8B;AAAA,cAClC,GAAG;AAAA,YACL;AAEA,gBAAI,OAAO;AACT,0CAA4B,YAAY,IAAI,aAAa,KAAK;AAAA,YAChE;AAEA,gBAAI,aAAa;AACf,yBAAW,QAAQ;AAAA,gBACjB,GAAG;AAAA,gBACH,kBAAkB;AAAA,cACpB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF,CAAC;AAAA,MACH;AAEA,aAAO,EAAE,GAAG,MAAM,QAAQ,aAAa;AAAA,IACzC;AAAA,EACF;AACF;;;ACrKA,IAAM,SAAS;AACf,IAAM,SAAS,OAAO,IAAI,MAAM;AAEzB,IAAM,iBAAN,MAAM,wBAAuB,MAAM;AAAA,EACxC,CAAkB,MAAM,IAAI;AAAA,EAEnB;AAAA,EAET,YAAY;AAAA,IACV,MAAAA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAIG;AACD,UAAM,OAAO;AACb,SAAK,OAAOA;AACZ,SAAK,QAAQ;AAAA,EACf;AAAA,EAEA,OAAO,WAAW,OAAyC;AACzD,WAAO,gBAAe,UAAU,OAAO,MAAM;AAAA,EAC/C;AAAA,EAEA,OAAiB,UAAU,OAAgB,cAA+B;AACxE,UAAM,eAAe,OAAO,IAAI,YAAY;AAC5C,WACE,SAAS,QACT,OAAO,UAAU,YACjB,gBAAgB,SAChB,OAAO,MAAM,YAAY,MAAM,aAC/B,MAAM,YAAY,MAAM;AAAA,EAE5B;AACF;;;AClCA,IAAM,OAAO;AACb,IAAMC,UAAS,oBAAoB,IAAI;AACvC,IAAMC,UAAS,OAAO,IAAID,OAAM;AAEzB,IAAM,0BAAN,cAAsC,eAAe;AAAA,EAC1D,CAAkBC,OAAM,IAAI;AAAA,EAE5B,YAAY;AAAA,IACV,UAAU;AAAA,IACV;AAAA,EACF,GAGG;AACD,UAAM,EAAE,MAAM,SAAS,MAAM,CAAC;AAAA,EAChC;AAAA,EAEA,OAAO,WAAW,OAAkD;AAClE,WAAO,eAAe,UAAU,OAAOD,OAAM;AAAA,EAC/C;AACF;;;ACpBA,IAAME,QAAO;AACb,IAAMC,UAAS,oBAAoBD,KAAI;AACvC,IAAME,UAAS,OAAO,IAAID,OAAM;AAEzB,IAAM,4BAAN,cAAwC,eAAe;AAAA,EAC5D,CAAkBC,OAAM,IAAI;AAAA,EAEnB;AAAA,EAET,YAAY;AAAA,IACV;AAAA,IACA,UAAU,oDAAoD,aAAa;AAAA,IAC3E;AAAA,EACF,GAIG;AACD,UAAM,EAAE,MAAAF,OAAM,SAAS,MAAM,CAAC;AAC9B,SAAK,gBAAgB;AAAA,EACvB;AAAA,EAEA,OAAO,WAAW,OAAoD;AACpE,WAAO,eAAe,UAAU,OAAOC,OAAM;AAAA,EAC/C;AACF;;;ACzBA,IAAME,QAAO;AACb,IAAMC,UAAS,oBAAoBD,KAAI;AACvC,IAAME,UAAS,OAAO,IAAID,OAAM;AAEzB,IAAM,qBAAN,cAAiC,eAAe;AAAA,EACrD,CAAkBC,OAAM,IAAI;AAAA,EAE5B,YAAY,EAAE,SAAS,MAAM,GAAyC;AACpE,UAAM,EAAE,MAAAF,OAAM,SAAS,MAAM,CAAC;AAAA,EAChC;AAAA,EAEA,OAAO,WAAW,OAA6C;AAC7D,WAAO,eAAe,UAAU,OAAOC,OAAM;AAAA,EAC/C;AACF;;;ACbO,SAAS,kBACd,eACA,SACoB;AACpB,SAAO,OAAO,UAA+B;AAC3C,QAAI;AACF,YAAM,QAAQ,KAAK;AAAA,IACrB,SAAS,OAAO;AACd,YAAM,IAAI,0BAA0B;AAAA,QAClC;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;ACbO,SAAS,qBAEQ;AACtB,SAAO,kBAAyB,kBAAkB,WAAS;AACzD,YAAQ,IAAI,OAAO;AAAA,MACjB,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,SAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AACH;;;ACXA,IAAM,WAAW,CAAC,SAAuB;AACvC,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,KAAK,MAAM,KAAK,SAAS,GAAa;AAAA,IAC/C,KAAK;AACH,aAAO,KAAK,MAAM,KAAK,SAAS,GAAU;AAAA,IAC5C,KAAK;AACH,aAAO,KAAK,MAAM,KAAK,SAAS,GAAK;AAAA,IACvC,KAAK;AACH,aAAO,KAAK,MAAM,KAAK,MAAM;AAAA,IAC/B;AACE,YAAM,IAAI,mBAAmB;AAAA,QAC3B,SAAS,8CAA8C,OAAO,KAAK,IAAI,CAAC;AAAA,MAC1E,CAAC;AAAA,EACL;AACF;AAEO,IAAM,eAAe,CAAC,MAAY,eAAiC;AACxE,QAAM,QAAQ,SAAS,IAAI;AAE3B,MAAI,eAAe,QAAS,QAAO;AACnC,MAAI,eAAe,SAAU,QAAO,QAAQ;AAC5C,MAAI,eAAe,QAAS,QAAO,QAAQ;AAC3C,SAAO,QAAQ;AACjB;AAEO,IAAM,kBAAkB,CAAC,MAAY,eAA+B;AACzE,SAAO;AAAA,IACL,QAAQ,aAAa,MAAM,UAAU;AAAA,IACrC,UAAU,KAAK;AAAA,IACf,MAAM;AAAA,EACR;AACF;AAEO,IAAM,aAAa,CAAC,SAAiB,OAAa;AAAA,EACvD;AAAA,EACA,MAAM;AAAA,EACN,UAAU;AACZ;;;ACrCO,IAAM,eAAe,CAAC,MAAY,eAA6B;AACpE,QAAM,YAAY,gBAAgB,MAAM,OAAO;AAC/C,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,KAAK,MAAM,UAAU,SAAS,UAAU;AAAA,EAClD;AACF;AAEO,IAAM,WAAW,IAAI,UAAwB;AAClD,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,QAAQ,GAAG,MAAM,SAAS,UAAU,MAAM;AAAA,EACrD;AAEA,QAAM,YAAY,MAAM,CAAC;AAEzB,MAAI,CAAC,WAAW;AACd,WAAO,EAAE,QAAQ,GAAG,MAAM,SAAS,UAAU,MAAM;AAAA,EACrD;AAEA,QAAM,eAAe,UAAU;AAE/B,QAAM,aAAa,MAAM,OAAO,CAAC,KAAK,gBAAgB;AACpD,QAAI,YAAY,aAAa,cAAc;AACzC,YAAM,IAAI,mBAAmB;AAAA,QAC3B,SAAS,iCAAiC,YAAY,OAAO,YAAY,QAAQ;AAAA,MACnF,CAAC;AAAA,IACH;AACA,WAAO,MAAM,gBAAgB,aAAa,OAAO,EAAE;AAAA,EACrD,GAAG,CAAC;AAEJ,SAAO,EAAE,QAAQ,YAAY,MAAM,SAAS,UAAU,aAAa;AACrE;AAEO,IAAM,gBAAgB,CAAC,MAAY,aAA2B;AACnE,MAAI,CAAC,YAAY,YAAY,EAAG,QAAO;AAEvC,QAAM,YAAY,gBAAgB,MAAM,OAAO;AAC/C,QAAM,iBAAiB,KAAK,MAAM,UAAU,SAAS,QAAQ;AAE7D,SAAO;AAAA,IACL,GAAG;AAAA,IACH,QAAQ,KAAK,IAAI,GAAG,UAAU,SAAS,cAAc;AAAA,EACvD;AACF;;;ACzCO,SAAS,wBACd,SAGe;AACf,SAAO,OAAO,YAAkC;AAC9C,WAAO,QAAQ,OAAO;AAAA,EACxB;AACF;;;ACRA,SAAS,kBAAkB,KAA+B;AACxD,SAAO;AAAA,IACL,cAAc,IAAI,cAAc;AAAA,IAChC,kBAAkB,IAAI,kBAAkB;AAAA,IACxC,GAAI,IAAI,eAAe,KAAK,QAAQ;AAAA,MAClC,SAAS,IAAI,eAAe;AAAA,IAC9B;AAAA,IACA,GAAI,IAAI,wBAAwB,KAAK,QAAQ;AAAA,MAC3C,sBAAsB,IAAI,wBAAwB;AAAA,IACpD;AAAA,IACA,GAAI,IAAI,yBAAyB,KAAK,QAAQ;AAAA,MAC5C,uBAAuB,IAAI,yBAAyB;AAAA,IACtD;AAAA,IACA,GAAI,IAAI,0BAA0B,KAAK,QAAQ;AAAA,MAC7C,yBAAyB,IAAI,0BAA0B;AAAA,IACzD;AAAA,IACA,GAAI,IAAI,kBAAkB,KAAK,QAAQ;AAAA,MACrC,UAAU,IAAI,kBAAkB;AAAA,IAClC;AAAA,EACF;AACF;AAOO,SAAS,yBAAyB;AAAA,EACvC;AAAA,EACA,SAAS;AACX,GAA0E;AACxE,SAAO;AAAA,IACL,OAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,IACF,MAA+D;AAC7D,YAAM,SAAS,IAAI,gBAAgB,EAAE,UAAU,QAAQ,CAAC;AACxD,UAAI,WAAY,QAAO,IAAI,WAAW,UAAU;AAChD,UAAI,cAAe,QAAO,IAAI,YAAY,aAAa;AAEvD,YAAM,MAAM,GAAG,MAAM,uBAAuB,MAAM;AAClD,YAAM,UAAkC,SACpC,EAAE,eAAe,UAAU,MAAM,GAAG,IACpC,CAAC;AAEL,UAAI;AACJ,UAAI;AACF,cAAM,MAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,CAAC;AACxC,YAAI,CAAC,IAAI,GAAI,QAAO;AACpB,eAAQ,MAAM,IAAI,KAAK;AAAA,MACzB,QAAQ;AACN,eAAO;AAAA,MACT;AAEA,UAAI,CAAC,KAAM,QAAO;AAElB,YAAM,OAAO,KAAK,OAAO;AACzB,YAAM,MAAM,OAAO,CAAC;AACpB,UAAI,CAAC,IAAK,QAAO;AAEjB,aAAO,kBAAkB,GAAG;AAAA,IAC9B;AAAA,EACF;AACF;;;AC/DO,SAAS,0BACd,YACe;AACf,SAAO,wBAAwB,CAAC,EAAE,QAAQ,MAA4B;AACpE,WAAO,WAAW,OAAO;AAAA,EAC3B,CAAC;AACH;","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('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"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ import { JSONObject, LanguageModelV3, LanguageModelV3Usage, SharedV3ProviderMeta
|
|
|
3
3
|
type Destination<TTags extends DefaultTags = DefaultTags> = (event: BillingEvent<TTags>) => Promise<void> | void;
|
|
4
4
|
|
|
5
5
|
interface Usage {
|
|
6
|
-
readonly
|
|
6
|
+
readonly subProvider?: string;
|
|
7
7
|
readonly inputTokens: number;
|
|
8
8
|
readonly outputTokens: number;
|
|
9
9
|
readonly totalTokens: number;
|
|
@@ -26,9 +26,16 @@ type EventBuilder<TPayload, TTags extends DefaultTags = DefaultTags> = (payload:
|
|
|
26
26
|
|
|
27
27
|
type DefaultTags = JSONObject;
|
|
28
28
|
interface BaseBillingMiddlewareOptions<TTags extends JSONObject = DefaultTags> {
|
|
29
|
+
/** One or more billing destinations that receive each emitted {@link BillingEvent}. */
|
|
29
30
|
destinations?: Destination<TTags>[];
|
|
31
|
+
/** Tags merged into every emitted event. */
|
|
30
32
|
defaultTags?: TTags;
|
|
33
|
+
/**
|
|
34
|
+
* Edge-runtime hook (e.g. `ctx.waitUntil`) used to keep the process alive
|
|
35
|
+
* while billing events are flushed asynchronously.
|
|
36
|
+
*/
|
|
31
37
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
38
|
+
/** Called when an error occurs during event extraction or dispatch. Defaults to a silent no-op. */
|
|
32
39
|
onError?: (error: unknown) => void;
|
|
33
40
|
}
|
|
34
41
|
|
|
@@ -51,11 +58,28 @@ interface ModelPricing {
|
|
|
51
58
|
type PriceResolverContext = {
|
|
52
59
|
modelId: string;
|
|
53
60
|
providerId?: string;
|
|
54
|
-
|
|
61
|
+
subProvider?: string;
|
|
55
62
|
quantization?: string;
|
|
56
63
|
};
|
|
57
64
|
type PriceResolver = (context: PriceResolverContext) => Promise<ModelPricing | undefined>;
|
|
58
65
|
|
|
66
|
+
interface MeterMetadata {
|
|
67
|
+
generation_id: string;
|
|
68
|
+
model_id: string;
|
|
69
|
+
provider: string;
|
|
70
|
+
sub_provider?: string;
|
|
71
|
+
input_tokens?: number;
|
|
72
|
+
output_tokens?: number;
|
|
73
|
+
total_tokens?: number;
|
|
74
|
+
reasoning_tokens?: number;
|
|
75
|
+
cache_read_tokens?: number;
|
|
76
|
+
cache_write_tokens?: number;
|
|
77
|
+
request_count?: number;
|
|
78
|
+
raw_provider_cost?: number;
|
|
79
|
+
raw_upstream_inference_cost?: number;
|
|
80
|
+
[key: string]: string | number | undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
59
83
|
interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {
|
|
60
84
|
responseId: string | undefined;
|
|
61
85
|
model: LanguageModelV3;
|
|
@@ -63,16 +87,45 @@ interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {
|
|
|
63
87
|
providerMetadata: SharedV3ProviderMetadata | undefined;
|
|
64
88
|
tags: TTags;
|
|
65
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Configuration for {@link createV3BillingMiddleware}.
|
|
92
|
+
*
|
|
93
|
+
* Extends {@link BaseBillingMiddlewareOptions} (`destinations`, `defaultTags`, `waitUntil`, `onError`) and
|
|
94
|
+
* requires an {@link EventBuilder} to construct the {@link BillingEvent}.
|
|
95
|
+
*
|
|
96
|
+
* @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.
|
|
97
|
+
*/
|
|
66
98
|
interface BillingMiddlewareV3Options<TTags extends DefaultTags = DefaultTags> extends BaseBillingMiddlewareOptions<TTags> {
|
|
99
|
+
/** Builds a billing event from the model response data. */
|
|
67
100
|
buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;
|
|
68
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Creates a billing middleware for the Language Model V3 API.
|
|
104
|
+
*
|
|
105
|
+
* @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.
|
|
106
|
+
* @param options - Billing options; see {@link BillingMiddlewareV3Options}.
|
|
107
|
+
* @returns The billing middleware.
|
|
108
|
+
*/
|
|
69
109
|
declare function createV3BillingMiddleware<TTags extends DefaultTags = DefaultTags>(options: BillingMiddlewareV3Options<TTags>): LanguageModelV3Middleware;
|
|
70
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Creates a destination wrapper that normalizes destination handler errors.
|
|
113
|
+
*
|
|
114
|
+
* @param destinationId - Unique identifier for the destination.
|
|
115
|
+
* @param handler - Destination implementation invoked for each billing event.
|
|
116
|
+
* @returns A destination function that wraps thrown errors as AiBillingDestinationError.
|
|
117
|
+
*/
|
|
71
118
|
declare function createDestination<TTags extends DefaultTags = DefaultTags>(destinationId: string, handler: (event: BillingEvent<TTags>) => Promise<void> | void): Destination<TTags>;
|
|
72
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Creates a destination that logs billing events to the console.
|
|
122
|
+
*
|
|
123
|
+
* @returns A destination that prints each event with full depth formatting.
|
|
124
|
+
*/
|
|
73
125
|
declare function consoleDestination<TTags extends DefaultTags = DefaultTags>(): Destination<TTags>;
|
|
74
126
|
|
|
75
127
|
declare const symbol$3: unique symbol;
|
|
128
|
+
/** Base error type for all ai-billing package errors. */
|
|
76
129
|
declare class AIBillingError extends Error {
|
|
77
130
|
private readonly [symbol$3];
|
|
78
131
|
readonly cause?: unknown;
|
|
@@ -86,6 +139,7 @@ declare class AIBillingError extends Error {
|
|
|
86
139
|
}
|
|
87
140
|
|
|
88
141
|
declare const symbol$2: unique symbol;
|
|
142
|
+
/** Error thrown when billing data extraction fails. */
|
|
89
143
|
declare class AiBillingExtractorError extends AIBillingError {
|
|
90
144
|
private readonly [symbol$2];
|
|
91
145
|
constructor({ message, cause, }: {
|
|
@@ -96,8 +150,12 @@ declare class AiBillingExtractorError extends AIBillingError {
|
|
|
96
150
|
}
|
|
97
151
|
|
|
98
152
|
declare const symbol$1: unique symbol;
|
|
153
|
+
/**
|
|
154
|
+
* Error raised when billing data processing fails for a destination.
|
|
155
|
+
*/
|
|
99
156
|
declare class AiBillingDestinationError extends AIBillingError {
|
|
100
157
|
private readonly [symbol$1];
|
|
158
|
+
/** The ID of the destination that failed to process billing data. */
|
|
101
159
|
readonly destinationId?: string;
|
|
102
160
|
constructor({ destinationId, message, cause, }: {
|
|
103
161
|
destinationId?: string;
|
|
@@ -108,6 +166,7 @@ declare class AiBillingDestinationError extends AIBillingError {
|
|
|
108
166
|
}
|
|
109
167
|
|
|
110
168
|
declare const symbol: unique symbol;
|
|
169
|
+
/** Error thrown when a cost conversion or calculation fails. */
|
|
111
170
|
declare class AiBillingCostError extends AIBillingError {
|
|
112
171
|
private readonly [symbol];
|
|
113
172
|
constructor({ message, cause }: {
|
|
@@ -117,22 +176,121 @@ declare class AiBillingCostError extends AIBillingError {
|
|
|
117
176
|
static isInstance(error: unknown): error is AiBillingCostError;
|
|
118
177
|
}
|
|
119
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Returns the numeric amount of `cost` expressed in `targetUnit`.
|
|
181
|
+
*
|
|
182
|
+
* Values are converted via an integer nanos intermediate so fractional `base` / `cents` / `micros` amounts
|
|
183
|
+
* round consistently. Throws {@link AiBillingCostError} when `cost.unit` is not a known {@link CostUnit}.
|
|
184
|
+
*
|
|
185
|
+
* @param cost - Source {@link Cost} (amount + unit + currency).
|
|
186
|
+
* @param targetUnit - Unit for the returned number (same scale as {@link Cost} amounts for that unit).
|
|
187
|
+
* @returns The amount in `targetUnit`; for `nanos` this is a whole number of nanos.
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
120
190
|
declare const costToNumber: (cost: Cost, targetUnit: CostUnit) => number;
|
|
191
|
+
/**
|
|
192
|
+
* Converts a {@link Cost} to the same amount in a different {@link CostUnit}, preserving `currency`.
|
|
193
|
+
*
|
|
194
|
+
* Implemented with {@link costToNumber}; the result is always a new object.
|
|
195
|
+
*
|
|
196
|
+
* @param cost - Source cost.
|
|
197
|
+
* @param targetUnit - Desired unit for `amount` on the returned object.
|
|
198
|
+
* @returns A new {@link Cost} with `unit: targetUnit` and `amount` in that unit's scale.
|
|
199
|
+
* @internal
|
|
200
|
+
*/
|
|
121
201
|
declare const convertCostUnit: (cost: Cost, targetUnit: CostUnit) => Cost;
|
|
202
|
+
/**
|
|
203
|
+
* Wraps a numeric rate as a {@link Cost} in `base` units and `USD` currency.
|
|
204
|
+
*
|
|
205
|
+
* Provider calculators pass per-token prices from {@link ModelPricing} here, then scale with
|
|
206
|
+
* {@link multiplyCost} using token counts.
|
|
207
|
+
*
|
|
208
|
+
* @param amount - Rate amount in base USD units (defaults to `0` when omitted).
|
|
209
|
+
* @returns A {@link Cost} with `unit: 'base'` and `currency: 'USD'`.
|
|
210
|
+
* @internal
|
|
211
|
+
*/
|
|
122
212
|
declare const rateToCost: (amount?: number) => Cost;
|
|
123
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Scales a {@link Cost} by `multiplier` (for example token count × per-token rate).
|
|
216
|
+
*
|
|
217
|
+
* Converts to {@link CostUnit} `nanos`, multiplies the integer nanos amount (rounded), and returns a
|
|
218
|
+
* {@link Cost} with `unit: 'nanos'` and the same `currency` as the input.
|
|
219
|
+
*
|
|
220
|
+
* @param cost - Base cost to scale.
|
|
221
|
+
* @param multiplier - Factor applied to the nanos amount (often a non-negative token count).
|
|
222
|
+
* @returns The scaled cost in nanos.
|
|
223
|
+
* @internal
|
|
224
|
+
*/
|
|
124
225
|
declare const multiplyCost: (cost: Cost, multiplier: number) => Cost;
|
|
226
|
+
/**
|
|
227
|
+
* Adds any number of {@link Cost} values after converting each to nanos.
|
|
228
|
+
*
|
|
229
|
+
* All arguments must share the same `currency`; otherwise throws {@link AiBillingCostError}. With no
|
|
230
|
+
* arguments, returns a zero USD cost in nanos. With a single cost, still normalizes to nanos.
|
|
231
|
+
*
|
|
232
|
+
* @param costs - Costs to sum (variadic).
|
|
233
|
+
* @returns The total as a {@link Cost} with `unit: 'nanos'` and the shared `currency`.
|
|
234
|
+
* @internal
|
|
235
|
+
*/
|
|
125
236
|
declare const addCosts: (...costs: Cost[]) => Cost;
|
|
237
|
+
/**
|
|
238
|
+
* Applies a fractional discount to `cost` in nanos: `amount * (1 - discount)`.
|
|
239
|
+
*
|
|
240
|
+
* If `discount` is falsy or `<= 0`, returns `cost` unchanged (same unit and amount). Otherwise converts to
|
|
241
|
+
* nanos, subtracts `round(amount * discount)`, and clamps the result at zero. Typical `discount` values are
|
|
242
|
+
* between `0` and `1` (for example `0.1` for 10% off).
|
|
243
|
+
*
|
|
244
|
+
* @param cost - Original cost.
|
|
245
|
+
* @param discount - Fraction of the nanos amount to remove (not a percentage label).
|
|
246
|
+
* @returns Either the original `cost` or a discounted {@link Cost} in nanos.
|
|
247
|
+
* @internal
|
|
248
|
+
*/
|
|
126
249
|
declare const applyDiscount: (cost: Cost, discount: number) => Cost;
|
|
127
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Creates a base price resolver that wraps a handler function.
|
|
253
|
+
* @param handler - The function that resolves model pricing.
|
|
254
|
+
* @returns A price resolver that wraps the handler function.
|
|
255
|
+
*/
|
|
128
256
|
declare function createBasePriceResolver(handler: (context: PriceResolverContext) => ModelPricing | undefined | Promise<ModelPricing | undefined>): PriceResolver;
|
|
129
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Configuration for {@link createNarevPriceResolver}.
|
|
260
|
+
*/
|
|
130
261
|
type NarevPriceResolverOptions = {
|
|
262
|
+
/** API key used for authenticated pricing requests. */
|
|
131
263
|
apiKey: string;
|
|
264
|
+
/** Optional base URL for the Narev API. */
|
|
132
265
|
apiUrl?: string;
|
|
133
266
|
};
|
|
134
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Creates a price resolver that fetches model pricing from the Narev API.
|
|
269
|
+
*
|
|
270
|
+
* @param options - Resolver options; see {@link NarevPriceResolverOptions}.
|
|
271
|
+
* @returns A base price resolver that resolves model pricing from Narev.
|
|
272
|
+
*/
|
|
273
|
+
declare function createNarevPriceResolver(options: NarevPriceResolverOptions): PriceResolver;
|
|
135
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Creates a price resolver that uses a static pricing map.
|
|
277
|
+
* @param pricingMap - A mapping of model IDs to model pricing.
|
|
278
|
+
* @returns A price resolver that uses the static pricing map.
|
|
279
|
+
*/
|
|
136
280
|
declare function createObjectPriceResolver(pricingMap: Record<string, ModelPricing>): PriceResolver;
|
|
137
281
|
|
|
138
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Casts a billing event into a JSON object payload.
|
|
284
|
+
* @param event - The billing event to cast.
|
|
285
|
+
* @returns The billing event represented as a JSON object.
|
|
286
|
+
*/
|
|
287
|
+
declare function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Converts a billing event into a meter metadata object.
|
|
291
|
+
* @param event - The billing event to convert.
|
|
292
|
+
* @returns The meter metadata object.
|
|
293
|
+
*/
|
|
294
|
+
declare function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(event: BillingEvent<TTags>): MeterMetadata;
|
|
295
|
+
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { JSONObject, LanguageModelV3, LanguageModelV3Usage, SharedV3ProviderMeta
|
|
|
3
3
|
type Destination<TTags extends DefaultTags = DefaultTags> = (event: BillingEvent<TTags>) => Promise<void> | void;
|
|
4
4
|
|
|
5
5
|
interface Usage {
|
|
6
|
-
readonly
|
|
6
|
+
readonly subProvider?: string;
|
|
7
7
|
readonly inputTokens: number;
|
|
8
8
|
readonly outputTokens: number;
|
|
9
9
|
readonly totalTokens: number;
|
|
@@ -26,9 +26,16 @@ type EventBuilder<TPayload, TTags extends DefaultTags = DefaultTags> = (payload:
|
|
|
26
26
|
|
|
27
27
|
type DefaultTags = JSONObject;
|
|
28
28
|
interface BaseBillingMiddlewareOptions<TTags extends JSONObject = DefaultTags> {
|
|
29
|
+
/** One or more billing destinations that receive each emitted {@link BillingEvent}. */
|
|
29
30
|
destinations?: Destination<TTags>[];
|
|
31
|
+
/** Tags merged into every emitted event. */
|
|
30
32
|
defaultTags?: TTags;
|
|
33
|
+
/**
|
|
34
|
+
* Edge-runtime hook (e.g. `ctx.waitUntil`) used to keep the process alive
|
|
35
|
+
* while billing events are flushed asynchronously.
|
|
36
|
+
*/
|
|
31
37
|
waitUntil?: (promise: Promise<unknown>) => void;
|
|
38
|
+
/** Called when an error occurs during event extraction or dispatch. Defaults to a silent no-op. */
|
|
32
39
|
onError?: (error: unknown) => void;
|
|
33
40
|
}
|
|
34
41
|
|
|
@@ -51,11 +58,28 @@ interface ModelPricing {
|
|
|
51
58
|
type PriceResolverContext = {
|
|
52
59
|
modelId: string;
|
|
53
60
|
providerId?: string;
|
|
54
|
-
|
|
61
|
+
subProvider?: string;
|
|
55
62
|
quantization?: string;
|
|
56
63
|
};
|
|
57
64
|
type PriceResolver = (context: PriceResolverContext) => Promise<ModelPricing | undefined>;
|
|
58
65
|
|
|
66
|
+
interface MeterMetadata {
|
|
67
|
+
generation_id: string;
|
|
68
|
+
model_id: string;
|
|
69
|
+
provider: string;
|
|
70
|
+
sub_provider?: string;
|
|
71
|
+
input_tokens?: number;
|
|
72
|
+
output_tokens?: number;
|
|
73
|
+
total_tokens?: number;
|
|
74
|
+
reasoning_tokens?: number;
|
|
75
|
+
cache_read_tokens?: number;
|
|
76
|
+
cache_write_tokens?: number;
|
|
77
|
+
request_count?: number;
|
|
78
|
+
raw_provider_cost?: number;
|
|
79
|
+
raw_upstream_inference_cost?: number;
|
|
80
|
+
[key: string]: string | number | undefined;
|
|
81
|
+
}
|
|
82
|
+
|
|
59
83
|
interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {
|
|
60
84
|
responseId: string | undefined;
|
|
61
85
|
model: LanguageModelV3;
|
|
@@ -63,16 +87,45 @@ interface BuildV3EventPayload<TTags extends DefaultTags = DefaultTags> {
|
|
|
63
87
|
providerMetadata: SharedV3ProviderMetadata | undefined;
|
|
64
88
|
tags: TTags;
|
|
65
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Configuration for {@link createV3BillingMiddleware}.
|
|
92
|
+
*
|
|
93
|
+
* Extends {@link BaseBillingMiddlewareOptions} (`destinations`, `defaultTags`, `waitUntil`, `onError`) and
|
|
94
|
+
* requires an {@link EventBuilder} to construct the {@link BillingEvent}.
|
|
95
|
+
*
|
|
96
|
+
* @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.
|
|
97
|
+
*/
|
|
66
98
|
interface BillingMiddlewareV3Options<TTags extends DefaultTags = DefaultTags> extends BaseBillingMiddlewareOptions<TTags> {
|
|
99
|
+
/** Builds a billing event from the model response data. */
|
|
67
100
|
buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;
|
|
68
101
|
}
|
|
102
|
+
/**
|
|
103
|
+
* Creates a billing middleware for the Language Model V3 API.
|
|
104
|
+
*
|
|
105
|
+
* @typeParam TTags - The shape of the tags object, extending {@link DefaultTags}.
|
|
106
|
+
* @param options - Billing options; see {@link BillingMiddlewareV3Options}.
|
|
107
|
+
* @returns The billing middleware.
|
|
108
|
+
*/
|
|
69
109
|
declare function createV3BillingMiddleware<TTags extends DefaultTags = DefaultTags>(options: BillingMiddlewareV3Options<TTags>): LanguageModelV3Middleware;
|
|
70
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Creates a destination wrapper that normalizes destination handler errors.
|
|
113
|
+
*
|
|
114
|
+
* @param destinationId - Unique identifier for the destination.
|
|
115
|
+
* @param handler - Destination implementation invoked for each billing event.
|
|
116
|
+
* @returns A destination function that wraps thrown errors as AiBillingDestinationError.
|
|
117
|
+
*/
|
|
71
118
|
declare function createDestination<TTags extends DefaultTags = DefaultTags>(destinationId: string, handler: (event: BillingEvent<TTags>) => Promise<void> | void): Destination<TTags>;
|
|
72
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Creates a destination that logs billing events to the console.
|
|
122
|
+
*
|
|
123
|
+
* @returns A destination that prints each event with full depth formatting.
|
|
124
|
+
*/
|
|
73
125
|
declare function consoleDestination<TTags extends DefaultTags = DefaultTags>(): Destination<TTags>;
|
|
74
126
|
|
|
75
127
|
declare const symbol$3: unique symbol;
|
|
128
|
+
/** Base error type for all ai-billing package errors. */
|
|
76
129
|
declare class AIBillingError extends Error {
|
|
77
130
|
private readonly [symbol$3];
|
|
78
131
|
readonly cause?: unknown;
|
|
@@ -86,6 +139,7 @@ declare class AIBillingError extends Error {
|
|
|
86
139
|
}
|
|
87
140
|
|
|
88
141
|
declare const symbol$2: unique symbol;
|
|
142
|
+
/** Error thrown when billing data extraction fails. */
|
|
89
143
|
declare class AiBillingExtractorError extends AIBillingError {
|
|
90
144
|
private readonly [symbol$2];
|
|
91
145
|
constructor({ message, cause, }: {
|
|
@@ -96,8 +150,12 @@ declare class AiBillingExtractorError extends AIBillingError {
|
|
|
96
150
|
}
|
|
97
151
|
|
|
98
152
|
declare const symbol$1: unique symbol;
|
|
153
|
+
/**
|
|
154
|
+
* Error raised when billing data processing fails for a destination.
|
|
155
|
+
*/
|
|
99
156
|
declare class AiBillingDestinationError extends AIBillingError {
|
|
100
157
|
private readonly [symbol$1];
|
|
158
|
+
/** The ID of the destination that failed to process billing data. */
|
|
101
159
|
readonly destinationId?: string;
|
|
102
160
|
constructor({ destinationId, message, cause, }: {
|
|
103
161
|
destinationId?: string;
|
|
@@ -108,6 +166,7 @@ declare class AiBillingDestinationError extends AIBillingError {
|
|
|
108
166
|
}
|
|
109
167
|
|
|
110
168
|
declare const symbol: unique symbol;
|
|
169
|
+
/** Error thrown when a cost conversion or calculation fails. */
|
|
111
170
|
declare class AiBillingCostError extends AIBillingError {
|
|
112
171
|
private readonly [symbol];
|
|
113
172
|
constructor({ message, cause }: {
|
|
@@ -117,22 +176,121 @@ declare class AiBillingCostError extends AIBillingError {
|
|
|
117
176
|
static isInstance(error: unknown): error is AiBillingCostError;
|
|
118
177
|
}
|
|
119
178
|
|
|
179
|
+
/**
|
|
180
|
+
* Returns the numeric amount of `cost` expressed in `targetUnit`.
|
|
181
|
+
*
|
|
182
|
+
* Values are converted via an integer nanos intermediate so fractional `base` / `cents` / `micros` amounts
|
|
183
|
+
* round consistently. Throws {@link AiBillingCostError} when `cost.unit` is not a known {@link CostUnit}.
|
|
184
|
+
*
|
|
185
|
+
* @param cost - Source {@link Cost} (amount + unit + currency).
|
|
186
|
+
* @param targetUnit - Unit for the returned number (same scale as {@link Cost} amounts for that unit).
|
|
187
|
+
* @returns The amount in `targetUnit`; for `nanos` this is a whole number of nanos.
|
|
188
|
+
* @internal
|
|
189
|
+
*/
|
|
120
190
|
declare const costToNumber: (cost: Cost, targetUnit: CostUnit) => number;
|
|
191
|
+
/**
|
|
192
|
+
* Converts a {@link Cost} to the same amount in a different {@link CostUnit}, preserving `currency`.
|
|
193
|
+
*
|
|
194
|
+
* Implemented with {@link costToNumber}; the result is always a new object.
|
|
195
|
+
*
|
|
196
|
+
* @param cost - Source cost.
|
|
197
|
+
* @param targetUnit - Desired unit for `amount` on the returned object.
|
|
198
|
+
* @returns A new {@link Cost} with `unit: targetUnit` and `amount` in that unit's scale.
|
|
199
|
+
* @internal
|
|
200
|
+
*/
|
|
121
201
|
declare const convertCostUnit: (cost: Cost, targetUnit: CostUnit) => Cost;
|
|
202
|
+
/**
|
|
203
|
+
* Wraps a numeric rate as a {@link Cost} in `base` units and `USD` currency.
|
|
204
|
+
*
|
|
205
|
+
* Provider calculators pass per-token prices from {@link ModelPricing} here, then scale with
|
|
206
|
+
* {@link multiplyCost} using token counts.
|
|
207
|
+
*
|
|
208
|
+
* @param amount - Rate amount in base USD units (defaults to `0` when omitted).
|
|
209
|
+
* @returns A {@link Cost} with `unit: 'base'` and `currency: 'USD'`.
|
|
210
|
+
* @internal
|
|
211
|
+
*/
|
|
122
212
|
declare const rateToCost: (amount?: number) => Cost;
|
|
123
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Scales a {@link Cost} by `multiplier` (for example token count × per-token rate).
|
|
216
|
+
*
|
|
217
|
+
* Converts to {@link CostUnit} `nanos`, multiplies the integer nanos amount (rounded), and returns a
|
|
218
|
+
* {@link Cost} with `unit: 'nanos'` and the same `currency` as the input.
|
|
219
|
+
*
|
|
220
|
+
* @param cost - Base cost to scale.
|
|
221
|
+
* @param multiplier - Factor applied to the nanos amount (often a non-negative token count).
|
|
222
|
+
* @returns The scaled cost in nanos.
|
|
223
|
+
* @internal
|
|
224
|
+
*/
|
|
124
225
|
declare const multiplyCost: (cost: Cost, multiplier: number) => Cost;
|
|
226
|
+
/**
|
|
227
|
+
* Adds any number of {@link Cost} values after converting each to nanos.
|
|
228
|
+
*
|
|
229
|
+
* All arguments must share the same `currency`; otherwise throws {@link AiBillingCostError}. With no
|
|
230
|
+
* arguments, returns a zero USD cost in nanos. With a single cost, still normalizes to nanos.
|
|
231
|
+
*
|
|
232
|
+
* @param costs - Costs to sum (variadic).
|
|
233
|
+
* @returns The total as a {@link Cost} with `unit: 'nanos'` and the shared `currency`.
|
|
234
|
+
* @internal
|
|
235
|
+
*/
|
|
125
236
|
declare const addCosts: (...costs: Cost[]) => Cost;
|
|
237
|
+
/**
|
|
238
|
+
* Applies a fractional discount to `cost` in nanos: `amount * (1 - discount)`.
|
|
239
|
+
*
|
|
240
|
+
* If `discount` is falsy or `<= 0`, returns `cost` unchanged (same unit and amount). Otherwise converts to
|
|
241
|
+
* nanos, subtracts `round(amount * discount)`, and clamps the result at zero. Typical `discount` values are
|
|
242
|
+
* between `0` and `1` (for example `0.1` for 10% off).
|
|
243
|
+
*
|
|
244
|
+
* @param cost - Original cost.
|
|
245
|
+
* @param discount - Fraction of the nanos amount to remove (not a percentage label).
|
|
246
|
+
* @returns Either the original `cost` or a discounted {@link Cost} in nanos.
|
|
247
|
+
* @internal
|
|
248
|
+
*/
|
|
126
249
|
declare const applyDiscount: (cost: Cost, discount: number) => Cost;
|
|
127
250
|
|
|
251
|
+
/**
|
|
252
|
+
* Creates a base price resolver that wraps a handler function.
|
|
253
|
+
* @param handler - The function that resolves model pricing.
|
|
254
|
+
* @returns A price resolver that wraps the handler function.
|
|
255
|
+
*/
|
|
128
256
|
declare function createBasePriceResolver(handler: (context: PriceResolverContext) => ModelPricing | undefined | Promise<ModelPricing | undefined>): PriceResolver;
|
|
129
257
|
|
|
258
|
+
/**
|
|
259
|
+
* Configuration for {@link createNarevPriceResolver}.
|
|
260
|
+
*/
|
|
130
261
|
type NarevPriceResolverOptions = {
|
|
262
|
+
/** API key used for authenticated pricing requests. */
|
|
131
263
|
apiKey: string;
|
|
264
|
+
/** Optional base URL for the Narev API. */
|
|
132
265
|
apiUrl?: string;
|
|
133
266
|
};
|
|
134
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Creates a price resolver that fetches model pricing from the Narev API.
|
|
269
|
+
*
|
|
270
|
+
* @param options - Resolver options; see {@link NarevPriceResolverOptions}.
|
|
271
|
+
* @returns A base price resolver that resolves model pricing from Narev.
|
|
272
|
+
*/
|
|
273
|
+
declare function createNarevPriceResolver(options: NarevPriceResolverOptions): PriceResolver;
|
|
135
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Creates a price resolver that uses a static pricing map.
|
|
277
|
+
* @param pricingMap - A mapping of model IDs to model pricing.
|
|
278
|
+
* @returns A price resolver that uses the static pricing map.
|
|
279
|
+
*/
|
|
136
280
|
declare function createObjectPriceResolver(pricingMap: Record<string, ModelPricing>): PriceResolver;
|
|
137
281
|
|
|
138
|
-
|
|
282
|
+
/**
|
|
283
|
+
* Casts a billing event into a JSON object payload.
|
|
284
|
+
* @param event - The billing event to cast.
|
|
285
|
+
* @returns The billing event represented as a JSON object.
|
|
286
|
+
*/
|
|
287
|
+
declare function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Converts a billing event into a meter metadata object.
|
|
291
|
+
* @param event - The billing event to convert.
|
|
292
|
+
* @returns The meter metadata object.
|
|
293
|
+
*/
|
|
294
|
+
declare function buildMeterMetadata<TTags extends DefaultTags = DefaultTags>(event: BillingEvent<TTags>): MeterMetadata;
|
|
295
|
+
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,38 @@ function toJSONObject(event) {
|
|
|
3
3
|
return event;
|
|
4
4
|
}
|
|
5
5
|
|
|
6
|
+
// src/event/to-meter-metadata.ts
|
|
7
|
+
function buildMeterMetadata(event) {
|
|
8
|
+
const u = event.usage ?? {};
|
|
9
|
+
const dimensions = {
|
|
10
|
+
generation_id: event.generationId,
|
|
11
|
+
model_id: event.modelId,
|
|
12
|
+
provider: event.provider
|
|
13
|
+
};
|
|
14
|
+
const addOptional = (key, value) => {
|
|
15
|
+
if (value !== void 0 && value !== null) {
|
|
16
|
+
dimensions[key] = value;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
addOptional("sub_provider", u.subProvider);
|
|
20
|
+
addOptional("input_tokens", u.inputTokens);
|
|
21
|
+
addOptional("output_tokens", u.outputTokens);
|
|
22
|
+
addOptional("total_tokens", u.totalTokens);
|
|
23
|
+
addOptional("reasoning_tokens", u.reasoningTokens);
|
|
24
|
+
addOptional("cache_read_tokens", u.cacheReadTokens);
|
|
25
|
+
addOptional("cache_write_tokens", u.cacheWriteTokens);
|
|
26
|
+
addOptional("request_count", u.requestCount);
|
|
27
|
+
addOptional("raw_provider_cost", u.rawProviderCost);
|
|
28
|
+
addOptional("raw_upstream_inference_cost", u.rawUpstreamInferenceCost);
|
|
29
|
+
if (event.tags) {
|
|
30
|
+
for (const [key, value] of Object.entries(event.tags)) {
|
|
31
|
+
if (value == null) continue;
|
|
32
|
+
dimensions[`tag_${key}`] = typeof value === "object" ? JSON.stringify(value) : value;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return dimensions;
|
|
36
|
+
}
|
|
37
|
+
|
|
6
38
|
// src/ai-sdk/language-model-middleware/v3/language-model-v3-base-billing-middleware.ts
|
|
7
39
|
function createV3BillingMiddleware(options) {
|
|
8
40
|
const { buildEvent, destinations, defaultTags, waitUntil, onError } = options;
|
|
@@ -157,6 +189,7 @@ var marker3 = `ai-billing.error.${name2}`;
|
|
|
157
189
|
var symbol3 = Symbol.for(marker3);
|
|
158
190
|
var AiBillingDestinationError = class extends AIBillingError {
|
|
159
191
|
[symbol3] = true;
|
|
192
|
+
/** The ID of the destination that failed to process billing data. */
|
|
160
193
|
destinationId;
|
|
161
194
|
constructor({
|
|
162
195
|
destinationId,
|
|
@@ -313,19 +346,17 @@ function rowToModelPricing(row) {
|
|
|
313
346
|
}
|
|
314
347
|
};
|
|
315
348
|
}
|
|
316
|
-
function createNarevPriceResolver({
|
|
317
|
-
apiKey,
|
|
318
|
-
apiUrl = "https://narev.ai"
|
|
319
|
-
}) {
|
|
349
|
+
function createNarevPriceResolver(options) {
|
|
350
|
+
const { apiKey, apiUrl = "https://narev.ai" } = options;
|
|
320
351
|
return createBasePriceResolver(
|
|
321
352
|
async ({
|
|
322
353
|
modelId,
|
|
323
354
|
providerId,
|
|
324
|
-
|
|
355
|
+
subProvider
|
|
325
356
|
}) => {
|
|
326
357
|
const params = new URLSearchParams({ model_id: modelId });
|
|
327
358
|
if (providerId) params.set("gateway", providerId);
|
|
328
|
-
if (
|
|
359
|
+
if (subProvider) params.set("provider", subProvider);
|
|
329
360
|
const url = `${apiUrl}/api/models/pricing?${params}`;
|
|
330
361
|
const headers = apiKey ? { Authorization: `Bearer ${apiKey}` } : {};
|
|
331
362
|
let data;
|
|
@@ -358,6 +389,7 @@ export {
|
|
|
358
389
|
AiBillingExtractorError,
|
|
359
390
|
addCosts,
|
|
360
391
|
applyDiscount,
|
|
392
|
+
buildMeterMetadata,
|
|
361
393
|
consoleDestination,
|
|
362
394
|
convertCostUnit,
|
|
363
395
|
costToNumber,
|
|
@@ -367,6 +399,7 @@ export {
|
|
|
367
399
|
createObjectPriceResolver,
|
|
368
400
|
createV3BillingMiddleware,
|
|
369
401
|
multiplyCost,
|
|
370
|
-
rateToCost
|
|
402
|
+
rateToCost,
|
|
403
|
+
toJSONObject
|
|
371
404
|
};
|
|
372
405
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/event/to-json-object.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\nexport function toJSONObject(event: BillingEvent<DefaultTags>): JSONObject {\n return event as unknown as JSONObject;\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\nexport interface BillingMiddlewareV3Options<\n TTags extends DefaultTags = DefaultTags,\n> extends BaseBillingMiddlewareOptions<TTags> {\n buildEvent: EventBuilder<BuildV3EventPayload<TTags>, TTags>;\n}\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\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\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\nexport class AiBillingDestinationError extends AIBillingError {\n private readonly [symbol] = true;\n\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\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\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';\nimport { JSONObject } from '@ai-sdk/provider';\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\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\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\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\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\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\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\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 { ModelPricing, PriceResolverContext } 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\nexport type NarevPriceResolverOptions = {\n apiKey: string;\n apiUrl?: string;\n};\n\nexport function createNarevPriceResolver({\n apiKey,\n apiUrl = 'https://narev.ai',\n}: NarevPriceResolverOptions): ReturnType<typeof createBasePriceResolver> {\n return createBasePriceResolver(\n async ({\n modelId,\n providerId,\n subProviderId,\n }: PriceResolverContext): Promise<ModelPricing | undefined> => {\n const params = new URLSearchParams({ model_id: modelId });\n if (providerId) params.set('gateway', providerId);\n if (subProviderId) params.set('provider', subProviderId);\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\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('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"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-billing/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -31,12 +31,14 @@
|
|
|
31
31
|
],
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@ai-sdk/provider": "^3.0.8",
|
|
34
|
+
"@edge-runtime/vm": "^5.0.0",
|
|
34
35
|
"tsup": "^8.5.1",
|
|
36
|
+
"typedoc": "^0.28.19",
|
|
37
|
+
"typedoc-plugin-markdown": "^4.11.0",
|
|
35
38
|
"typescript": "5.9.2",
|
|
36
39
|
"vitest": "4.1.1",
|
|
37
|
-
"@edge-runtime/vm": "^5.0.0",
|
|
38
40
|
"zod": "^4.3.6",
|
|
39
|
-
"@ai-billing/testing": "0.0.
|
|
41
|
+
"@ai-billing/testing": "0.0.3",
|
|
40
42
|
"@ai-billing/typescript-config": "0.0.1"
|
|
41
43
|
},
|
|
42
44
|
"peerDependencies": {
|
|
@@ -48,6 +50,7 @@
|
|
|
48
50
|
"scripts": {
|
|
49
51
|
"build": "tsup",
|
|
50
52
|
"check-types": "tsc --noEmit",
|
|
53
|
+
"docs:generate": "typedoc --options typedoc.json",
|
|
51
54
|
"lint": "oxlint",
|
|
52
55
|
"dev": "tsup --watch",
|
|
53
56
|
"test": "vitest run",
|