vibezcheck 0.5.11 → 0.5.13

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.
Files changed (58) hide show
  1. package/dist/ai-sdk/index.d.mts +5 -5
  2. package/dist/ai-sdk/index.d.ts +5 -5
  3. package/dist/ai-sdk/index.js +45 -5
  4. package/dist/ai-sdk/index.js.map +1 -1
  5. package/dist/ai-sdk/index.mjs +45 -5
  6. package/dist/ai-sdk/index.mjs.map +1 -1
  7. package/dist/ai-sdk/middleware.d.mts +3 -3
  8. package/dist/ai-sdk/middleware.d.ts +3 -3
  9. package/dist/ai-sdk/middleware.js +37 -3
  10. package/dist/ai-sdk/middleware.js.map +1 -1
  11. package/dist/ai-sdk/middleware.mjs +37 -3
  12. package/dist/ai-sdk/middleware.mjs.map +1 -1
  13. package/dist/billing/index.d.mts +8 -6
  14. package/dist/billing/index.d.ts +8 -6
  15. package/dist/billing/index.js +312 -6
  16. package/dist/billing/index.js.map +1 -1
  17. package/dist/billing/index.mjs +319 -6
  18. package/dist/billing/index.mjs.map +1 -1
  19. package/dist/cli/index.js +8 -1
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/cli/index.mjs +8 -1
  22. package/dist/cli/index.mjs.map +1 -1
  23. package/dist/{client-eXSwD_kI.d.ts → client-0CuOBECi.d.ts} +1 -1
  24. package/dist/{client-ttJwYM7x.d.mts → client-xP86Qg_b.d.mts} +1 -1
  25. package/dist/customers/index.d.mts +1 -1
  26. package/dist/customers/index.d.ts +1 -1
  27. package/dist/database/index.d.mts +1 -1
  28. package/dist/database/index.d.ts +1 -1
  29. package/dist/index.d.mts +8 -8
  30. package/dist/index.d.ts +8 -8
  31. package/dist/index.js +52 -6
  32. package/dist/index.js.map +1 -1
  33. package/dist/index.mjs +52 -6
  34. package/dist/index.mjs.map +1 -1
  35. package/dist/meter/index.d.mts +2 -2
  36. package/dist/meter/index.d.ts +2 -2
  37. package/dist/meter/index.js +35 -2
  38. package/dist/meter/index.js.map +1 -1
  39. package/dist/meter/index.mjs +35 -2
  40. package/dist/meter/index.mjs.map +1 -1
  41. package/dist/pricing/index.d.mts +27 -3
  42. package/dist/pricing/index.d.ts +27 -3
  43. package/dist/pricing/index.js +34 -1
  44. package/dist/pricing/index.js.map +1 -1
  45. package/dist/pricing/index.mjs +34 -1
  46. package/dist/pricing/index.mjs.map +1 -1
  47. package/dist/react/index.d.mts +1 -1
  48. package/dist/react/index.d.ts +1 -1
  49. package/dist/{session-D9fdP255.d.mts → session-CueUIV77.d.mts} +10 -4
  50. package/dist/{session-CUnv_muf.d.ts → session-YF67Yij2.d.ts} +10 -4
  51. package/dist/{types-DHlsaLvI.d.mts → types-CqXTmCNv.d.mts} +2 -0
  52. package/dist/{types-DHlsaLvI.d.ts → types-CqXTmCNv.d.ts} +2 -0
  53. package/dist/{with-billing-DhHGWCAp.d.mts → with-billing-Df6izlJ4.d.mts} +4 -2
  54. package/dist/{with-billing-CVGxl3ot.d.ts → with-billing-DgQ380Zl.d.ts} +4 -2
  55. package/examples/nextjs-app-router-openai/package.json +1 -1
  56. package/examples/nextjs-saas-starter/package.json +1 -1
  57. package/manifest/pricing-v1.json +4904 -974
  58. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts","../../src/meter/batcher.ts","../../src/meter/extractors/openai.ts","../../src/meter/extractors/anthropic.ts","../../src/meter/extractors/gemini.ts","../../src/meter/extractors/generic.ts","../../src/meter/extractors/index.ts","../../src/pricing/sync.ts","../../src/pricing/table.ts","../../src/pricing/calculator.ts","../../src/customers/helpers.ts","../../src/meter/stream.ts","../../src/meter/client.ts","../../src/ai-sdk/with-billing.ts","../../src/ai-sdk/middleware.ts"],"sourcesContent":["/**\r\n * Known supported model identifiers with full IDE autocomplete\r\n */\r\nexport type SupportedOpenAIModel =\r\n | 'openai/gpt-4o'\r\n | 'openai/gpt-4o-mini'\r\n | 'openai/gpt-4.5-preview'\r\n | 'openai/gpt-4.1'\r\n | 'openai/gpt-4.1-nano'\r\n | 'openai/gpt-4-turbo'\r\n | 'openai/gpt-4'\r\n | 'openai/gpt-3.5-turbo'\r\n | 'openai/o1'\r\n | 'openai/o1-mini'\r\n | 'openai/o3'\r\n | 'openai/o3-mini'\r\n | 'openai/gpt-5'\r\n | 'openai/gpt-5-mini'\r\n | 'openai/gpt-5.6-sol'\r\n | 'openai/gpt-5.6-terra'\r\n | 'openai/gpt-5.6-luna'\r\n | 'openai/text-embedding-3-small'\r\n | 'openai/text-embedding-3-large'\r\n | 'gpt-4o'\r\n | 'gpt-4o-mini'\r\n | 'gpt-4.5-preview'\r\n | 'gpt-4.5'\r\n | 'gpt-4.1'\r\n | 'gpt-4.1-nano'\r\n | 'gpt-4-turbo'\r\n | 'gpt-4'\r\n | 'gpt-3.5-turbo'\r\n | 'o1'\r\n | 'o1-mini'\r\n | 'o3'\r\n | 'o3-mini'\r\n | 'gpt-5'\r\n | 'gpt-5-mini'\r\n | 'gpt-5.6-sol'\r\n | 'gpt-5.6-terra'\r\n | 'gpt-5.6-luna';\r\n\r\nexport type SupportedAnthropicModel =\r\n | 'anthropic/claude-3-7-sonnet'\r\n | 'anthropic/claude-3-5-sonnet'\r\n | 'anthropic/claude-3-5-haiku'\r\n | 'anthropic/claude-3-opus'\r\n | 'anthropic/claude-3-haiku'\r\n | 'anthropic/claude-2.1'\r\n | 'anthropic/claude-2.0'\r\n | 'anthropic/claude-opus-5'\r\n | 'anthropic/haiku-4.5'\r\n | 'claude-3-7-sonnet'\r\n | 'claude-3-5-sonnet'\r\n | 'claude-3-5-haiku'\r\n | 'claude-3-opus'\r\n | 'claude-3-haiku'\r\n | 'claude-2.1'\r\n | 'claude-2.0'\r\n | 'claude-opus-5'\r\n | 'haiku-4.5';\r\n\r\nexport type SupportedGoogleModel =\r\n | 'google/gemini-2.5-pro'\r\n | 'google/gemini-2.5-flash'\r\n | 'google/gemini-2.0-flash'\r\n | 'google/gemini-2.0-flash-lite'\r\n | 'google/gemini-2.0-pro'\r\n | 'google/gemini-1.5-pro'\r\n | 'google/gemini-1.5-flash'\r\n | 'google/gemini-1.5-flash-8b'\r\n | 'google/gemini-1.0-pro'\r\n | 'google/gemini-3.7-flash'\r\n | 'google/gemini-3.1-pro'\r\n | 'gemini-2.5-pro'\r\n | 'gemini-2.5-flash'\r\n | 'gemini-2.0-flash'\r\n | 'gemini-2.0-flash-lite'\r\n | 'gemini-2.0-pro'\r\n | 'gemini-1.5-pro'\r\n | 'gemini-1.5-flash'\r\n | 'gemini-1.5-flash-8b'\r\n | 'gemini-1.0-pro'\r\n | 'gemini-3.7-flash'\r\n | 'gemini-3.1-pro';\r\n\r\nexport type SupportedDeepSeekModel =\r\n | 'deepseek/deepseek-chat'\r\n | 'deepseek/deepseek-reasoner'\r\n | 'deepseek/deepseek-v3'\r\n | 'deepseek/deepseek-r1'\r\n | 'deepseek/deepseek-v4-pro'\r\n | 'deepseek-chat'\r\n | 'deepseek-reasoner'\r\n | 'deepseek-v3'\r\n | 'deepseek-r1'\r\n | 'deepseek-v4-pro';\r\n\r\nexport type SupportedXAIModel =\r\n | 'xai/grok-3'\r\n | 'xai/grok-3-mini'\r\n | 'xai/grok-2'\r\n | 'xai/grok-2-vision'\r\n | 'xai/grok-beta'\r\n | 'grok-3'\r\n | 'grok-3-mini'\r\n | 'grok-2'\r\n | 'grok-2-vision'\r\n | 'grok-beta';\r\n\r\nexport type SupportedMistralModel =\r\n | 'mistral/mistral-large-latest'\r\n | 'mistral/codestral-latest'\r\n | 'mistral/mistral-small-latest'\r\n | 'mistral/ministral-8b-latest'\r\n | 'mistral-large-latest'\r\n | 'codestral-latest'\r\n | 'mistral-small-latest'\r\n | 'ministral-8b-latest';\r\n\r\nexport type SupportedGroqModel =\r\n | 'groq/llama-3.3-70b-versatile'\r\n | 'groq/llama-3.1-70b-versatile'\r\n | 'groq/llama-3.1-8b-instant'\r\n | 'groq/deepseek-r1-distill-llama-70b'\r\n | 'llama-3.3-70b-versatile'\r\n | 'llama-3.1-70b-versatile'\r\n | 'llama-3.1-8b-instant'\r\n | 'deepseek-r1-distill-llama-70b';\r\n\r\nexport type SupportedCohereModel =\r\n | 'cohere/command-r-plus'\r\n | 'cohere/command-r'\r\n | 'command-r-plus'\r\n | 'command-r';\r\n\r\nexport type KnownModel =\r\n | SupportedOpenAIModel\r\n | SupportedAnthropicModel\r\n | SupportedGoogleModel\r\n | SupportedDeepSeekModel\r\n | SupportedXAIModel\r\n | SupportedMistralModel\r\n | SupportedGroqModel\r\n | SupportedCohereModel;\r\n\r\n/**\r\n * Union of all known model IDs with loose string fallback for custom / future models\r\n */\r\nexport type SupportedModel = KnownModel | (string & {});\r\n\r\n/**\r\n * Detailed token usage breakdown\r\n */\r\nexport interface TokenUsage {\r\n /** Input/Prompt tokens */\r\n inputTokens: number;\r\n /** Total output/completion tokens (including reasoning) */\r\n outputTokens: number;\r\n /** Total tokens (input + output) */\r\n totalTokens: number;\r\n /** Hidden reasoning / thinking tokens (e.g. o1/o3/GPT-5, Claude 3.7 Thinking, Gemini 3.7 Thoughts) */\r\n reasoningTokens?: number;\r\n /** Visible output tokens (outputTokens - reasoningTokens) */\r\n visibleOutputTokens?: number;\r\n /** Cached input tokens read from KV cache / prompt cache */\r\n cachedTokens?: number;\r\n /** Cache write / creation tokens */\r\n cacheWriteTokens?: number;\r\n}\r\n\r\n/**\r\n * Calculated inference cost breakdown\r\n */\r\nexport interface InferenceCost {\r\n /** Cost for standard input prompt tokens in USD */\r\n inputCostUSD: number;\r\n /** Cost for output completion tokens in USD */\r\n outputCostUSD: number;\r\n /** Cost for reasoning/thinking tokens in USD (if applicable) */\r\n reasoningCostUSD?: number;\r\n /** Savings from prompt caching in USD */\r\n cachedDiscountUSD?: number;\r\n /** Alias for cachedDiscountUSD */\r\n savingsUSD?: number;\r\n /** Total computed base inference cost in USD */\r\n totalUSD: number;\r\n /** Wholesale provider cost in USD */\r\n wholesaleTotalUSD?: number;\r\n /** Alias for wholesaleTotalUSD */\r\n wholesaleUSD?: number;\r\n /** Amount billed to customer in USD */\r\n billedUSD?: number;\r\n /** Net developer profit in USD */\r\n profitUSD?: number;\r\n /** Retail price after developer markup (if markup applied) */\r\n retailUSD?: number;\r\n /** Currency (defaults to 'USD') */\r\n currency: string;\r\n}\r\n\r\n/**\r\n * Structured Customer Information with rich metadata, multi-tenancy & billing attributes\r\n */\r\nexport interface CustomerInfo {\r\n /** Internal user ID or customer identifier ('usr_123', 'cus_xxx') */\r\n id?: string;\r\n /** Explicit user ID */\r\n userId?: string;\r\n /** Customer email */\r\n email?: string;\r\n /** Customer full name or business display name */\r\n name?: string;\r\n /** Phone number */\r\n phone?: string;\r\n /** Multi-tenant Organization or Company ID */\r\n orgId?: string;\r\n /** Organization / Company name */\r\n orgName?: string;\r\n /** Multi-tenant Organization ID alias */\r\n organizationId?: string;\r\n /** Team / Workspace identifier */\r\n teamId?: string;\r\n /** Workspace identifier alias */\r\n workspaceId?: string;\r\n /** User Role within organization (e.g. 'admin', 'member', 'owner') */\r\n role?: string;\r\n /** Subscription Plan name (e.g. 'free', 'starter', 'pro', 'enterprise') */\r\n plan?: string;\r\n /** Billing Tier (e.g. 'tier_1', 'growth', 'unlimited') */\r\n tier?: string;\r\n /** Billing currency (defaults to 'usd') */\r\n currency?: string;\r\n /** Flexible custom metadata (key-value attributes) */\r\n metadata?: Record<string, string | number | boolean | null>;\r\n /** Arbitrary extra developer fields */\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * Customer identification parameter: can be a string ('cus_xxx' or 'user@example.com') or a rich structured object\r\n */\r\nexport type CustomerParam = string | CustomerInfo;\r\n\r\n/**\r\n * Full usage event emitted upon completion of an LLM call or stream\r\n */\r\nexport interface UsageEvent {\r\n /** Unique ID for the event */\r\n id?: string;\r\n /** Timestamp ISO string */\r\n timestamp: string;\r\n /** Model name (e.g. 'gpt-5.6-sol', 'claude-3-7-sonnet') */\r\n model: string;\r\n /** Provider (e.g. 'openai', 'anthropic', 'google', 'mistral', 'groq', 'deepseek', 'generic') */\r\n provider: string;\r\n /** Token breakdown */\r\n usage: TokenUsage;\r\n /** Computed cost */\r\n cost: InferenceCost;\r\n /** Customer ID (internal userId, customer identifier, or anonymous) */\r\n customerId?: string;\r\n /** Optional customer email */\r\n customerEmail?: string;\r\n /** Full customer profile snapshot if provided */\r\n customer?: CustomerInfo;\r\n /** Custom developer metadata (e.g. userId, orgId, feature, session) */\r\n metadata?: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Event emitted when a circuit breaker budget or token limit is reached\r\n */\r\nexport interface BudgetExceededEvent {\r\n reason: 'cost_per_call_exceeded' | 'total_budget_exceeded' | 'max_tokens_exceeded';\r\n limit: number;\r\n current: number;\r\n model: string;\r\n customerId?: string;\r\n message: string;\r\n}\r\n\r\n/**\r\n * Error thrown when an Agent Circuit Breaker trips\r\n */\r\nexport class VibezCircuitBreakerError extends Error {\r\n public readonly event: BudgetExceededEvent;\r\n\r\n constructor(event: BudgetExceededEvent) {\r\n super(event.message);\r\n this.name = 'VibezCircuitBreakerError';\r\n this.event = event;\r\n }\r\n}\r\n\r\n/**\r\n * Circuit Breaker / Budget Guardrail Configuration\r\n */\r\nexport interface CircuitBreakerOptions {\r\n /** Maximum allowed USD cost for a single generation or stream (default: 0.50) */\r\n maxCostPerCallUSD?: number;\r\n /** Cumulative budget limit for customer/session in USD (e.g. 5.00) */\r\n maxBudgetUSD?: number;\r\n /** Hard ceiling on total tokens per generation (e.g. 10000) */\r\n maxTokensPerCall?: number;\r\n /** Model to gracefully fall back to if budget limit is exceeded instead of hard erroring */\r\n fallbackModelOnBudget?: string;\r\n /** Callback fired when circuit breaker trips */\r\n onBudgetExceeded?: (event: BudgetExceededEvent) => void | Promise<void>;\r\n /** Whether to throw a VibezCircuitBreakerError if limit exceeded (default: false) */\r\n throwOnBudgetExceeded?: boolean;\r\n}\r\n\r\n/**\r\n * Pluggable Database / Storage Adapter Interface\r\n */\r\nexport interface DatabaseAdapter {\r\n name: string;\r\n save: (event: UsageEvent) => Promise<void> | void;\r\n getBalance?: (customerId: string) => Promise<number | undefined>;\r\n}\r\n\r\n/**\r\n * Profit Pricing & Markup Configuration\r\n */\r\nexport interface PricingConfig {\r\n /** Profit margin multiplier (e.g. 1.5 = Cost + 50% profit margin automatically added) */\r\n margin?: number;\r\n /** Minimum charge in USD for any single call (e.g. 0.01 = at least 1 cent) */\r\n minimumChargeUSD?: number;\r\n}\r\n\r\n/**\r\n * Inline Rate Card Configuration for 1-line custom/newly released model pricing\r\n */\r\nexport interface InlineRateConfig {\r\n /** Input tokens price per 1 Million tokens in USD */\r\n in: number;\r\n /** Output tokens price per 1 Million tokens in USD */\r\n out?: number;\r\n output?: number;\r\n /** Reasoning/thinking tokens price per 1 Million tokens in USD (optional) */\r\n reasoning?: number;\r\n /** Cached input tokens price per 1 Million tokens in USD (optional) */\r\n cached?: number;\r\n}\r\n\r\n/**\r\n * Non-LLM Tool execution metering options\r\n */\r\nexport interface ToolMeterOptions {\r\n /** Fixed cost in USD for this tool execution (e.g. 0.01 for search, 0.04 for image) */\r\n costUSD: number;\r\n /** Customer identifier to attribute tool cost to */\r\n customer?: CustomerParam;\r\n /** Additional metadata */\r\n metadata?: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Configuration options for the VibezCheck Meter\r\n */\r\nexport interface MeterOptions extends CircuitBreakerOptions {\r\n /** API Key (optional identifier or auth token). If omitted, runs in local telemetry mode */\r\n apiKey?: string;\r\n /** Batching options to optimize event dispatch */\r\n batching?: {\r\n /** Max events per batch (default: 50) */\r\n maxBatchSize?: number;\r\n /** Flush interval in milliseconds (default: 50ms) */\r\n flushIntervalMs?: number;\r\n };\r\n /** Callback fired whenever usage is extracted */\r\n onUsage?: (event: UsageEvent) => void | Promise<void>;\r\n /** Callback fired when a batch of usage events is flushed (e.g. for database persistence or external syncing) */\r\n onBatch?: (events: UsageEvent[]) => void | Promise<void>;\r\n /** Error handler callback */\r\n onError?: (error: Error, events: UsageEvent[]) => void;\r\n /** Markup multiplier for retail price calculations (e.g. 1.3 for 30% profit) */\r\n markupMultiplier?: number;\r\n /** Pricing options including profit margin and minimum charge */\r\n pricing?: PricingConfig;\r\n /** Enable debug console logging (default: false) */\r\n debug?: boolean;\r\n}\r\n\r\n/**\r\n * Stream wrap options\r\n */\r\nexport interface StreamWrapOptions extends CircuitBreakerOptions {\r\n /** Customer identifier or email or object */\r\n customer?: CustomerParam;\r\n /** Direct customer ID string */\r\n customerId?: string;\r\n /** Model override if not automatically detectable */\r\n model?: string;\r\n /** Provider override if not automatically detectable */\r\n provider?: string;\r\n /** Profit margin & minimum charge configuration */\r\n pricing?: PricingConfig;\r\n /** 1-line inline pricing rate card */\r\n rate?: InlineRateConfig;\r\n /** Whether to capture tokens if the client aborts or closes tab mid-stream (default: true) */\r\n captureOnAbort?: boolean;\r\n /** Execution runtime environment (default: 'auto') */\r\n runtime?: 'auto' | 'serverless' | 'edge' | 'node';\r\n /** Custom metadata attached to the usage event */\r\n metadata?: Record<string, string | number | boolean>;\r\n /** Custom usage callback for this specific stream */\r\n onUsage?: (event: UsageEvent) => void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Direct usage recording options\r\n */\r\nexport interface RecordUsageOptions {\r\n model: string;\r\n provider?: string;\r\n inputTokens: number;\r\n outputTokens: number;\r\n reasoningTokens?: number;\r\n cachedTokens?: number;\r\n customer?: CustomerParam;\r\n customerId?: string;\r\n metadata?: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Model Pricing Rates (per 1 Million Tokens in USD)\r\n */\r\nexport interface ModelPricingRates {\r\n inputPer1M: number;\r\n outputPer1M: number;\r\n cachedInputPer1M?: number;\r\n reasoningPer1M?: number;\r\n cacheWritePer1M?: number;\r\n currency?: string;\r\n}\r\n\r\n/**\r\n * Aggregated Usage Summary\r\n */\r\nexport interface UsageSummary {\r\n totalRequests: number;\r\n totalTokens: number;\r\n totalInputTokens: number;\r\n totalOutputTokens: number;\r\n totalReasoningTokens: number;\r\n totalCostUSD: number;\r\n byModel: Record<\r\n string,\r\n {\r\n requests: number;\r\n tokens: number;\r\n costUSD: number;\r\n }\r\n >;\r\n}\r\n","import type { UsageEvent, UsageSummary, MeterOptions } from '../types';\r\n\r\n/**\r\n * Detects whether the current runtime is a serverless environment\r\n * (AWS Lambda, Vercel Serverless, Cloudflare Workers/Pages, Netlify, Deno Deploy, Next.js)\r\n */\r\nexport function isServerlessEnvironment(): boolean {\r\n if (typeof process !== 'undefined' && process.env) {\r\n if (\r\n process.env.VERCEL ||\r\n process.env.AWS_LAMBDA_FUNCTION_NAME ||\r\n process.env.LAMBDA_TASK_ROOT ||\r\n process.env.NETLIFY ||\r\n process.env.DENO_DEPLOYMENT_ID ||\r\n process.env.CF_PAGES ||\r\n process.env.NEXT_RUNTIME\r\n ) {\r\n return true;\r\n }\r\n }\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (g.EdgeRuntime || g.WebSocketPair) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nconst activeBatchers = new Set<MeterBatcher>();\r\nlet exitListenerAttached = false;\r\n\r\nfunction ensureExitListener() {\r\n if (exitListenerAttached) return;\r\n if (typeof process !== 'undefined' && typeof process.once === 'function') {\r\n try {\r\n process.once('beforeExit', () => {\r\n for (const batcher of activeBatchers) {\r\n batcher.flush().catch(() => {});\r\n }\r\n });\r\n exitListenerAttached = true;\r\n } catch {\r\n // Fallback for restricted sandboxes\r\n }\r\n }\r\n}\r\n\r\nexport class MeterBatcher {\r\n private queue: UsageEvent[] = [];\r\n private timer: NodeJS.Timeout | null = null;\r\n private isFlushing: boolean = false;\r\n private readonly maxBatchSize: number;\r\n private readonly flushIntervalMs: number;\r\n private readonly isExplicitFlushInterval: boolean;\r\n private readonly onUsageCallback?: (event: UsageEvent) => void | Promise<void>;\r\n private readonly onBatchCallback?: (events: UsageEvent[]) => void | Promise<void>;\r\n private readonly onErrorCallback?: (error: Error, events: UsageEvent[]) => void;\r\n private readonly debug: boolean;\r\n\r\n // In-memory ledger for local stats\r\n private totalRequests = 0;\r\n private totalTokens = 0;\r\n private totalInputTokens = 0;\r\n private totalOutputTokens = 0;\r\n private totalReasoningTokens = 0;\r\n private totalCostUSD = 0;\r\n private byModel: Record<string, { requests: number; tokens: number; costUSD: number }> = {};\r\n\r\n constructor(options: MeterOptions = {}) {\r\n this.maxBatchSize = options.batching?.maxBatchSize ?? 50;\r\n this.flushIntervalMs = options.batching?.flushIntervalMs ?? 50;\r\n this.isExplicitFlushInterval = options.batching?.flushIntervalMs !== undefined;\r\n this.onUsageCallback = options.onUsage;\r\n this.onBatchCallback = options.onBatch;\r\n this.onErrorCallback = options.onError;\r\n this.debug = options.debug ?? false;\r\n\r\n activeBatchers.add(this);\r\n ensureExitListener();\r\n }\r\n\r\n /**\r\n * Enqueue a usage event for batch dispatching\r\n */\r\n public enqueue(event: UsageEvent): void {\r\n // 1. Update in-memory local ledger\r\n this.recordInLedger(event);\r\n\r\n // 2. Fire onUsage hook immediately\r\n if (this.onUsageCallback) {\r\n try {\r\n const res = this.onUsageCallback(event);\r\n if (res instanceof Promise) {\r\n res.catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Error in onUsage callback:', err);\r\n });\r\n }\r\n } catch (err) {\r\n if (this.debug) console.error('[vibezcheck] Error in onUsage callback:', err);\r\n }\r\n }\r\n\r\n // 3. If no onBatch handler is configured, we run in immediate local mode\r\n if (!this.onBatchCallback) {\r\n if (this.debug) {\r\n console.log(\r\n `[vibezcheck:local] 📊 ${event.model} | Tokens: ${event.usage.totalTokens} | Cost: $${event.cost.totalUSD.toFixed(6)}`\r\n );\r\n }\r\n return;\r\n }\r\n\r\n // 4. Queue for batch dispatch\r\n this.queue.push(event);\r\n\r\n if (this.queue.length >= this.maxBatchSize) {\r\n this.flush().catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Batch flush error:', err);\r\n });\r\n return;\r\n }\r\n\r\n // 5. Serverless Lifecycle Spooling: Auto-register with after() or waitUntil()\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (typeof g.after === 'function') {\r\n g.after(() => this.flush().catch(() => {}));\r\n return;\r\n }\r\n if (typeof g.waitUntil === 'function') {\r\n g.waitUntil(this.flush().catch(() => {}));\r\n return;\r\n }\r\n }\r\n\r\n // In serverless environments where timers are frozen on response, auto-flush immediately unless explicit interval given\r\n if (isServerlessEnvironment() && !this.isExplicitFlushInterval) {\r\n this.flush().catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Serverless auto-flush error:', err);\r\n });\r\n return;\r\n }\r\n\r\n if (!this.timer) {\r\n this.timer = setTimeout(() => {\r\n this.timer = null;\r\n this.flush().catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Debounce flush error:', err);\r\n });\r\n }, this.flushIntervalMs);\r\n }\r\n }\r\n\r\n /**\r\n * Immediately flush all queued events\r\n */\r\n public async flush(): Promise<void> {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n\r\n if (this.queue.length === 0 || !this.onBatchCallback || this.isFlushing) {\r\n return;\r\n }\r\n\r\n this.isFlushing = true;\r\n const eventsToSend = [...this.queue];\r\n this.queue = [];\r\n\r\n try {\r\n await this.onBatchCallback(eventsToSend);\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n if (this.debug) {\r\n console.error('[vibezcheck] Failed to flush meter event batch:', err);\r\n }\r\n if (this.onErrorCallback) {\r\n this.onErrorCallback(err, eventsToSend);\r\n }\r\n } finally {\r\n this.isFlushing = false;\r\n // If new items were queued while flushing, trigger another flush\r\n if (this.queue.length > 0) {\r\n this.flush().catch(() => {});\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates internal in-memory ledger\r\n */\r\n private recordInLedger(event: UsageEvent): void {\r\n this.totalRequests += 1;\r\n this.totalTokens += event.usage.totalTokens;\r\n this.totalInputTokens += event.usage.inputTokens;\r\n this.totalOutputTokens += event.usage.outputTokens;\r\n this.totalReasoningTokens += event.usage.reasoningTokens ?? 0;\r\n this.totalCostUSD += event.cost.totalUSD;\r\n\r\n const modelKey = event.model;\r\n if (!this.byModel[modelKey]) {\r\n this.byModel[modelKey] = { requests: 0, tokens: 0, costUSD: 0 };\r\n }\r\n this.byModel[modelKey].requests += 1;\r\n this.byModel[modelKey].tokens += event.usage.totalTokens;\r\n this.byModel[modelKey].costUSD += event.cost.totalUSD;\r\n }\r\n\r\n /**\r\n * Get in-memory usage summary\r\n */\r\n public getSummary(): UsageSummary {\r\n return {\r\n totalRequests: this.totalRequests,\r\n totalTokens: this.totalTokens,\r\n totalInputTokens: this.totalInputTokens,\r\n totalOutputTokens: this.totalOutputTokens,\r\n totalReasoningTokens: this.totalReasoningTokens,\r\n totalCostUSD: Number(this.totalCostUSD.toFixed(6)),\r\n byModel: { ...this.byModel },\r\n };\r\n }\r\n\r\n /**\r\n * Reset in-memory ledger\r\n */\r\n public resetLedger(): void {\r\n this.totalRequests = 0;\r\n this.totalTokens = 0;\r\n this.totalInputTokens = 0;\r\n this.totalOutputTokens = 0;\r\n this.totalReasoningTokens = 0;\r\n this.totalCostUSD = 0;\r\n this.byModel = {};\r\n }\r\n}\r\n","import type { TokenUsage } from '../../types';\r\n\r\nexport interface ExtractedUsage {\r\n model: string;\r\n provider: string;\r\n usage: TokenUsage;\r\n}\r\n\r\n/**\r\n * Extracts token usage from OpenAI synchronous responses (ChatCompletion, Responses, Embeddings)\r\n */\r\nexport function extractOpenAIResponseUsage(response: any): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // 1. Standard OpenAI ChatCompletion\r\n if ('choices' in response && 'usage' in response && response.usage) {\r\n const rawUsage = response.usage;\r\n const model = response.model || 'gpt-4o';\r\n\r\n const inputTokens = rawUsage.prompt_tokens ?? 0;\r\n const outputTokens = rawUsage.completion_tokens ?? 0;\r\n const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens ?? 0;\r\n const cachedTokens = rawUsage.prompt_tokens_details?.cached_tokens ?? 0;\r\n\r\n return {\r\n model,\r\n provider: 'openai',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n // 2. OpenAI Embeddings Response\r\n if ('data' in response && 'usage' in response && response.usage && 'model' in response) {\r\n const rawUsage = response.usage;\r\n const inputTokens = rawUsage.prompt_tokens ?? 0;\r\n\r\n return {\r\n model: response.model || 'text-embedding-3-small',\r\n provider: 'openai',\r\n usage: {\r\n inputTokens,\r\n outputTokens: 0,\r\n totalTokens: inputTokens,\r\n },\r\n };\r\n }\r\n\r\n // 3. OpenAI Responses API (New standard)\r\n if ('status' in response && 'usage' in response && response.usage) {\r\n const rawUsage = response.usage;\r\n const model = response.model || 'gpt-5.6-sol';\r\n\r\n const inputTokens = rawUsage.input_tokens ?? rawUsage.prompt_tokens ?? 0;\r\n const outputTokens = rawUsage.output_tokens ?? rawUsage.completion_tokens ?? 0;\r\n const reasoningTokens =\r\n rawUsage.output_token_details?.reasoning_tokens ??\r\n rawUsage.completion_tokens_details?.reasoning_tokens ??\r\n 0;\r\n const cachedTokens =\r\n rawUsage.input_token_details?.cached_tokens ??\r\n rawUsage.prompt_tokens_details?.cached_tokens ??\r\n 0;\r\n\r\n return {\r\n model,\r\n provider: 'openai',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Extracts token usage from an individual OpenAI stream chunk or stream accumulator\r\n */\r\nexport function inspectOpenAIStreamChunk(chunk: any): {\r\n model?: string;\r\n usage?: TokenUsage;\r\n} {\r\n if (!chunk || typeof chunk !== 'object') return {};\r\n\r\n const model = chunk.model;\r\n\r\n // Final chunk with usage object (when stream_options: { include_usage: true }, finish chunk, or Groq / DeepSeek / Mistral stream ending)\r\n const rawUsage =\r\n (chunk.type === 'finish' ? chunk.usage : null) ||\r\n chunk.usage ||\r\n chunk.token_usage ||\r\n chunk.x_groq?.usage ||\r\n chunk.usageMetadata;\r\n if (rawUsage) {\r\n let inputTokens = 0;\r\n let outputTokens = 0;\r\n let reasoningTokens = 0;\r\n let cachedTokens = 0;\r\n\r\n if (typeof rawUsage.inputTokens === 'object' && rawUsage.inputTokens !== null) {\r\n inputTokens = rawUsage.inputTokens.total ?? rawUsage.inputTokens.noCache ?? 0;\r\n cachedTokens = rawUsage.inputTokens.cacheRead ?? 0;\r\n } else if (typeof rawUsage.promptTokens === 'number') {\r\n inputTokens = rawUsage.promptTokens;\r\n } else if (typeof rawUsage.inputTokens === 'number') {\r\n inputTokens = rawUsage.inputTokens;\r\n } else {\r\n inputTokens =\r\n rawUsage.prompt_tokens ??\r\n rawUsage.input_tokens ??\r\n rawUsage.promptTokenCount ??\r\n 0;\r\n }\r\n\r\n if (typeof rawUsage.outputTokens === 'object' && rawUsage.outputTokens !== null) {\r\n outputTokens = rawUsage.outputTokens.total ?? rawUsage.outputTokens.text ?? 0;\r\n reasoningTokens = rawUsage.outputTokens.reasoning ?? 0;\r\n } else if (typeof rawUsage.completionTokens === 'number') {\r\n outputTokens = rawUsage.completionTokens;\r\n } else if (typeof rawUsage.outputTokens === 'number') {\r\n outputTokens = rawUsage.outputTokens;\r\n } else {\r\n outputTokens =\r\n rawUsage.completion_tokens ??\r\n rawUsage.output_tokens ??\r\n rawUsage.candidatesTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!reasoningTokens) {\r\n reasoningTokens =\r\n rawUsage.completion_tokens_details?.reasoning_tokens ??\r\n rawUsage.output_token_details?.reasoning_tokens ??\r\n rawUsage.reasoning_tokens ??\r\n rawUsage.reasoningTokens ??\r\n rawUsage.thoughtsTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!cachedTokens) {\r\n cachedTokens =\r\n rawUsage.prompt_tokens_details?.cached_tokens ??\r\n rawUsage.input_token_details?.cached_tokens ??\r\n rawUsage.prompt_cache_hit_tokens ??\r\n rawUsage.cached_tokens ??\r\n rawUsage.cachedTokens ??\r\n rawUsage.cachedContentTokenCount ??\r\n 0;\r\n }\r\n\r\n return {\r\n model,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n // Response API stream event (response.completed or response.done)\r\n if (chunk.type === 'response.completed' || chunk.type === 'response.done') {\r\n if (chunk.response?.usage) {\r\n const rawUsage = chunk.response.usage;\r\n const inputTokens = rawUsage.input_tokens ?? 0;\r\n const outputTokens = rawUsage.output_tokens ?? 0;\r\n const reasoningTokens = rawUsage.output_token_details?.reasoning_tokens ?? 0;\r\n const cachedTokens = rawUsage.input_token_details?.cached_tokens ?? 0;\r\n\r\n return {\r\n model: chunk.response.model || model,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n }\r\n\r\n return { model };\r\n}\r\n","import type { TokenUsage } from '../../types';\r\nimport type { ExtractedUsage } from './openai';\r\n\r\n/**\r\n * Extracts token usage from Anthropic synchronous responses\r\n */\r\nexport function extractAnthropicResponseUsage(response: any): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // Anthropic Message response has type: 'message' or role: 'assistant' with usage\r\n if (response.type === 'message' || ('content' in response && 'usage' in response)) {\r\n const rawUsage = response.usage || {};\r\n const model = response.model || 'claude-3-7-sonnet';\r\n\r\n const inputTokens = rawUsage.input_tokens ?? 0;\r\n const outputTokens = rawUsage.output_tokens ?? 0;\r\n const cachedTokens = rawUsage.cache_read_input_tokens ?? 0;\r\n const cacheWriteTokens = rawUsage.cache_creation_input_tokens ?? 0;\r\n\r\n // Check content blocks for thinking/reasoning tokens count or thinking blocks\r\n let reasoningTokens: number | undefined = undefined;\r\n if (Array.isArray(response.content)) {\r\n const thinkingBlocks = response.content.filter((b: any) => b.type === 'thinking');\r\n if (thinkingBlocks.length > 0) {\r\n // Approximate or extract explicit thinking tokens if present in metadata\r\n reasoningTokens = (rawUsage as any).thinking_tokens ?? undefined;\r\n }\r\n }\r\n\r\n return {\r\n model,\r\n provider: 'anthropic',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens,\r\n visibleOutputTokens:\r\n reasoningTokens !== undefined ? Math.max(0, outputTokens - reasoningTokens) : outputTokens,\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Accumulates stream events across an Anthropic raw message stream\r\n */\r\nexport class AnthropicStreamAccumulator {\r\n private model: string = 'claude-3-7-sonnet';\r\n private inputTokens: number = 0;\r\n private outputTokens: number = 0;\r\n private cachedTokens: number = 0;\r\n private cacheWriteTokens: number = 0;\r\n private reasoningTokens: number = 0;\r\n\r\n processEvent(event: any): void {\r\n if (!event || typeof event !== 'object') return;\r\n\r\n // 1. message_start (contains model and initial input usage)\r\n if (event.type === 'message_start' && event.message) {\r\n if (event.message.model) {\r\n this.model = event.message.model;\r\n }\r\n if (event.message.usage) {\r\n this.inputTokens = event.message.usage.input_tokens ?? 0;\r\n this.cachedTokens = event.message.usage.cache_read_input_tokens ?? 0;\r\n this.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;\r\n }\r\n }\r\n\r\n // 2. message_delta (contains final output usage)\r\n if (event.type === 'message_delta' && event.usage) {\r\n this.outputTokens = event.usage.output_tokens ?? 0;\r\n if (event.usage.thinking_tokens) {\r\n this.reasoningTokens = event.usage.thinking_tokens;\r\n }\r\n }\r\n\r\n // 3. content_block_start / content_block_delta for thinking blocks\r\n if (event.type === 'content_block_start' && event.content_block?.type === 'thinking') {\r\n // thinking block detected\r\n }\r\n }\r\n\r\n getUsage(): ExtractedUsage {\r\n return {\r\n model: this.model,\r\n provider: 'anthropic',\r\n usage: {\r\n inputTokens: this.inputTokens,\r\n outputTokens: this.outputTokens,\r\n totalTokens: this.inputTokens + this.outputTokens,\r\n reasoningTokens: this.reasoningTokens > 0 ? this.reasoningTokens : undefined,\r\n visibleOutputTokens:\r\n this.reasoningTokens > 0\r\n ? Math.max(0, this.outputTokens - this.reasoningTokens)\r\n : this.outputTokens,\r\n cachedTokens: this.cachedTokens > 0 ? this.cachedTokens : undefined,\r\n cacheWriteTokens: this.cacheWriteTokens > 0 ? this.cacheWriteTokens : undefined,\r\n },\r\n };\r\n }\r\n}\r\n","import type { TokenUsage } from '../../types';\r\nimport type { ExtractedUsage } from './openai';\r\n\r\n/**\r\n * Extracts token usage from Google Gemini API response or chunk\r\n */\r\nexport function extractGeminiResponseUsage(\r\n response: any,\r\n fallbackModel: string = 'gemini-3.7-flash'\r\n): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // Gemini returns usageMetadata on response or GenerateContentResult\r\n const usageMetadata = response.usageMetadata || response.response?.usageMetadata;\r\n\r\n if (usageMetadata) {\r\n const inputTokens = usageMetadata.promptTokenCount ?? 0;\r\n const baseOutputTokens = usageMetadata.candidatesTokenCount ?? 0;\r\n const thoughtsTokenCount =\r\n usageMetadata.thoughtsTokenCount ?? (usageMetadata as any).reasoningTokenCount ?? 0;\r\n const cachedTokens = usageMetadata.cachedContentTokenCount ?? 0;\r\n\r\n const totalOutput = baseOutputTokens + thoughtsTokenCount;\r\n const model = response.model || response.response?.model || fallbackModel;\r\n\r\n return {\r\n model,\r\n provider: 'google',\r\n usage: {\r\n inputTokens,\r\n outputTokens: totalOutput,\r\n totalTokens: inputTokens + totalOutput,\r\n reasoningTokens: thoughtsTokenCount > 0 ? thoughtsTokenCount : undefined,\r\n visibleOutputTokens: baseOutputTokens,\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n","import type { TokenUsage } from '../../types';\r\nimport type { ExtractedUsage } from './openai';\r\n\r\n/**\r\n * Extracts token usage from generic LLM provider objects (DeepSeek, Groq, Mistral, Ollama, Cohere, Together)\r\n */\r\nexport function extractGenericResponseUsage(\r\n response: any,\r\n fallbackModel: string = 'generic-llm',\r\n fallbackProvider: string = 'generic'\r\n): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // Check common usage property locations\r\n const usage = response.usage || response.token_usage || response.usageMetadata;\r\n\r\n if (usage) {\r\n let inputTokens = 0;\r\n let outputTokens = 0;\r\n let reasoningTokens = 0;\r\n let cachedTokens = 0;\r\n\r\n if (typeof usage.inputTokens === 'object' && usage.inputTokens !== null) {\r\n inputTokens = usage.inputTokens.total ?? usage.inputTokens.noCache ?? 0;\r\n cachedTokens = usage.inputTokens.cacheRead ?? 0;\r\n } else if (typeof usage.promptTokens === 'number') {\r\n inputTokens = usage.promptTokens;\r\n } else if (typeof usage.inputTokens === 'number') {\r\n inputTokens = usage.inputTokens;\r\n } else {\r\n inputTokens =\r\n usage.prompt_tokens ??\r\n usage.input_tokens ??\r\n usage.promptTokenCount ??\r\n usage.prompt_eval_count ??\r\n 0;\r\n }\r\n\r\n if (typeof usage.outputTokens === 'object' && usage.outputTokens !== null) {\r\n outputTokens = usage.outputTokens.total ?? usage.outputTokens.text ?? 0;\r\n reasoningTokens = usage.outputTokens.reasoning ?? 0;\r\n } else if (typeof usage.completionTokens === 'number') {\r\n outputTokens = usage.completionTokens;\r\n } else if (typeof usage.outputTokens === 'number') {\r\n outputTokens = usage.outputTokens;\r\n } else {\r\n outputTokens =\r\n usage.completion_tokens ??\r\n usage.output_tokens ??\r\n usage.candidatesTokenCount ??\r\n usage.eval_count ??\r\n 0;\r\n }\r\n\r\n if (!reasoningTokens) {\r\n reasoningTokens =\r\n usage.reasoning_tokens ??\r\n usage.thoughtsTokenCount ??\r\n usage.completion_tokens_details?.reasoning_tokens ??\r\n 0;\r\n }\r\n\r\n if (!cachedTokens) {\r\n cachedTokens =\r\n usage.prompt_tokens_details?.cached_tokens ??\r\n usage.cached_tokens ??\r\n usage.cachedContentTokenCount ??\r\n 0;\r\n }\r\n\r\n const model = response.model || fallbackModel;\r\n const provider = response.provider || fallbackProvider;\r\n\r\n return {\r\n model,\r\n provider,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n","import type { ExtractedUsage } from './openai';\r\nimport { extractOpenAIResponseUsage } from './openai';\r\nimport { extractAnthropicResponseUsage } from './anthropic';\r\nimport { extractGeminiResponseUsage } from './gemini';\r\nimport { extractGenericResponseUsage } from './generic';\r\n\r\nexport * from './openai';\r\nexport * from './anthropic';\r\nexport * from './gemini';\r\nexport * from './generic';\r\n\r\n/**\r\n * Universal polymorphic response detector\r\n */\r\nexport function detectAndExtractUsage(\r\n response: any,\r\n fallbackModel?: string,\r\n fallbackProvider?: string\r\n): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // 1. Try OpenAI\r\n const openaiResult = extractOpenAIResponseUsage(response);\r\n if (openaiResult) return openaiResult;\r\n\r\n // 2. Try Anthropic\r\n const anthropicResult = extractAnthropicResponseUsage(response);\r\n if (anthropicResult) return anthropicResult;\r\n\r\n // 3. Try Gemini\r\n const geminiResult = extractGeminiResponseUsage(response, fallbackModel);\r\n if (geminiResult) return geminiResult;\r\n\r\n // 4. Try Generic\r\n const genericResult = extractGenericResponseUsage(response, fallbackModel, fallbackProvider);\r\n if (genericResult) return genericResult;\r\n\r\n return null;\r\n}\r\n","import type { ModelPricingRates } from '../types';\nimport { normalizeModelKey } from './table';\n\nexport interface PricingSyncOptions {\n /**\n * Remote manifest URL to fetch pricing from.\n * Defaults to the official hosted pricing-v1.json manifest.\n */\n manifestUrl?: string;\n\n /**\n * Request timeout in milliseconds (default: 3000ms).\n */\n timeoutMs?: number;\n\n /**\n * Custom fetch implementation (defaults to globalThis.fetch).\n */\n fetch?: typeof fetch;\n\n /**\n * Maximum cache age in milliseconds before re-fetching (default: 3600_000 = 1 hour).\n */\n cacheTtlMs?: number;\n\n /**\n * If true, bypass cache TTL and force an immediate re-fetch.\n */\n force?: boolean;\n\n /**\n * Fallback manifest JSON string or object to seed cache if network fails.\n */\n fallbackManifest?: unknown;\n\n /**\n * Custom headers for authentication or versioning.\n */\n headers?: Record<string, string>;\n}\n\nexport interface PricingSyncStatus {\n status: 'idle' | 'syncing' | 'synced' | 'failed';\n lastSyncTime: number | null;\n lastSyncETag: string | null;\n cachedModelsCount: number;\n lastError: string | null;\n}\n\nexport interface StripePricingItem {\n publisher?: string;\n provider?: string;\n model: string;\n prices_per_1m: {\n input_token?: number | null;\n output_token?: number | null;\n cached_input?: number | null;\n cached_output?: number | null;\n cached_read?: number | null;\n cached_write?: number | null;\n };\n}\n\nexport const DEFAULT_MANIFEST_URL =\n 'https://raw.githubusercontent.com/seeyouin2x5x/vibezcheck-sdk/main/manifest/pricing-v1.json';\n\nexport const VERCEL_GATEWAY_MODELS_URL = 'https://ai-gateway.vercel.sh/v1/models';\n\nexport interface VercelGatewayModelItem {\n id: string;\n name?: string;\n owned_by?: string;\n type?: string;\n pricing?: {\n input?: string | number | null;\n output?: string | number | null;\n input_cache_read?: string | number | null;\n input_cache_write?: string | number | null;\n };\n prices_per_1m?: {\n input_token?: number | null;\n output_token?: number | null;\n cached_input?: number | null;\n cached_write?: number | null;\n };\n}\n\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst DEFAULT_CACHE_TTL_MS = 3600_000; // 1 hour\n\n// In-memory fast cache\nconst dynamicPricingCache: Record<string, ModelPricingRates> = {};\n\nlet lastSyncTime: number | null = null;\nlet lastSyncETag: string | null = null;\nlet syncStatus: 'idle' | 'syncing' | 'synced' | 'failed' = 'idle';\nlet lastError: string | null = null;\n\n/**\n * Synchronously retrieves a rate from the dynamic pricing cache\n */\nexport function getDynamicRate(model: string): ModelPricingRates | undefined {\n if (!model) return undefined;\n const key = model.toLowerCase().trim();\n if (dynamicPricingCache[key]) {\n return dynamicPricingCache[key];\n }\n const normalized = normalizeModelKey(key);\n if (dynamicPricingCache[normalized]) {\n return dynamicPricingCache[normalized];\n }\n return undefined;\n}\n\n/**\n * Returns the count of models currently held in dynamic cache\n */\nexport function getDynamicCacheSize(): number {\n return Object.keys(dynamicPricingCache).length;\n}\n\n/**\n * Resets the in-memory dynamic pricing cache\n */\nexport function clearDynamicCache(): void {\n for (const k of Object.keys(dynamicPricingCache)) {\n delete dynamicPricingCache[k];\n }\n lastSyncTime = null;\n lastSyncETag = null;\n syncStatus = 'idle';\n lastError = null;\n}\n\n/**\n * Current synchronization status and telemetry\n */\nexport function getSyncStatus(): PricingSyncStatus {\n return {\n status: syncStatus,\n lastSyncTime,\n lastSyncETag,\n cachedModelsCount: Object.keys(dynamicPricingCache).length,\n lastError,\n };\n}\n\n/**\n * Ingests and registers an array of Stripe rate items or a manifest object into cache\n */\nexport function seedPricingCache(manifest: unknown): number {\n if (!manifest || typeof manifest !== 'object') {\n return 0;\n }\n\n let count = 0;\n\n // Case 1: Array of pricing items (Stripe or Vercel)\n if (Array.isArray(manifest)) {\n for (const item of manifest) {\n if (registerStripeItem(item) || registerVercelGatewayItem(item)) {\n count++;\n }\n }\n return count;\n }\n\n const obj = manifest as Record<string, any>;\n\n // Case 2: Vercel Gateway direct endpoint response: { object: \"list\", data: [...] }\n if (obj.object === 'list' && Array.isArray(obj.data)) {\n for (const item of obj.data) {\n if (registerVercelGatewayItem(item) || registerStripeItem(item)) {\n count++;\n }\n }\n return count;\n }\n\n // Case 3: Object with models array (e.g. { models: [...] })\n if (Array.isArray(obj.models)) {\n for (const item of obj.models) {\n if (registerStripeItem(item) || registerVercelGatewayItem(item)) {\n count++;\n }\n }\n }\n\n // Case 4: Object with vercel_gateway_models array\n if (Array.isArray(obj.vercel_gateway_models)) {\n for (const item of obj.vercel_gateway_models) {\n if (registerVercelGatewayItem(item) || registerStripeItem(item)) {\n count++;\n }\n }\n }\n\n // Case 5: Object with rates dictionary (e.g. { rates: { \"gpt-4o\": { inputPer1M: 2.5, ... } } })\n const ratesDict = obj.rates && typeof obj.rates === 'object' ? obj.rates : obj;\n for (const [key, val] of Object.entries(ratesDict)) {\n if (\n key === 'models' ||\n key === 'rates' ||\n key === 'version' ||\n key === '$schema' ||\n key === 'sources' ||\n key === 'vercel_gateway_models'\n ) {\n continue;\n }\n const v = val as any;\n if (v && typeof v === 'object' && typeof v.inputPer1M === 'number' && typeof v.outputPer1M === 'number') {\n registerRate(key, {\n inputPer1M: Math.max(0, v.inputPer1M),\n outputPer1M: Math.max(0, v.outputPer1M),\n cachedInputPer1M: typeof v.cachedInputPer1M === 'number' ? Math.max(0, v.cachedInputPer1M) : undefined,\n reasoningPer1M: typeof v.reasoningPer1M === 'number' ? Math.max(0, v.reasoningPer1M) : undefined,\n cacheWritePer1M: typeof v.cacheWritePer1M === 'number' ? Math.max(0, v.cacheWritePer1M) : undefined,\n currency: typeof v.currency === 'string' ? v.currency : 'USD',\n });\n count++;\n }\n }\n\n return count;\n}\n\nfunction registerRate(key: string, rate: ModelPricingRates): void {\n const cleanKey = key.toLowerCase().trim();\n dynamicPricingCache[cleanKey] = rate;\n const normalized = normalizeModelKey(cleanKey);\n dynamicPricingCache[normalized] = rate;\n}\n\nfunction registerVercelGatewayItem(entry: any): boolean {\n if (!entry || typeof entry !== 'object') return false;\n const modelId = typeof entry.id === 'string' ? entry.id : typeof entry.model === 'string' ? entry.model : null;\n if (!modelId) return false;\n\n // If entry has prices_per_1m already precomputed\n if (entry.prices_per_1m && typeof entry.prices_per_1m.input_token === 'number' && typeof entry.prices_per_1m.output_token === 'number') {\n return registerStripeItem({ ...entry, model: modelId });\n }\n\n const p = entry.pricing;\n if (!p || typeof p !== 'object') return false;\n\n const inSingle = p.input !== undefined && p.input !== null ? parseFloat(String(p.input)) : null;\n const outSingle = p.output !== undefined && p.output !== null ? parseFloat(String(p.output)) : null;\n if (inSingle === null || isNaN(inSingle) || outSingle === null || isNaN(outSingle)) {\n return false;\n }\n\n const roundRate = (v: number) => Math.round(v * 1e6) / 1e6;\n\n const rateObj: ModelPricingRates = {\n inputPer1M: Math.max(0, roundRate(inSingle * 1_000_000)),\n outputPer1M: Math.max(0, roundRate(outSingle * 1_000_000)),\n currency: 'USD',\n };\n\n if (p.input_cache_read !== undefined && p.input_cache_read !== null) {\n const cr = parseFloat(String(p.input_cache_read));\n if (!isNaN(cr)) {\n rateObj.cachedInputPer1M = Math.max(0, roundRate(cr * 1_000_000));\n }\n }\n if (p.input_cache_write !== undefined && p.input_cache_write !== null) {\n const cw = parseFloat(String(p.input_cache_write));\n if (!isNaN(cw)) {\n rateObj.cacheWritePer1M = Math.max(0, roundRate(cw * 1_000_000));\n }\n }\n\n const fullId = modelId.toLowerCase().trim();\n registerRate(fullId, rateObj);\n\n if (fullId.includes('/')) {\n const stripped = fullId.split('/').slice(1).join('/');\n registerRate(stripped, rateObj);\n }\n\n if (entry.owned_by && typeof entry.owned_by === 'string') {\n const owner = entry.owned_by.toLowerCase().replace(/\\s+/g, '-');\n dynamicPricingCache[`${owner}/${fullId}`] = rateObj;\n }\n\n return true;\n}\n\nfunction registerStripeItem(entry: any): boolean {\n const modelKey = typeof entry.model === 'string' ? entry.model : typeof entry.id === 'string' ? entry.id : null;\n if (!entry || typeof entry !== 'object' || !modelKey) {\n return false;\n }\n const p = entry.prices_per_1m;\n if (!p || typeof p !== 'object') return false;\n if (typeof p.input_token !== 'number' || typeof p.output_token !== 'number') return false;\n\n const rateObj: ModelPricingRates = {\n inputPer1M: Math.max(0, p.input_token),\n outputPer1M: Math.max(0, p.output_token),\n currency: 'USD',\n };\n\n if (typeof p.cached_input === 'number') {\n rateObj.cachedInputPer1M = Math.max(0, p.cached_input);\n } else if (typeof p.cached_read === 'number') {\n rateObj.cachedInputPer1M = Math.max(0, p.cached_read);\n }\n\n if (typeof p.cached_write === 'number') {\n rateObj.cacheWritePer1M = Math.max(0, p.cached_write);\n }\n\n const baseKey = modelKey.toLowerCase().trim();\n registerRate(baseKey, rateObj);\n\n if (entry.publisher && typeof entry.publisher === 'string') {\n const pub = entry.publisher.toLowerCase().replace(/\\s+/g, '-');\n dynamicPricingCache[`${pub}/${baseKey}`] = rateObj;\n if (pub === 'mistral-ai') {\n dynamicPricingCache[`mistral/${baseKey}`] = rateObj;\n }\n }\n\n if (entry.provider && typeof entry.provider === 'string') {\n const prov = entry.provider.toLowerCase().replace(/\\s+/g, '-');\n dynamicPricingCache[`${prov}/${baseKey}`] = rateObj;\n }\n\n return true;\n}\n\n/**\n * Asynchronously synchronizes the LLM pricing manifest from a remote endpoint.\n *\n * Guaranteed Safe & Non-Throwing:\n * If network is down, request times out, or manifest is invalid, returns false\n * and seamlessly preserves existing cached or bundled rates (offline fallback).\n */\nexport async function syncPricingManifest(options: PricingSyncOptions = {}): Promise<boolean> {\n const ttl = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;\n const now = Date.now();\n\n // If cache is fresh and not forced, reuse existing cache\n if (!options.force && lastSyncTime !== null && now - lastSyncTime < ttl && Object.keys(dynamicPricingCache).length > 0) {\n return true;\n }\n\n const url = options.manifestUrl || DEFAULT_MANIFEST_URL;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const fetchFn = options.fetch || globalThis.fetch;\n\n if (typeof fetchFn !== 'function') {\n // No fetch available in environment; try fallback manifest\n if (options.fallbackManifest) {\n seedPricingCache(options.fallbackManifest);\n lastSyncTime = now;\n syncStatus = 'synced';\n return true;\n }\n syncStatus = 'failed';\n lastError = 'Fetch API unavailable in runtime environment';\n return false;\n }\n\n syncStatus = 'syncing';\n\n const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timeoutId = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;\n\n try {\n const reqHeaders: Record<string, string> = {\n Accept: 'application/json',\n ...(options.headers || {}),\n };\n\n if (lastSyncETag && !options.force) {\n reqHeaders['If-None-Match'] = lastSyncETag;\n }\n\n const response = await fetchFn(url, {\n method: 'GET',\n headers: reqHeaders,\n signal: controller?.signal,\n });\n\n if (timeoutId) clearTimeout(timeoutId);\n\n // 304 Not Modified: Existing dynamic cache is still up to date\n if (response.status === 304) {\n lastSyncTime = now;\n syncStatus = 'synced';\n lastError = null;\n return true;\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`);\n }\n\n const etag = response.headers?.get ? response.headers.get('etag') : null;\n if (etag) {\n lastSyncETag = etag;\n }\n\n const data = await response.json();\n const seeded = seedPricingCache(data);\n\n if (seeded === 0) {\n throw new Error('Manifest contains no recognizable pricing rates');\n }\n\n lastSyncTime = now;\n syncStatus = 'synced';\n lastError = null;\n return true;\n } catch (err: any) {\n if (timeoutId) clearTimeout(timeoutId);\n\n syncStatus = 'failed';\n lastError = err?.message || 'Unknown network error';\n\n // Seed fallback if provided\n if (options.fallbackManifest) {\n seedPricingCache(options.fallbackManifest);\n }\n\n // Graceful offline fallback: Never throw, return false\n return false;\n }\n}\n\n/**\n * Non-blocking, fire-and-forget background synchronization.\n * Triggers sync in background without awaiting or crashing if network is unavailable.\n */\nexport function triggerBackgroundSync(options: PricingSyncOptions = {}): void {\n syncPricingManifest(options).catch(() => {\n // Silently caught - offline fallback preserved\n });\n}\n\n/**\n * Synchronizes LLM token pricing directly from Vercel AI Gateway (https://ai-gateway.vercel.sh/v1/models).\n * Converts single-token rates into per-1M-token rates and populates dynamic cache.\n */\nexport async function syncVercelGateway(options: PricingSyncOptions = {}): Promise<boolean> {\n return syncPricingManifest({\n manifestUrl: VERCEL_GATEWAY_MODELS_URL,\n ...options,\n });\n}\n\n/**\n * Non-blocking, fire-and-forget background synchronization from Vercel AI Gateway.\n */\nexport function triggerVercelGatewaySync(options: PricingSyncOptions = {}): void {\n syncVercelGateway(options).catch(() => {\n // Silently caught - offline fallback preserved\n });\n}\n\n","import type { ModelPricingRates } from '../types';\r\nimport { getDynamicRate } from './sync';\r\n\r\n/**\r\n * Built-in Registry of Model Pricing (USD per 1 Million Tokens)\r\n * Sourced from official 2026 provider pricing tables.\r\n */\r\nexport const MODEL_PRICING_TABLE: Record<string, ModelPricingRates> = {\r\n // --- OpenAI (Modern & Reasoning) ---\r\n 'gpt-5.6-sol': { inputPer1M: 4.0, outputPer1M: 20.0, cachedInputPer1M: 0.4 },\r\n 'gpt-5.6-terra': { inputPer1M: 2.0, outputPer1M: 12.0, cachedInputPer1M: 0.2 },\r\n 'gpt-5.6-luna': { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },\r\n 'gpt-5': { inputPer1M: 4.0, outputPer1M: 20.0, cachedInputPer1M: 0.4 },\r\n 'gpt-5-mini': { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },\r\n 'o1': { inputPer1M: 15.0, outputPer1M: 60.0, cachedInputPer1M: 7.5 },\r\n 'o1-mini': { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },\r\n 'o3': { inputPer1M: 15.0, outputPer1M: 60.0, cachedInputPer1M: 7.5 },\r\n 'o3-mini': { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },\r\n 'gpt-4o': { inputPer1M: 2.5, outputPer1M: 10.0, cachedInputPer1M: 1.25 },\r\n 'gpt-4o-mini': { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.075 },\r\n 'gpt-4.5': { inputPer1M: 75.0, outputPer1M: 150.0, cachedInputPer1M: 37.5 },\r\n 'gpt-4.5-preview': { inputPer1M: 75.0, outputPer1M: 150.0, cachedInputPer1M: 37.5 },\r\n 'chatgpt-4o-latest': { inputPer1M: 5.0, outputPer1M: 15.0 },\r\n 'gpt-4.1': { inputPer1M: 2.0, outputPer1M: 8.0, cachedInputPer1M: 1.0 },\r\n 'gpt-4.1-nano': { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.05 },\r\n 'gpt-6-astra': { inputPer1M: 5.0, outputPer1M: 25.0, cachedInputPer1M: 0.5 },\r\n 'gpt-6-astra-fast': { inputPer1M: 3.0, outputPer1M: 15.0, cachedInputPer1M: 0.3 },\r\n 'gpt-image-2.5-flare': { inputPer1M: 0.0, outputPer1M: 0.04 },\r\n 'gpt-image-2.5-sunburst': { inputPer1M: 0.0, outputPer1M: 0.08 },\r\n\r\n // --- OpenAI (Legacy & Backward Compatibility) ---\r\n 'gpt-4-turbo': { inputPer1M: 10.0, outputPer1M: 30.0, cachedInputPer1M: 5.0 },\r\n 'gpt-4-turbo-preview': { inputPer1M: 10.0, outputPer1M: 30.0, cachedInputPer1M: 5.0 },\r\n 'gpt-4': { inputPer1M: 30.0, outputPer1M: 60.0 },\r\n 'gpt-4-32k': { inputPer1M: 60.0, outputPer1M: 120.0 },\r\n 'gpt-3.5-turbo': { inputPer1M: 0.5, outputPer1M: 1.5 },\r\n 'gpt-3.5-turbo-16k': { inputPer1M: 3.0, outputPer1M: 4.0 },\r\n 'text-embedding-3-small': { inputPer1M: 0.02, outputPer1M: 0.0 },\r\n 'text-embedding-3-large': { inputPer1M: 0.13, outputPer1M: 0.0 },\r\n 'text-embedding-ada-002': { inputPer1M: 0.10, outputPer1M: 0.0 },\r\n\r\n // --- Anthropic (Modern & Extended Thinking) ---\r\n 'claude-3-7-sonnet': { inputPer1M: 0.59, outputPer1M: 2.93, cachedInputPer1M: 0.3 },\r\n 'claude-sonnet-5': { inputPer1M: 2.0, outputPer1M: 10.0, cachedInputPer1M: 0.3 },\r\n 'claude-3-5-sonnet': { inputPer1M: 3.0, outputPer1M: 15.0, cachedInputPer1M: 0.3 },\r\n 'claude-3-5-haiku': { inputPer1M: 0.8, outputPer1M: 4.0, cachedInputPer1M: 0.08 },\r\n 'haiku-4.5': { inputPer1M: 1.0, outputPer1M: 5.0, cachedInputPer1M: 0.1 },\r\n 'claude-opus-5': { inputPer1M: 5.0, outputPer1M: 25.0, cachedInputPer1M: 1.5 },\r\n 'claude-3-opus': { inputPer1M: 15.0, outputPer1M: 75.0, cachedInputPer1M: 1.5 },\r\n\r\n // --- Anthropic (Legacy & Backward Compatibility) ---\r\n 'claude-3-sonnet': { inputPer1M: 3.0, outputPer1M: 15.0, cachedInputPer1M: 0.3 },\r\n 'claude-3-haiku': { inputPer1M: 0.25, outputPer1M: 1.25, cachedInputPer1M: 0.025 },\r\n 'claude-2.1': { inputPer1M: 8.0, outputPer1M: 24.0 },\r\n 'claude-2.0': { inputPer1M: 8.0, outputPer1M: 24.0 },\r\n 'claude-instant-1.2': { inputPer1M: 1.63, outputPer1M: 5.51 },\r\n\r\n // --- Google Gemini (Modern & Thoughts) ---\r\n 'gemini-3.7-flash': { inputPer1M: 0.75, outputPer1M: 3.75, cachedInputPer1M: 0.18 },\r\n 'gemini-3.1-pro': { inputPer1M: 2.0, outputPer1M: 12.0, cachedInputPer1M: 0.5 },\r\n 'gemini-3.5-flash': { inputPer1M: 1.5, outputPer1M: 9.0, cachedInputPer1M: 0.38 },\r\n 'gemini-3.1-flash-lite': { inputPer1M: 0.25, outputPer1M: 1.5, cachedInputPer1M: 0.06 },\r\n 'gemini-2.5-pro': { inputPer1M: 1.25, outputPer1M: 5.0, cachedInputPer1M: 0.3125 },\r\n 'gemini-2.5-flash': { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.0375 },\r\n 'gemini-2.0-flash': { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.025 },\r\n 'gemini-2.0-flash-lite': { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },\r\n 'gemini-2.0-pro': { inputPer1M: 1.25, outputPer1M: 5.0, cachedInputPer1M: 0.3125 },\r\n\r\n // --- Google Gemini (Legacy & Backward Compatibility) ---\r\n 'gemini-1.5-pro': { inputPer1M: 1.25, outputPer1M: 5.0, cachedInputPer1M: 0.3125 },\r\n 'gemini-1.5-flash': { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },\r\n 'gemini-1.5-flash-8b': { inputPer1M: 0.0375, outputPer1M: 0.15, cachedInputPer1M: 0.009375 },\r\n 'gemini-1.0-pro': { inputPer1M: 0.5, outputPer1M: 1.5 },\r\n\r\n // --- xAI Grok ---\r\n 'grok-4.6': { inputPer1M: 3.0, outputPer1M: 15.0 },\r\n 'grok-3': { inputPer1M: 3.0, outputPer1M: 15.0 },\r\n 'grok-3-mini': { inputPer1M: 0.3, outputPer1M: 1.5 },\r\n 'grok-2': { inputPer1M: 2.0, outputPer1M: 10.0 },\r\n 'grok-2-vision': { inputPer1M: 2.0, outputPer1M: 10.0 },\r\n 'grok-beta': { inputPer1M: 5.0, outputPer1M: 15.0 },\r\n\r\n // --- Mistral ---\r\n 'mistral-large-3': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n 'mistral-large-latest': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n 'mistral-large-2411': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n 'codestral-latest': { inputPer1M: 0.3, outputPer1M: 0.9 },\r\n 'mistral-medium-latest': { inputPer1M: 2.7, outputPer1M: 8.1 },\r\n 'mistral-medium-3-5': { inputPer1M: 2.0, outputPer1M: 6.0, cachedInputPer1M: 0.4 },\r\n 'mistral-medium-2604': { inputPer1M: 2.0, outputPer1M: 6.0, cachedInputPer1M: 0.4 },\r\n 'magistral-small-latest': { inputPer1M: 0.5, outputPer1M: 1.5, cachedInputPer1M: 0.1 },\r\n 'magistral-medium-latest': { inputPer1M: 2.0, outputPer1M: 6.0, cachedInputPer1M: 0.4 },\r\n 'mistral-small-latest': { inputPer1M: 0.2, outputPer1M: 0.6 },\r\n 'mistral-small-2603': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'mistral-vibe-cli-fast': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'mistral-vibe-cli-latest': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'codestral-2508': { inputPer1M: 0.3, outputPer1M: 0.9, cachedInputPer1M: 0.08 },\r\n 'codestral-embed': { inputPer1M: 0.1, outputPer1M: 0.0 },\r\n 'mistral-embed-2312': { inputPer1M: 0.1, outputPer1M: 0.0 },\r\n 'zai-glm-5-2': { inputPer1M: 0.6, outputPer1M: 2.2, cachedInputPer1M: 0.15 },\r\n 'glm-5-2': { inputPer1M: 0.6, outputPer1M: 2.2, cachedInputPer1M: 0.15 },\r\n 'labs-leanstral-1-5': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'ministral-8b-latest': { inputPer1M: 0.1, outputPer1M: 0.1 },\r\n 'ministral-3b-latest': { inputPer1M: 0.04, outputPer1M: 0.04 },\r\n 'open-mistral-7b': { inputPer1M: 0.2, outputPer1M: 0.2 },\r\n 'open-mixtral-8x7b': { inputPer1M: 0.7, outputPer1M: 0.7 },\r\n 'open-mixtral-8x22b': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n\r\n // --- Groq & Meta Llama LPUs ---\r\n 'llama-3.3-70b-versatile': { inputPer1M: 0.59, outputPer1M: 0.79 },\r\n 'llama-3.1-405b': { inputPer1M: 3.0, outputPer1M: 3.0 },\r\n 'llama-3.1-70b-versatile': { inputPer1M: 0.59, outputPer1M: 0.79 },\r\n 'llama-3.1-8b-instant': { inputPer1M: 0.05, outputPer1M: 0.08 },\r\n 'llama-3.2-1b-preview': { inputPer1M: 0.04, outputPer1M: 0.04 },\r\n 'llama-3.2-3b-preview': { inputPer1M: 0.06, outputPer1M: 0.06 },\r\n 'llama-3.2-11b-vision': { inputPer1M: 0.18, outputPer1M: 0.18 },\r\n 'llama-3.2-90b-vision': { inputPer1M: 0.90, outputPer1M: 0.90 },\r\n 'deepseek-r1-distill-llama-70b': { inputPer1M: 0.75, outputPer1M: 0.99 },\r\n 'deepseek-r1-distill-qwen-32b': { inputPer1M: 0.49, outputPer1M: 0.49 },\r\n 'qwen-2.5-32b': { inputPer1M: 0.29, outputPer1M: 0.39 },\r\n 'qwen-2.5-72b': { inputPer1M: 0.35, outputPer1M: 0.40 },\r\n 'mixtral-8x7b-32768': { inputPer1M: 0.24, outputPer1M: 0.24 },\r\n 'gemma2-9b-it': { inputPer1M: 0.20, outputPer1M: 0.20 },\r\n\r\n // --- DeepSeek ---\r\n 'deepseek-v4-pro': { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },\r\n 'deepseek-v4.1-flash': { inputPer1M: 0.20, outputPer1M: 0.60, cachedInputPer1M: 0.05 },\r\n 'deepseek-v4-flash': { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },\r\n 'deepseek-v3': { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },\r\n 'deepseek-chat': { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },\r\n 'deepseek-r1': { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },\r\n 'deepseek-reasoner': { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },\r\n\r\n // --- Gateway, Inception & InclusionAI Models ---\r\n 'mercury-2.5': { inputPer1M: 0.25, outputPer1M: 0.75, cachedInputPer1M: 0.05 },\r\n 'mercury-2': { inputPer1M: 0.25, outputPer1M: 0.75, cachedInputPer1M: 0.05 },\r\n 'ling-3.0-flash-sante': { inputPer1M: 0.15, outputPer1M: 0.45, cachedInputPer1M: 0.03 },\r\n 'ling-3.0-flash': { inputPer1M: 0.15, outputPer1M: 0.45, cachedInputPer1M: 0.03 },\r\n\r\n // --- Cohere ---\r\n 'command-r-plus': { inputPer1M: 2.5, outputPer1M: 10.0 },\r\n 'command-r': { inputPer1M: 0.15, outputPer1M: 0.6 },\r\n 'command': { inputPer1M: 1.0, outputPer1M: 2.0 },\r\n 'command-light': { inputPer1M: 0.3, outputPer1M: 0.6 },\r\n 'embed-english-v3.0': { inputPer1M: 0.10, outputPer1M: 0.0 },\r\n\r\n // --- Perplexity ---\r\n 'sonar': { inputPer1M: 1.0, outputPer1M: 1.0 },\r\n 'sonar-pro': { inputPer1M: 3.0, outputPer1M: 15.0 },\r\n 'sonar-reasoning': { inputPer1M: 1.0, outputPer1M: 5.0 },\r\n 'sonar-reasoning-pro': { inputPer1M: 2.0, outputPer1M: 8.0 },\r\n};\r\n\r\n/**\r\n * Common model alias map to normalize nicknames, shorthands, and legacy IDs\r\n */\r\nexport const MODEL_ALIASES: Record<string, string> = {\r\n // OpenAI Shorthands & Aliases\r\n 'gpt4': 'gpt-4',\r\n 'gpt4o': 'gpt-4o',\r\n 'gpt-4-preview': 'gpt-4-turbo',\r\n 'gpt-4-0125-preview': 'gpt-4-turbo',\r\n 'gpt-4-1106-preview': 'gpt-4-turbo',\r\n 'gpt-3.5': 'gpt-3.5-turbo',\r\n 'gpt-3.5-turbo-0125': 'gpt-3.5-turbo',\r\n 'gpt-3.5-turbo-1106': 'gpt-3.5-turbo',\r\n 'gpt-3.5-turbo-16k-0613': 'gpt-3.5-turbo-16k',\r\n\r\n // Anthropic Shorthands\r\n 'sonnet': 'claude-3-5-sonnet',\r\n 'sonnet-3.7': 'claude-3-7-sonnet',\r\n 'sonnet-3.5': 'claude-3-5-sonnet',\r\n 'haiku': 'claude-3-5-haiku',\r\n 'haiku-3.5': 'claude-3-5-haiku',\r\n 'opus': 'claude-3-opus',\r\n 'claude-2': 'claude-2.0',\r\n 'claude-instant': 'claude-instant-1.2',\r\n\r\n // DeepSeek Shorthands\r\n 'r1': 'deepseek-r1',\r\n 'v3': 'deepseek-v3',\r\n\r\n // Gemini Shorthands\r\n 'flash': 'gemini-2.0-flash',\r\n 'pro': 'gemini-1.5-pro',\r\n\r\n // Meta / Groq Shorthands\r\n 'llama-3.3-70b': 'llama-3.3-70b-versatile',\r\n 'llama-3.1-70b': 'llama-3.1-70b-versatile',\r\n 'llama-3.1-8b': 'llama-3.1-8b-instant',\r\n 'llama-3-70b': 'llama-3.1-70b-versatile',\r\n 'llama-3-8b': 'llama-3.1-8b-instant',\r\n\r\n // Mistral Shorthands\r\n 'codestral': 'codestral-latest',\r\n 'mistral-large': 'mistral-large-latest',\r\n 'mistral-small': 'mistral-small-latest',\r\n 'magistral': 'magistral-small-latest',\r\n 'magistral-small': 'magistral-small-latest',\r\n 'magistral-medium': 'magistral-medium-latest',\r\n 'mistral-3.5': 'mistral-medium-3-5',\r\n 'mistral-medium-3.5': 'mistral-medium-3-5',\r\n 'gpt-image-2.5': 'gpt-image-2.5-flare',\r\n 'gpt-image-sunburst': 'gpt-image-2.5-sunburst',\r\n 'gpt-image-flare': 'gpt-image-2.5-flare',\r\n};\r\n\r\n/**\r\n * Dynamic in-memory registry allowing runtime custom price registration\r\n */\r\nconst customPricingRegistry: Record<string, ModelPricingRates> = {};\r\n\r\n/**\r\n * Normalize model identifier to match pricing table keys:\r\n * - Strips AWS Bedrock prefixes (e.g. 'anthropic.claude-3-5-sonnet-20241022-v2:0' -> 'claude-3-5-sonnet')\r\n * - Strips provider prefixes (e.g. 'openai/gpt-4o' -> 'gpt-4o', 'deepseek/deepseek-r1' -> 'deepseek-r1')\r\n * - Strips date suffixes (e.g. '-20240307', '-20250219')\r\n * - Resolves shorthands and aliases\r\n */\r\nexport function normalizeModelKey(rawModel: string): string {\r\n if (!rawModel) return 'unknown';\r\n\r\n let model = rawModel.toLowerCase().trim();\r\n\r\n // Strip AWS Bedrock model prefix (e.g. 'us.anthropic.claude-3-5-sonnet...', 'meta.llama3-...')\r\n model = model.replace(/^[a-z0-9_-]+\\.(anthropic|meta|amazon|cohere|mistral|ai21)\\./i, '');\r\n model = model.replace(/^(anthropic|meta|amazon|cohere|mistral|ai21)\\./i, '');\r\n\r\n // Strip AWS Bedrock version suffix (e.g. '-v1:0', '-v2:0', ':0')\r\n model = model.replace(/-v\\d+(:\\d+)?$/, '');\r\n model = model.replace(/:\\d+$/, '');\r\n\r\n // Strip provider prefix if present (e.g. 'openai/gpt-4o' -> 'gpt-4o', 'meta-llama/llama-3.3-70b-instruct' -> 'llama-3.3-70b-instruct')\r\n if (model.includes('/')) {\r\n model = model.split('/').slice(1).join('/');\r\n }\r\n\r\n // Remove trailing version/mode tags (e.g. ':latest', ':free', ':beta')\r\n model = model.replace(/:(latest|free|beta)$/, '');\r\n\r\n // Remove date suffixes like -20240307 or -20250219 or -2024-08-06\r\n model = model.replace(/-\\d{8}$/, '');\r\n model = model.replace(/-\\d{4}-\\d{2}-\\d{2}$/, '');\r\n\r\n // Normalize Bedrock Meta format (e.g. llama3-1-70b -> llama-3.1-70b)\r\n model = model.replace(/llama(\\d+)-(\\d+)-/g, 'llama-$1.$2-');\r\n model = model.replace(/llama(\\d+)\\.(\\d+)-/g, 'llama-$1.$2-');\r\n\r\n // Check aliases before fine-tuning\r\n if (MODEL_ALIASES[model]) {\r\n return MODEL_ALIASES[model];\r\n }\r\n\r\n // Remove common modifier suffixes if not directly matching table\r\n if (!MODEL_PRICING_TABLE[model]) {\r\n const withoutInstruct = model.replace(/-(instruct|chat|preview)$/, '');\r\n if (MODEL_PRICING_TABLE[withoutInstruct]) {\r\n return withoutInstruct;\r\n }\r\n if (MODEL_ALIASES[withoutInstruct]) {\r\n return MODEL_ALIASES[withoutInstruct];\r\n }\r\n }\r\n\r\n return model;\r\n}\r\n\r\n/**\r\n * Retrieve pricing rates for a given model\r\n */\r\nexport function getModelPricing(modelName: string): ModelPricingRates {\r\n const normalized = normalizeModelKey(modelName);\r\n\r\n // Check custom registry first\r\n if (customPricingRegistry[normalized]) {\r\n return customPricingRegistry[normalized];\r\n }\r\n if (customPricingRegistry[modelName]) {\r\n return customPricingRegistry[modelName];\r\n }\r\n\r\n // Check dynamic synced manifest cache\r\n const dynamicRate = getDynamicRate(modelName) || getDynamicRate(normalized);\r\n if (dynamicRate) {\r\n return dynamicRate;\r\n }\r\n\r\n // Check built-in table with normalized key\r\n if (MODEL_PRICING_TABLE[normalized]) {\r\n return MODEL_PRICING_TABLE[normalized];\r\n }\r\n // Check built-in table with direct key\r\n if (MODEL_PRICING_TABLE[modelName]) {\r\n return MODEL_PRICING_TABLE[modelName];\r\n }\r\n\r\n // Check alias table fallback\r\n const alias = MODEL_ALIASES[modelName.toLowerCase().trim()];\r\n if (alias) {\r\n const dynamicAlias = getDynamicRate(alias);\r\n if (dynamicAlias) return dynamicAlias;\r\n if (MODEL_PRICING_TABLE[alias]) {\r\n return MODEL_PRICING_TABLE[alias];\r\n }\r\n }\r\n\r\n // Fallback defaults for unknown models (conservative estimates: $1.00 in, $3.00 out)\r\n return {\r\n inputPer1M: 1.0,\r\n outputPer1M: 3.0,\r\n cachedInputPer1M: 0.5,\r\n };\r\n}\r\n\r\n/**\r\n * Register or override pricing rates for a custom model\r\n */\r\nexport function registerModelPricing(modelName: string, rates: ModelPricingRates): void {\r\n const normalized = normalizeModelKey(modelName);\r\n customPricingRegistry[normalized] = rates;\r\n customPricingRegistry[modelName] = rates;\r\n}\r\n","import type { InferenceCost, TokenUsage, InlineRateConfig, ModelPricingRates } from '../types';\nimport { getModelPricing } from './table';\n\nexport interface CalculateCostParams {\n model: string;\n inputTokens?: number;\n outputTokens?: number;\n reasoningTokens?: number;\n cachedTokens?: number;\n cacheWriteTokens?: number;\n markupMultiplier?: number;\n minimumChargeUSD?: number;\n customRate?: InlineRateConfig;\n}\n\n/**\n * BigInt Nano-Precision Financial Math Engine\n * 1 USD = 1,000,000,000 Nano-USD (10^9)\n * 1 token at $1.00 / 1M = $0.000001 = 1,000 Nano-USD\n * Prevents IEEE 754 floating point precision drift on micro-transactions.\n */\nexport function calculateCost(params: CalculateCostParams): InferenceCost {\n let rates: ModelPricingRates;\n\n if (params.customRate) {\n const outRate = params.customRate.out ?? params.customRate.output ?? 0;\n rates = {\n inputPer1M: params.customRate.in,\n outputPer1M: outRate,\n reasoningPer1M: params.customRate.reasoning ?? outRate,\n cachedInputPer1M: params.customRate.cached ?? params.customRate.in * 0.15,\n currency: 'USD',\n };\n } else {\n rates = getModelPricing(params.model);\n }\n\n const inputTokens = BigInt(Math.max(0, params.inputTokens ?? 0));\n const outputTokens = BigInt(Math.max(0, params.outputTokens ?? 0));\n const reasoningTokens = BigInt(Math.max(0, params.reasoningTokens ?? 0));\n const cachedTokens = BigInt(Math.max(0, params.cachedTokens ?? 0));\n\n // Regular input tokens (minus any cached tokens)\n const regularInputTokens = inputTokens > cachedTokens ? inputTokens - cachedTokens : 0n;\n\n // Convert rate per 1M tokens to integer nano-dollars per single token (rate * 1,000)\n // Using 10^9 nano-precision\n const rateInputNano = BigInt(Math.round(rates.inputPer1M * 1_000));\n const cachedPer1M = rates.cachedInputPer1M ?? rates.inputPer1M * 0.15;\n const rateCachedNano = BigInt(Math.round(cachedPer1M * 1_000));\n const rateOutputNano = BigInt(Math.round(rates.outputPer1M * 1_000));\n const reasoningPer1M = rates.reasoningPer1M ?? rates.outputPer1M;\n const rateReasoningNano = BigInt(Math.round(reasoningPer1M * 1_000));\n\n // Compute component nano costs\n const regularInputCostNano = regularInputTokens * rateInputNano;\n const cachedInputCostNano = cachedTokens * rateCachedNano;\n const inputCostNano = regularInputCostNano + cachedInputCostNano;\n const outputCostNano = outputTokens * rateOutputNano;\n const reasoningCostNano = reasoningTokens * rateReasoningNano;\n\n // Prompt cache savings discount\n const standardCacheCostNano = cachedTokens * rateInputNano;\n const cachedDiscountNano =\n standardCacheCostNano > cachedInputCostNano ? standardCacheCostNano - cachedInputCostNano : 0n;\n\n // Total wholesale cost\n const wholesaleNano = inputCostNano + outputCostNano;\n\n // Retail calculation\n const markup = params.markupMultiplier ?? 1.0;\n let billedNano = wholesaleNano;\n let hasRetail = false;\n\n if (markup !== 1.0 || params.minimumChargeUSD !== undefined) {\n hasRetail = true;\n const markupMultiplierNano = BigInt(Math.round(markup * 1_000));\n billedNano = (wholesaleNano * markupMultiplierNano) / 1_000n;\n\n if (params.minimumChargeUSD !== undefined && params.minimumChargeUSD > 0) {\n const minChargeNano = BigInt(Math.round(params.minimumChargeUSD * 1_000_000_000));\n if (billedNano < minChargeNano) {\n billedNano = minChargeNano;\n }\n }\n }\n\n const inputCostUSD = Number(inputCostNano) / 1_000_000_000;\n const outputCostUSD = Number(outputCostNano) / 1_000_000_000;\n const reasoningCostUSD = Number(reasoningCostNano) / 1_000_000_000;\n const cachedDiscountUSD = Number(cachedDiscountNano) / 1_000_000_000;\n const totalUSD = Number(wholesaleNano) / 1_000_000_000;\n const wholesaleTotalUSD = totalUSD;\n const billedUSD = Number(billedNano) / 1_000_000_000;\n const profitUSD = Math.max(0, billedUSD - wholesaleTotalUSD);\n const retailUSD = hasRetail ? billedUSD : undefined;\n\n return {\n inputCostUSD: Number(inputCostUSD.toFixed(8)),\n outputCostUSD: Number(outputCostUSD.toFixed(8)),\n reasoningCostUSD: reasoningTokens > 0n ? Number(reasoningCostUSD.toFixed(8)) : undefined,\n cachedDiscountUSD: cachedTokens > 0n ? Number(cachedDiscountUSD.toFixed(8)) : undefined,\n savingsUSD: cachedTokens > 0n ? Number(cachedDiscountUSD.toFixed(8)) : undefined,\n totalUSD: Number(totalUSD.toFixed(8)),\n wholesaleTotalUSD: Number(wholesaleTotalUSD.toFixed(8)),\n wholesaleUSD: Number(wholesaleTotalUSD.toFixed(8)),\n billedUSD: Number(billedUSD.toFixed(8)),\n profitUSD: Number(profitUSD.toFixed(8)),\n retailUSD: retailUSD !== undefined ? Number(retailUSD.toFixed(8)) : undefined,\n currency: rates.currency || 'USD',\n };\n}\n\n/**\n * Calculates cost directly from a TokenUsage object\n */\nexport function calculateUsageCost(\n model: string,\n usage: TokenUsage,\n optionsOrMarkup?: number | { markupMultiplier?: number; minimumChargeUSD?: number; customRate?: InlineRateConfig }\n): InferenceCost {\n const options =\n typeof optionsOrMarkup === 'number'\n ? { markupMultiplier: optionsOrMarkup }\n : optionsOrMarkup || {};\n\n return calculateCost({\n model,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n reasoningTokens: usage.reasoningTokens,\n cachedTokens: usage.cachedTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n markupMultiplier: options.markupMultiplier,\n minimumChargeUSD: options.minimumChargeUSD,\n customRate: options.customRate,\n });\n}\n","import type { CustomerParam, CustomerInfo } from '../types';\r\n\r\nexport interface NormalizedCustomer {\r\n customerId?: string;\r\n customerEmail?: string;\r\n customerObj?: CustomerInfo;\r\n customerMetadata: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Normalizes string or object customer into structured identifiers and metadata\r\n */\r\nexport function normalizeCustomer(customer?: CustomerParam, extraCustomerId?: string): NormalizedCustomer {\r\n if (!customer && !extraCustomerId) {\r\n return {\r\n customerId: undefined,\r\n customerEmail: undefined,\r\n customerObj: undefined,\r\n customerMetadata: {},\r\n };\r\n }\r\n\r\n if (typeof customer === 'string') {\r\n const isEmail = customer.includes('@');\r\n const customerObj: CustomerInfo = {\r\n id: customer,\r\n email: isEmail ? customer : undefined,\r\n };\r\n return {\r\n customerId: customer,\r\n customerEmail: isEmail ? customer : undefined,\r\n customerObj,\r\n customerMetadata: {},\r\n };\r\n }\r\n\r\n const customerObj = customer || (extraCustomerId ? { id: extraCustomerId } : undefined);\r\n const customerId = customerObj?.id || customerObj?.userId || extraCustomerId;\r\n const customerEmail = customerObj?.email;\r\n\r\n const customerMetadata: Record<string, string | number | boolean> = {};\r\n\r\n if (customerObj) {\r\n const orgId = customerObj.orgId || customerObj.organizationId;\r\n if (orgId) customerMetadata.org_id = String(orgId);\r\n\r\n const teamId = customerObj.teamId || customerObj.workspaceId;\r\n if (teamId) customerMetadata.team_id = String(teamId);\r\n\r\n if (customerObj.plan) customerMetadata.plan = String(customerObj.plan);\r\n if (customerObj.tier) customerMetadata.tier = String(customerObj.tier);\r\n if (customerObj.role) customerMetadata.role = String(customerObj.role);\r\n if (customerObj.orgName) customerMetadata.org_name = String(customerObj.orgName);\r\n\r\n if (customerObj.metadata) {\r\n for (const [key, val] of Object.entries(customerObj.metadata)) {\r\n if (val !== null && val !== undefined) {\r\n customerMetadata[key] = val as string | number | boolean;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n customerId,\r\n customerEmail,\r\n customerObj,\r\n customerMetadata,\r\n };\r\n}\r\n","import type { UsageEvent, StreamWrapOptions } from '../types';\r\nimport { inspectOpenAIStreamChunk } from './extractors/openai';\r\nimport { AnthropicStreamAccumulator } from './extractors/anthropic';\r\nimport { extractGeminiResponseUsage } from './extractors/gemini';\r\nimport { calculateUsageCost } from '../pricing/calculator';\r\nimport { normalizeCustomer } from '../customers/helpers';\r\n\r\nexport type UsageDispatchedCallback = (event: UsageEvent) => void;\r\n\r\n/**\r\n * Wraps an OpenAI async iterable stream to capture usage at stream conclusion\r\n */\r\nexport function wrapOpenAIStream<T extends AsyncIterable<any>>(\r\n stream: T,\r\n options: StreamWrapOptions,\r\n onComplete: UsageDispatchedCallback\r\n): T {\r\n let detectedModel = options.model || 'gpt-4o';\r\n let finalUsage: any = null;\r\n\r\n const wrappedAsyncIterable = {\r\n async *[Symbol.asyncIterator]() {\r\n try {\r\n for await (const chunk of stream) {\r\n const inspected = inspectOpenAIStreamChunk(chunk);\r\n if (inspected.model) {\r\n detectedModel = inspected.model;\r\n }\r\n if (inspected.usage) {\r\n finalUsage = inspected.usage;\r\n }\r\n yield chunk;\r\n }\r\n } finally {\r\n if (finalUsage) {\r\n const cost = calculateUsageCost(detectedModel, finalUsage);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model: detectedModel,\r\n provider: 'openai',\r\n usage: finalUsage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n },\r\n };\r\n\r\n onComplete(event);\r\n if (options.onUsage) {\r\n options.onUsage(event);\r\n }\r\n }\r\n }\r\n },\r\n };\r\n\r\n return wrappedAsyncIterable as unknown as T;\r\n}\r\n\r\n/**\r\n * Wraps an Anthropic message stream to accumulate message_start and message_delta usage\r\n */\r\nexport function wrapAnthropicStream<T extends AsyncIterable<any>>(\r\n stream: T,\r\n options: StreamWrapOptions,\r\n onComplete: UsageDispatchedCallback\r\n): T {\r\n const accumulator = new AnthropicStreamAccumulator();\r\n\r\n const wrappedAsyncIterable = {\r\n async *[Symbol.asyncIterator]() {\r\n try {\r\n for await (const event of stream) {\r\n accumulator.processEvent(event);\r\n yield event;\r\n }\r\n } finally {\r\n const extracted = accumulator.getUsage();\r\n const model = options.model || extracted.model;\r\n const cost = calculateUsageCost(model, extracted.usage);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const usageEvent: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model,\r\n provider: 'anthropic',\r\n usage: extracted.usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n },\r\n };\r\n\r\n onComplete(usageEvent);\r\n if (options.onUsage) {\r\n options.onUsage(usageEvent);\r\n }\r\n }\r\n },\r\n };\r\n\r\n return wrappedAsyncIterable as unknown as T;\r\n}\r\n\r\n/**\r\n * Wraps a Google Gemini GenerateContentStreamResult\r\n */\r\nexport function wrapGeminiStream(\r\n result: any,\r\n options: StreamWrapOptions,\r\n onComplete: UsageDispatchedCallback\r\n): any {\r\n if (!result || !result.stream) return result;\r\n\r\n const originalStream = result.stream;\r\n const model = options.model || 'gemini-3.7-flash';\r\n let lastChunkWithUsage: any = null;\r\n\r\n const wrappedStream = (async function* () {\r\n try {\r\n for await (const chunk of originalStream) {\r\n if (chunk.usageMetadata) {\r\n lastChunkWithUsage = chunk;\r\n }\r\n yield chunk;\r\n }\r\n } finally {\r\n if (lastChunkWithUsage) {\r\n const extracted = extractGeminiResponseUsage(lastChunkWithUsage, model);\r\n if (extracted) {\r\n const cost = calculateUsageCost(extracted.model, extracted.usage);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model: extracted.model,\r\n provider: 'google',\r\n usage: extracted.usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n },\r\n };\r\n\r\n onComplete(event);\r\n if (options.onUsage) {\r\n options.onUsage(event);\r\n }\r\n }\r\n }\r\n }\r\n })();\r\n\r\n return {\r\n ...result,\r\n stream: wrappedStream,\r\n };\r\n}\r\n\r\n/**\r\n * Universal Stream Wrapper\r\n */\r\nexport function wrapUniversalStream<T>(\r\n stream: T,\r\n options: StreamWrapOptions = {},\r\n onComplete: UsageDispatchedCallback\r\n): T {\r\n if (!stream || typeof stream !== 'object') return stream;\r\n\r\n // 1. Check Gemini stream\r\n if ('stream' in stream && 'response' in stream) {\r\n return wrapGeminiStream(stream, options, onComplete);\r\n }\r\n\r\n // 2. Check if stream is an AsyncIterable\r\n if (Symbol.asyncIterator in stream) {\r\n // If provider is explicitly anthropic or model is claude\r\n if (options.provider === 'anthropic' || options.model?.toLowerCase().includes('claude')) {\r\n return wrapAnthropicStream(stream as any, options, onComplete);\r\n }\r\n // Default to universal stream wrapper which detects usage chunks polymorphically\r\n return wrapOpenAIStream(stream as any, options, onComplete);\r\n }\r\n\r\n return stream;\r\n}\r\n","import type {\r\n MeterOptions,\r\n StreamWrapOptions,\r\n RecordUsageOptions,\r\n UsageEvent,\r\n UsageSummary,\r\n CustomerParam,\r\n} from '../types';\r\nimport { MeterBatcher } from './batcher';\r\nimport { detectAndExtractUsage } from './extractors';\r\nimport { calculateUsageCost } from '../pricing/calculator';\r\nimport { wrapUniversalStream } from './stream';\r\nimport { normalizeCustomer } from '../customers/helpers';\r\n\r\nexport class VibezMeter {\r\n private batcher: MeterBatcher;\r\n private markupMultiplier?: number;\r\n\r\n constructor(options: MeterOptions = {}) {\r\n this.markupMultiplier = options.pricing?.margin ?? options.markupMultiplier;\r\n this.batcher = new MeterBatcher(options);\r\n }\r\n\r\n /**\r\n * Track token usage from a non-streaming response object (OpenAI, Anthropic, Gemini, etc.)\r\n */\r\n public trackUsage(\r\n response: any,\r\n options: {\r\n customer?: CustomerParam;\r\n customerId?: string;\r\n model?: string;\r\n provider?: string;\r\n metadata?: Record<string, string | number | boolean>;\r\n } = {}\r\n ): UsageEvent | null {\r\n const extracted = detectAndExtractUsage(response, options.model, options.provider);\r\n if (!extracted) {\r\n return null;\r\n }\r\n\r\n const model = options.model || extracted.model;\r\n const cost = calculateUsageCost(model, extracted.usage, this.markupMultiplier);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const mergedMeta = {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n };\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model,\r\n provider: extracted.provider,\r\n usage: extracted.usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: mergedMeta,\r\n };\r\n\r\n this.batcher.enqueue(event);\r\n return event;\r\n }\r\n\r\n /**\r\n * Wrap any LLM stream (OpenAI, Anthropic, Gemini) with zero added latency\r\n */\r\n public wrapStream<T>(stream: T, options: StreamWrapOptions = {}): T {\r\n return wrapUniversalStream(stream, options, (event) => {\r\n this.batcher.enqueue(event);\r\n });\r\n }\r\n\r\n /**\r\n * Directly record token usage manually\r\n */\r\n public recordUsage(options: RecordUsageOptions & { customer?: CustomerParam }): UsageEvent {\r\n const inputTokens = options.inputTokens ?? 0;\r\n const outputTokens = options.outputTokens ?? 0;\r\n const reasoningTokens = options.reasoningTokens;\r\n const cachedTokens = options.cachedTokens;\r\n\r\n const usage = {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens,\r\n visibleOutputTokens:\r\n reasoningTokens !== undefined ? Math.max(0, outputTokens - reasoningTokens) : outputTokens,\r\n cachedTokens,\r\n };\r\n\r\n const cost = calculateUsageCost(options.model, usage, this.markupMultiplier);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const mergedMeta = {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n };\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model: options.model,\r\n provider: options.provider || 'custom',\r\n usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: mergedMeta,\r\n };\r\n\r\n this.batcher.enqueue(event);\r\n return event;\r\n }\r\n\r\n /**\r\n * Flush pending events (vital for Serverless & Edge environments)\r\n */\r\n public async flush(): Promise<void> {\r\n await this.batcher.flush();\r\n }\r\n\r\n /**\r\n * Get in-memory aggregated usage statistics\r\n */\r\n public getUsageSummary(): UsageSummary {\r\n return this.batcher.getSummary();\r\n }\r\n\r\n /**\r\n * Reset in-memory ledger\r\n */\r\n public resetSummary(): void {\r\n this.batcher.resetLedger();\r\n }\r\n}\r\n\r\n/**\r\n * Factory function to create a VibezMeter instance\r\n */\r\nexport function createMeter(options: MeterOptions = {}): VibezMeter {\r\n return new VibezMeter(options);\r\n}\r\n","import type {\r\n CustomerParam,\r\n UsageEvent,\r\n CircuitBreakerOptions,\r\n BudgetExceededEvent,\r\n PricingConfig,\r\n InlineRateConfig,\r\n} from '../types';\r\nimport { VibezCircuitBreakerError } from '../types';\r\nimport { createMeter, VibezMeter } from '../meter/client';\r\nimport { calculateUsageCost } from '../pricing/calculator';\r\nimport { normalizeCustomer } from '../customers/helpers';\r\n\r\nexport interface WithBillingOptions extends CircuitBreakerOptions {\r\n /** Customer email, user ID, or rich customer object with metadata */\r\n customer?: CustomerParam;\r\n /** Direct customer ID */\r\n customerId?: string;\r\n /** Profit margin & minimum charge configuration */\r\n pricing?: PricingConfig;\r\n /** 1-line inline pricing rate card */\r\n rate?: InlineRateConfig;\r\n /** Pluggable Database Sink (Supabase, Postgres, Firebase, or 1-line callback) */\r\n database?: any | ((event: UsageEvent) => void | Promise<void>);\r\n /** Whether to capture tokens if the client aborts or closes tab mid-stream (default: true) */\r\n captureOnAbort?: boolean;\r\n /** Execution runtime environment (default: 'auto') */\r\n runtime?: 'auto' | 'serverless' | 'edge' | 'node';\r\n /** API Key override */\r\n apiKey?: string;\r\n /** Existing VibezMeter instance (optional) */\r\n meter?: VibezMeter;\r\n /** Custom meter event name */\r\n eventName?: string;\r\n /** Usage callback fired upon generation/stream completion */\r\n onUsage?: (event: UsageEvent) => void | Promise<void>;\r\n /** Custom developer metadata */\r\n metadata?: Record<string, string | number | boolean>;\r\n /** Suppress console warnings (default: true in test environment) */\r\n silent?: boolean;\r\n}\r\n\r\n/**\r\n * Wraps any Vercel AI SDK LanguageModel (v2 or v3) with automated token metering, cost intelligence, and agent circuit breakers.\r\n *\r\n * Sane Defaults Built-In:\r\n * - $0.50 safety ceiling per call (overridable)\r\n * - Automatic in-flight token capture on abort\r\n * - Automatic prompt caching discount parsing\r\n * - Serverless lifecycle preservation\r\n */\r\nexport function withBilling<T extends object>(\r\n model: T,\r\n optionsOrCustomer?: CustomerParam | WithBillingOptions,\r\n extraOptions: WithBillingOptions = {}\r\n): T {\r\n if (!model || typeof model !== 'object') {\r\n return model;\r\n }\r\n\r\n let options: WithBillingOptions = {};\r\n if (typeof optionsOrCustomer === 'string') {\r\n options = { ...extraOptions, customer: optionsOrCustomer };\r\n } else if (typeof optionsOrCustomer === 'object' && optionsOrCustomer !== null) {\r\n if ('userId' in optionsOrCustomer || 'email' in optionsOrCustomer || 'id' in optionsOrCustomer) {\r\n options = { ...extraOptions, customer: optionsOrCustomer as CustomerParam };\r\n } else {\r\n options = { ...(optionsOrCustomer as WithBillingOptions), ...extraOptions };\r\n }\r\n }\r\n\r\n const meter =\r\n options.meter ||\r\n createMeter({\r\n apiKey: options.apiKey,\r\n });\r\n\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n const customerId = normalized.customerId;\r\n const customerEmail = normalized.customerEmail;\r\n const customerObj = normalized.customerObj;\r\n const customerMetadata = normalized.customerMetadata;\r\n\r\n const modelId = (model as any).modelId || 'unknown-model';\r\n const provider = (model as any).provider?.replace(/^@ai-sdk\\//, '') || 'ai-sdk';\r\n\r\n // Sane Default: $0.50 circuit breaker ceiling unless explicitly disabled or configured\r\n const maxCostPerCall = options.maxCostPerCallUSD !== undefined ? options.maxCostPerCallUSD : 0.50;\r\n const captureOnAbort = options.captureOnAbort !== false; // Default: true\r\n\r\n // Helper to safely schedule serverless flushes\r\n const scheduleFlush = () => {\r\n try {\r\n const flushPromise = meter.flush();\r\n // Next.js 15+ after() or Cloudflare Workers / Vercel Edge waitUntil()\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (typeof g.after === 'function') {\r\n g.after(() => flushPromise);\r\n return;\r\n }\r\n if (typeof g.waitUntil === 'function') {\r\n g.waitUntil(flushPromise);\r\n return;\r\n }\r\n }\r\n flushPromise.catch(() => {});\r\n } catch {\r\n // Fallback in environments without after() or waitUntil()\r\n }\r\n };\r\n\r\n // Helper to record usage and enforce circuit breakers\r\n const handleUsage = (rawUsage: any, extraMeta?: Record<string, any>) => {\r\n if (!rawUsage) return;\r\n\r\n let inputTokens = 0;\r\n let outputTokens = 0;\r\n let reasoningTokens = 0;\r\n let cachedTokens = 0;\r\n let cacheWriteTokens = 0;\r\n\r\n // AI SDK v4+ (LanguageModelV4Usage) structured object or legacy flat number\r\n if (typeof rawUsage.inputTokens === 'object' && rawUsage.inputTokens !== null) {\r\n inputTokens = rawUsage.inputTokens.total ?? rawUsage.inputTokens.noCache ?? 0;\r\n cachedTokens = rawUsage.inputTokens.cacheRead ?? 0;\r\n cacheWriteTokens = rawUsage.inputTokens.cacheWrite ?? 0;\r\n } else if (typeof rawUsage.promptTokens === 'number') {\r\n inputTokens = rawUsage.promptTokens;\r\n } else if (typeof rawUsage.inputTokens === 'number') {\r\n inputTokens = rawUsage.inputTokens;\r\n } else {\r\n inputTokens =\r\n rawUsage.prompt_tokens ??\r\n rawUsage.input_tokens ??\r\n rawUsage.promptTokenCount ??\r\n 0;\r\n }\r\n\r\n if (typeof rawUsage.outputTokens === 'object' && rawUsage.outputTokens !== null) {\r\n outputTokens = rawUsage.outputTokens.total ?? rawUsage.outputTokens.text ?? 0;\r\n reasoningTokens = rawUsage.outputTokens.reasoning ?? 0;\r\n } else if (typeof rawUsage.completionTokens === 'number') {\r\n outputTokens = rawUsage.completionTokens;\r\n } else if (typeof rawUsage.outputTokens === 'number') {\r\n outputTokens = rawUsage.outputTokens;\r\n } else {\r\n outputTokens =\r\n rawUsage.completion_tokens ??\r\n rawUsage.output_tokens ??\r\n rawUsage.candidatesTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!reasoningTokens) {\r\n reasoningTokens =\r\n rawUsage.reasoningTokens ??\r\n rawUsage.completionTokensDetails?.reasoningTokens ??\r\n rawUsage.outputTokenDetails?.reasoningTokens ??\r\n rawUsage.reasoning_tokens ??\r\n rawUsage.completion_tokens_details?.reasoning_tokens ??\r\n rawUsage.output_token_details?.reasoning_tokens ??\r\n rawUsage.thoughtsTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!cachedTokens) {\r\n cachedTokens =\r\n rawUsage.promptTokensDetails?.cachedTokens ??\r\n rawUsage.inputTokenDetails?.cachedTokens ??\r\n rawUsage.cachedTokens ??\r\n rawUsage.cached_tokens ??\r\n rawUsage.prompt_tokens_details?.cached_tokens ??\r\n rawUsage.input_token_details?.cached_tokens ??\r\n rawUsage.cachedContentTokenCount ??\r\n rawUsage.cache_read_input_tokens ??\r\n 0;\r\n }\r\n\r\n if (!cacheWriteTokens) {\r\n cacheWriteTokens =\r\n rawUsage.cacheWriteTokens ??\r\n rawUsage.cache_creation_input_tokens ??\r\n rawUsage.cacheCreationTokens ??\r\n 0;\r\n }\r\n\r\n const usage = {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : undefined,\r\n };\r\n\r\n // Calculate cost with profit margin & minimum charge & custom rates\r\n const cost = calculateUsageCost(modelId, usage, {\r\n markupMultiplier: options.pricing?.margin,\r\n minimumChargeUSD: options.pricing?.minimumChargeUSD,\r\n customRate: options.rate,\r\n });\r\n\r\n // 🛡️ Agent Circuit Breakers Check ($0.50 default safety fuse)\r\n if (maxCostPerCall > 0 && maxCostPerCall !== Infinity && cost.totalUSD > maxCostPerCall) {\r\n const budgetEvent: BudgetExceededEvent = {\r\n reason: 'cost_per_call_exceeded',\r\n limit: maxCostPerCall,\r\n current: cost.totalUSD,\r\n model: modelId,\r\n customerId,\r\n message: `[vibezcheck] Circuit Breaker tripped: Call cost ($${cost.totalUSD.toFixed(4)}) exceeded budget ceiling ($${maxCostPerCall.toFixed(4)}).`,\r\n };\r\n\r\n if (options.onBudgetExceeded) {\r\n options.onBudgetExceeded(budgetEvent);\r\n }\r\n\r\n if (options.throwOnBudgetExceeded) {\r\n throw new VibezCircuitBreakerError(budgetEvent);\r\n }\r\n }\r\n\r\n if (options.maxTokensPerCall && usage.totalTokens > options.maxTokensPerCall) {\r\n const budgetEvent: BudgetExceededEvent = {\r\n reason: 'max_tokens_exceeded',\r\n limit: options.maxTokensPerCall,\r\n current: usage.totalTokens,\r\n model: modelId,\r\n customerId,\r\n message: `[vibezcheck] Circuit Breaker tripped: Token count (${usage.totalTokens}) exceeded maxTokensPerCall limit (${options.maxTokensPerCall}).`,\r\n };\r\n\r\n if (options.onBudgetExceeded) {\r\n options.onBudgetExceeded(budgetEvent);\r\n }\r\n\r\n if (options.throwOnBudgetExceeded) {\r\n throw new VibezCircuitBreakerError(budgetEvent);\r\n }\r\n }\r\n\r\n const mergedMetadata: Record<string, string | number | boolean> = {\r\n ...customerMetadata,\r\n ...options.metadata,\r\n ...extraMeta,\r\n };\r\n\r\n const event: UsageEvent = {\r\n id: `evt_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,\r\n timestamp: new Date().toISOString(),\r\n model: modelId,\r\n provider,\r\n usage,\r\n cost,\r\n customerId,\r\n customerEmail,\r\n customer: customerObj,\r\n metadata: mergedMetadata,\r\n };\r\n\r\n // Record via meter batcher\r\n meter.recordUsage({\r\n model: modelId,\r\n provider,\r\n inputTokens,\r\n outputTokens,\r\n reasoningTokens: usage.reasoningTokens,\r\n cachedTokens: usage.cachedTokens,\r\n customerId,\r\n customer: customerObj,\r\n metadata: event.metadata,\r\n });\r\n\r\n if (options.onUsage) {\r\n options.onUsage(event);\r\n }\r\n\r\n // 🛡️ Duck-Typed Database Sink Execution (Airbag Isolated)\r\n if (options.database) {\r\n const dbTarget = options.database;\r\n const executeDbWrite = async () => {\r\n try {\r\n // 1. Direct Supabase client duck-typing (has .from()) or wrapped { client, table }\r\n const supabaseClient = typeof dbTarget === 'object' && dbTarget !== null && typeof dbTarget.from === 'function'\r\n ? dbTarget\r\n : (typeof dbTarget === 'object' && dbTarget !== null && typeof dbTarget.client?.from === 'function' ? dbTarget.client : null);\r\n\r\n if (supabaseClient) {\r\n const tableName = (dbTarget as any)?.table || 'vibez_usage';\r\n await supabaseClient.from(tableName).insert({\r\n customer_id: customerId,\r\n user_id: customerObj?.userId || customerId,\r\n model: modelId,\r\n input_tokens: usage.inputTokens,\r\n output_tokens: usage.outputTokens,\r\n total_tokens: usage.totalTokens,\r\n cached_tokens: usage.cachedTokens,\r\n reasoning_tokens: usage.reasoningTokens,\r\n cost_usd: cost.totalUSD,\r\n created_at: event.timestamp,\r\n metadata: event.metadata,\r\n });\r\n return;\r\n }\r\n\r\n // 2. Typed DatabaseAdapter (has .save())\r\n if (typeof dbTarget === 'object' && dbTarget !== null && typeof dbTarget.save === 'function') {\r\n await dbTarget.save(event);\r\n return;\r\n }\r\n\r\n // 3. 1-line callback function\r\n if (typeof dbTarget === 'function') {\r\n await dbTarget(event);\r\n return;\r\n }\r\n } catch (err: any) {\r\n // Zero Blast Radius: Third-party DB errors never crash the user's stream\r\n if (process.env.NODE_ENV !== 'test' && !options.silent) {\r\n console.warn(`[vibezcheck] Database record failed safely:`, err?.message || err);\r\n }\r\n }\r\n };\r\n\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (typeof g.after === 'function') {\r\n g.after(() => executeDbWrite());\r\n return;\r\n }\r\n if (typeof g.waitUntil === 'function') {\r\n g.waitUntil(executeDbWrite());\r\n return;\r\n }\r\n }\r\n executeDbWrite().catch(() => {});\r\n }\r\n\r\n scheduleFlush();\r\n return event;\r\n };\r\n\r\n // Proxy to intercept LanguageModel calls\r\n const handler: ProxyHandler<any> = {\r\n get(target, prop, receiver) {\r\n const originalValue = Reflect.get(target, prop, receiver);\r\n\r\n // Intercept doStream (Vercel AI SDK v1/v2/v3)\r\n if (prop === 'doStream' && typeof originalValue === 'function') {\r\n return async function (...args: any[]) {\r\n const result = await originalValue.apply(target, args);\r\n if (!result || !result.stream) {\r\n return result;\r\n }\r\n\r\n const originalStream = result.stream;\r\n let streamCompleted = false;\r\n let accumulatedChars = 0;\r\n\r\n // Estimate input prompt tokens from args if available\r\n let estimatedInputTokens = 0;\r\n try {\r\n if (args[0]?.prompt) {\r\n const str = typeof args[0].prompt === 'string' ? args[0].prompt : JSON.stringify(args[0].prompt);\r\n estimatedInputTokens = Math.ceil(str.length / 4);\r\n }\r\n } catch {}\r\n\r\n // In-flight abort signal listener\r\n const abortSignal = args[0]?.abortSignal;\r\n if (abortSignal && captureOnAbort) {\r\n abortSignal.addEventListener(\r\n 'abort',\r\n () => {\r\n if (!streamCompleted && accumulatedChars > 0) {\r\n streamCompleted = true;\r\n const estimatedOutputTokens = Math.ceil(accumulatedChars / 3.8);\r\n handleUsage(\r\n {\r\n inputTokens: estimatedInputTokens,\r\n outputTokens: estimatedOutputTokens,\r\n },\r\n { aborted: true, partial: true }\r\n );\r\n }\r\n },\r\n { once: true }\r\n );\r\n }\r\n\r\n // Wrap stream to capture tokens upon finish chunk or abort\r\n const transformStream = new TransformStream({\r\n transform(chunk, controller) {\r\n controller.enqueue(chunk);\r\n\r\n if (chunk.type === 'text-delta' && typeof chunk.delta === 'string') {\r\n accumulatedChars += chunk.delta.length;\r\n } else if (chunk.type === 'reasoning-delta' && typeof chunk.delta === 'string') {\r\n accumulatedChars += chunk.delta.length;\r\n } else {\r\n const delta = chunk.textDelta || chunk.text || chunk.delta;\r\n if (delta && typeof delta === 'string') {\r\n accumulatedChars += delta.length;\r\n } else if (chunk.type === 'reasoning' || chunk.type === 'reasoning-delta') {\r\n const reasoning = chunk.reasoning || chunk.textDelta || chunk.text || chunk.delta || '';\r\n if (typeof reasoning === 'string') {\r\n accumulatedChars += reasoning.length;\r\n }\r\n }\r\n }\r\n\r\n // AI SDK stream finish chunk or direct usage payload (OpenAI, Anthropic, Gemini, DeepSeek, Groq, Mistral)\r\n const chunkUsage =\r\n (chunk.type === 'finish' ? chunk.usage : null) ||\r\n chunk.usage ||\r\n chunk.token_usage ||\r\n chunk.usageMetadata;\r\n if (chunkUsage) {\r\n streamCompleted = true;\r\n const event = handleUsage(chunkUsage);\r\n if (chunk.type === 'finish' && event) {\r\n chunk.providerMetadata = {\r\n ...chunk.providerMetadata,\r\n vibezcheck: {\r\n type: 'vibezcheck',\r\n cost: event.cost,\r\n usage: event.usage,\r\n model: modelId,\r\n provider,\r\n customerId,\r\n customerEmail,\r\n timestamp: event.timestamp,\r\n },\r\n };\r\n }\r\n }\r\n },\r\n flush() {\r\n // If stream ended without finish chunk (e.g. cancelled/aborted), record partial tokens\r\n if (!streamCompleted && captureOnAbort && accumulatedChars > 0) {\r\n streamCompleted = true;\r\n const estimatedOutputTokens = Math.ceil(accumulatedChars / 3.8);\r\n handleUsage(\r\n {\r\n inputTokens: estimatedInputTokens,\r\n outputTokens: estimatedOutputTokens,\r\n },\r\n { aborted: true, partial: true }\r\n );\r\n }\r\n },\r\n });\r\n\r\n return {\r\n ...result,\r\n stream: originalStream.pipeThrough(transformStream),\r\n };\r\n };\r\n }\r\n\r\n // Intercept doGenerate (Vercel AI SDK v1/v2/v3/v4/v5+)\r\n if (prop === 'doGenerate' && typeof originalValue === 'function') {\r\n return async function (...args: any[]) {\r\n const result = await originalValue.apply(target, args);\r\n const usage = result?.usage || result?.tokenUsage || result?.usageMetadata;\r\n if (usage) {\r\n handleUsage(usage);\r\n }\r\n return result;\r\n };\r\n }\r\n\r\n return originalValue;\r\n },\r\n apply(target, thisArg, argArray) {\r\n if (typeof target === 'function') {\r\n return Reflect.apply(target, thisArg, argArray);\r\n }\r\n return target;\r\n },\r\n has(target, prop) {\r\n return Reflect.has(target, prop);\r\n },\r\n ownKeys(target) {\r\n return Reflect.ownKeys(target);\r\n },\r\n getPrototypeOf(target) {\r\n return Reflect.getPrototypeOf(target);\r\n },\r\n };\r\n\r\n return new Proxy(model, handler);\r\n}\r\n\r\n/**\r\n * Convenient alias for withBilling\r\n */\r\nexport const meteredModel = withBilling;\r\n","import { withBilling, type WithBillingOptions } from './with-billing';\n\n/**\n * VibezCheck Middleware for Vercel AI SDK wrapLanguageModel({ model, middleware })\n */\nexport function vibezcheckMiddleware(options: WithBillingOptions = {}) {\n return {\n specificationVersion: 'v1' as const,\n\n wrapGenerate: async ({ doGenerate, params, model }: any) => {\n const target = { ...model, doGenerate };\n const metered = withBilling(target, options);\n return (metered as any).doGenerate(params);\n },\n\n wrapStream: async ({ doStream, params, model }: any) => {\n const target = { ...model, doStream };\n const metered = withBilling(target, options);\n return (metered as any).doStream(params);\n },\n };\n}\n\nexport default vibezcheckMiddleware;\n"],"mappings":"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","names":["rawUsage","customerObj"]}
1
+ {"version":3,"sources":["../../src/types.ts","../../src/meter/batcher.ts","../../src/meter/extractors/openai.ts","../../src/meter/extractors/anthropic.ts","../../src/meter/extractors/gemini.ts","../../src/meter/extractors/generic.ts","../../src/meter/extractors/index.ts","../../src/pricing/sync.ts","../../src/pricing/table.ts","../../src/pricing/calculator.ts","../../src/customers/helpers.ts","../../src/meter/stream.ts","../../src/meter/client.ts","../../src/ai-sdk/with-billing.ts","../../src/ai-sdk/middleware.ts"],"sourcesContent":["/**\r\n * Known supported model identifiers with full IDE autocomplete\r\n */\r\nexport type SupportedOpenAIModel =\r\n | 'openai/gpt-4o'\r\n | 'openai/gpt-4o-mini'\r\n | 'openai/gpt-4.5-preview'\r\n | 'openai/gpt-4.1'\r\n | 'openai/gpt-4.1-nano'\r\n | 'openai/gpt-4-turbo'\r\n | 'openai/gpt-4'\r\n | 'openai/gpt-3.5-turbo'\r\n | 'openai/o1'\r\n | 'openai/o1-mini'\r\n | 'openai/o3'\r\n | 'openai/o3-mini'\r\n | 'openai/gpt-5'\r\n | 'openai/gpt-5-mini'\r\n | 'openai/gpt-5.6-sol'\r\n | 'openai/gpt-5.6-terra'\r\n | 'openai/gpt-5.6-luna'\r\n | 'openai/text-embedding-3-small'\r\n | 'openai/text-embedding-3-large'\r\n | 'gpt-4o'\r\n | 'gpt-4o-mini'\r\n | 'gpt-4.5-preview'\r\n | 'gpt-4.5'\r\n | 'gpt-4.1'\r\n | 'gpt-4.1-nano'\r\n | 'gpt-4-turbo'\r\n | 'gpt-4'\r\n | 'gpt-3.5-turbo'\r\n | 'o1'\r\n | 'o1-mini'\r\n | 'o3'\r\n | 'o3-mini'\r\n | 'gpt-5'\r\n | 'gpt-5-mini'\r\n | 'gpt-5.6-sol'\r\n | 'gpt-5.6-terra'\r\n | 'gpt-5.6-luna';\r\n\r\nexport type SupportedAnthropicModel =\r\n | 'anthropic/claude-3-7-sonnet'\r\n | 'anthropic/claude-3-5-sonnet'\r\n | 'anthropic/claude-3-5-haiku'\r\n | 'anthropic/claude-3-opus'\r\n | 'anthropic/claude-3-haiku'\r\n | 'anthropic/claude-2.1'\r\n | 'anthropic/claude-2.0'\r\n | 'anthropic/claude-opus-5'\r\n | 'anthropic/haiku-4.5'\r\n | 'claude-3-7-sonnet'\r\n | 'claude-3-5-sonnet'\r\n | 'claude-3-5-haiku'\r\n | 'claude-3-opus'\r\n | 'claude-3-haiku'\r\n | 'claude-2.1'\r\n | 'claude-2.0'\r\n | 'claude-opus-5'\r\n | 'haiku-4.5';\r\n\r\nexport type SupportedGoogleModel =\r\n | 'google/gemini-2.5-pro'\r\n | 'google/gemini-2.5-flash'\r\n | 'google/gemini-2.0-flash'\r\n | 'google/gemini-2.0-flash-lite'\r\n | 'google/gemini-2.0-pro'\r\n | 'google/gemini-1.5-pro'\r\n | 'google/gemini-1.5-flash'\r\n | 'google/gemini-1.5-flash-8b'\r\n | 'google/gemini-1.0-pro'\r\n | 'google/gemini-3.7-flash'\r\n | 'google/gemini-3.1-pro'\r\n | 'gemini-2.5-pro'\r\n | 'gemini-2.5-flash'\r\n | 'gemini-2.0-flash'\r\n | 'gemini-2.0-flash-lite'\r\n | 'gemini-2.0-pro'\r\n | 'gemini-1.5-pro'\r\n | 'gemini-1.5-flash'\r\n | 'gemini-1.5-flash-8b'\r\n | 'gemini-1.0-pro'\r\n | 'gemini-3.7-flash'\r\n | 'gemini-3.1-pro';\r\n\r\nexport type SupportedDeepSeekModel =\r\n | 'deepseek/deepseek-chat'\r\n | 'deepseek/deepseek-reasoner'\r\n | 'deepseek/deepseek-v3'\r\n | 'deepseek/deepseek-r1'\r\n | 'deepseek/deepseek-v4-pro'\r\n | 'deepseek-chat'\r\n | 'deepseek-reasoner'\r\n | 'deepseek-v3'\r\n | 'deepseek-r1'\r\n | 'deepseek-v4-pro';\r\n\r\nexport type SupportedXAIModel =\r\n | 'xai/grok-3'\r\n | 'xai/grok-3-mini'\r\n | 'xai/grok-2'\r\n | 'xai/grok-2-vision'\r\n | 'xai/grok-beta'\r\n | 'grok-3'\r\n | 'grok-3-mini'\r\n | 'grok-2'\r\n | 'grok-2-vision'\r\n | 'grok-beta';\r\n\r\nexport type SupportedMistralModel =\r\n | 'mistral/mistral-large-latest'\r\n | 'mistral/codestral-latest'\r\n | 'mistral/mistral-small-latest'\r\n | 'mistral/ministral-8b-latest'\r\n | 'mistral-large-latest'\r\n | 'codestral-latest'\r\n | 'mistral-small-latest'\r\n | 'ministral-8b-latest';\r\n\r\nexport type SupportedGroqModel =\r\n | 'groq/llama-3.3-70b-versatile'\r\n | 'groq/llama-3.1-70b-versatile'\r\n | 'groq/llama-3.1-8b-instant'\r\n | 'groq/deepseek-r1-distill-llama-70b'\r\n | 'llama-3.3-70b-versatile'\r\n | 'llama-3.1-70b-versatile'\r\n | 'llama-3.1-8b-instant'\r\n | 'deepseek-r1-distill-llama-70b';\r\n\r\nexport type SupportedCohereModel =\r\n | 'cohere/command-r-plus'\r\n | 'cohere/command-r'\r\n | 'command-r-plus'\r\n | 'command-r';\r\n\r\nexport type KnownModel =\r\n | SupportedOpenAIModel\r\n | SupportedAnthropicModel\r\n | SupportedGoogleModel\r\n | SupportedDeepSeekModel\r\n | SupportedXAIModel\r\n | SupportedMistralModel\r\n | SupportedGroqModel\r\n | SupportedCohereModel;\r\n\r\n/**\r\n * Union of all known model IDs with loose string fallback for custom / future models\r\n */\r\nexport type SupportedModel = KnownModel | (string & {});\r\n\r\n/**\r\n * Detailed token usage breakdown\r\n */\r\nexport interface TokenUsage {\r\n /** Input/Prompt tokens */\r\n inputTokens: number;\r\n /** Total output/completion tokens (including reasoning) */\r\n outputTokens: number;\r\n /** Total tokens (input + output) */\r\n totalTokens: number;\r\n /** Hidden reasoning / thinking tokens (e.g. o1/o3/GPT-5, Claude 3.7 Thinking, Gemini 3.7 Thoughts) */\r\n reasoningTokens?: number;\r\n /** Visible output tokens (outputTokens - reasoningTokens) */\r\n visibleOutputTokens?: number;\r\n /** Cached input tokens read from KV cache / prompt cache */\r\n cachedTokens?: number;\r\n /** Cache write / creation tokens */\r\n cacheWriteTokens?: number;\r\n}\r\n\r\n/**\r\n * Calculated inference cost breakdown\r\n */\r\nexport interface InferenceCost {\r\n /** Cost for standard input prompt tokens in USD */\r\n inputCostUSD: number;\r\n /** Cost for output completion tokens in USD */\r\n outputCostUSD: number;\r\n /** Cost for reasoning/thinking tokens in USD (if applicable) */\r\n reasoningCostUSD?: number;\r\n /** Savings from prompt caching in USD */\r\n cachedDiscountUSD?: number;\r\n /** Alias for cachedDiscountUSD */\r\n savingsUSD?: number;\r\n /** Total computed base inference cost in USD */\r\n totalUSD: number;\r\n /** Wholesale provider cost in USD */\r\n wholesaleTotalUSD?: number;\r\n /** Alias for wholesaleTotalUSD */\r\n wholesaleUSD?: number;\r\n /** Amount billed to customer in USD */\r\n billedUSD?: number;\r\n /** Net developer profit in USD */\r\n profitUSD?: number;\r\n /** Retail price after developer markup (if markup applied) */\r\n retailUSD?: number;\r\n /** Currency (defaults to 'USD') */\r\n currency: string;\r\n}\r\n\r\n/**\r\n * Structured Customer Information with rich metadata, multi-tenancy & billing attributes\r\n */\r\nexport interface CustomerInfo {\r\n /** Internal user ID or customer identifier ('usr_123', 'cus_xxx') */\r\n id?: string;\r\n /** Explicit user ID */\r\n userId?: string;\r\n /** Customer email */\r\n email?: string;\r\n /** Customer full name or business display name */\r\n name?: string;\r\n /** Phone number */\r\n phone?: string;\r\n /** Multi-tenant Organization or Company ID */\r\n orgId?: string;\r\n /** Organization / Company name */\r\n orgName?: string;\r\n /** Multi-tenant Organization ID alias */\r\n organizationId?: string;\r\n /** Team / Workspace identifier */\r\n teamId?: string;\r\n /** Workspace identifier alias */\r\n workspaceId?: string;\r\n /** User Role within organization (e.g. 'admin', 'member', 'owner') */\r\n role?: string;\r\n /** Subscription Plan name (e.g. 'free', 'starter', 'pro', 'enterprise') */\r\n plan?: string;\r\n /** Billing Tier (e.g. 'tier_1', 'growth', 'unlimited') */\r\n tier?: string;\r\n /** Billing currency (defaults to 'usd') */\r\n currency?: string;\r\n /** Flexible custom metadata (key-value attributes) */\r\n metadata?: Record<string, string | number | boolean | null>;\r\n /** Arbitrary extra developer fields */\r\n [key: string]: any;\r\n}\r\n\r\n/**\r\n * Customer identification parameter: can be a string ('cus_xxx' or 'user@example.com') or a rich structured object\r\n */\r\nexport type CustomerParam = string | CustomerInfo;\r\n\r\n/**\r\n * Full usage event emitted upon completion of an LLM call or stream\r\n */\r\nexport interface UsageEvent {\r\n /** Unique ID for the event */\r\n id?: string;\r\n /** Timestamp ISO string */\r\n timestamp: string;\r\n /** Model name (e.g. 'gpt-5.6-sol', 'claude-3-7-sonnet') */\r\n model: string;\r\n /** Provider (e.g. 'openai', 'anthropic', 'google', 'mistral', 'groq', 'deepseek', 'generic') */\r\n provider: string;\r\n /** Token breakdown */\r\n usage: TokenUsage;\r\n /** Computed cost */\r\n cost: InferenceCost;\r\n /** Customer ID (internal userId, customer identifier, or anonymous) */\r\n customerId?: string;\r\n /** Optional customer email */\r\n customerEmail?: string;\r\n /** Full customer profile snapshot if provided */\r\n customer?: CustomerInfo;\r\n /** Custom developer metadata (e.g. userId, orgId, feature, session) */\r\n metadata?: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Event emitted when a circuit breaker budget or token limit is reached\r\n */\r\nexport interface BudgetExceededEvent {\r\n reason: 'cost_per_call_exceeded' | 'total_budget_exceeded' | 'max_tokens_exceeded';\r\n limit: number;\r\n current: number;\r\n model: string;\r\n customerId?: string;\r\n message: string;\r\n}\r\n\r\n/**\r\n * Error thrown when an Agent Circuit Breaker trips\r\n */\r\nexport class VibezCircuitBreakerError extends Error {\r\n public readonly event: BudgetExceededEvent;\r\n\r\n constructor(event: BudgetExceededEvent) {\r\n super(event.message);\r\n this.name = 'VibezCircuitBreakerError';\r\n this.event = event;\r\n }\r\n}\r\n\r\n/**\r\n * Circuit Breaker / Budget Guardrail Configuration\r\n */\r\nexport interface CircuitBreakerOptions {\r\n /** Maximum allowed USD cost for a single generation or stream (default: 0.50) */\r\n maxCostPerCallUSD?: number;\r\n /** Cumulative budget limit for customer/session in USD (e.g. 5.00) */\r\n maxBudgetUSD?: number;\r\n /** Hard ceiling on total tokens per generation (e.g. 10000) */\r\n maxTokensPerCall?: number;\r\n /** Model to gracefully fall back to if budget limit is exceeded instead of hard erroring */\r\n fallbackModelOnBudget?: string;\r\n /** Callback fired when circuit breaker trips */\r\n onBudgetExceeded?: (event: BudgetExceededEvent) => void | Promise<void>;\r\n /** Whether to throw a VibezCircuitBreakerError if limit exceeded (default: false) */\r\n throwOnBudgetExceeded?: boolean;\r\n}\r\n\r\n/**\r\n * Pluggable Database / Storage Adapter Interface\r\n */\r\nexport interface DatabaseAdapter {\r\n name: string;\r\n save: (event: UsageEvent) => Promise<void> | void;\r\n getBalance?: (customerId: string) => Promise<number | undefined>;\r\n}\r\n\r\n/**\r\n * Profit Pricing & Markup Configuration\r\n */\r\nexport interface PricingConfig {\r\n /** Profit margin multiplier (e.g. 1.5 = Cost + 50% profit margin automatically added) */\r\n margin?: number;\r\n /** Retail markup multiplier (alias for margin, e.g. 1.3 = +30% markup) */\r\n markup?: number;\r\n /** Minimum charge in USD for any single call (e.g. 0.01 = at least 1 cent) */\r\n minimumChargeUSD?: number;\r\n}\r\n\r\n/**\r\n * Inline Rate Card Configuration for 1-line custom/newly released model pricing\r\n */\r\nexport interface InlineRateConfig {\r\n /** Input tokens price per 1 Million tokens in USD */\r\n in: number;\r\n /** Output tokens price per 1 Million tokens in USD */\r\n out?: number;\r\n output?: number;\r\n /** Reasoning/thinking tokens price per 1 Million tokens in USD (optional) */\r\n reasoning?: number;\r\n /** Cached input tokens price per 1 Million tokens in USD (optional) */\r\n cached?: number;\r\n}\r\n\r\n/**\r\n * Non-LLM Tool execution metering options\r\n */\r\nexport interface ToolMeterOptions {\r\n /** Fixed cost in USD for this tool execution (e.g. 0.01 for search, 0.04 for image) */\r\n costUSD: number;\r\n /** Customer identifier to attribute tool cost to */\r\n customer?: CustomerParam;\r\n /** Additional metadata */\r\n metadata?: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Configuration options for the VibezCheck Meter\r\n */\r\nexport interface MeterOptions extends CircuitBreakerOptions {\r\n /** API Key (optional identifier or auth token). If omitted, runs in local telemetry mode */\r\n apiKey?: string;\r\n /** Batching options to optimize event dispatch */\r\n batching?: {\r\n /** Max events per batch (default: 50) */\r\n maxBatchSize?: number;\r\n /** Flush interval in milliseconds (default: 50ms) */\r\n flushIntervalMs?: number;\r\n };\r\n /** Callback fired whenever usage is extracted */\r\n onUsage?: (event: UsageEvent) => void | Promise<void>;\r\n /** Callback fired when a batch of usage events is flushed (e.g. for database persistence or external syncing) */\r\n onBatch?: (events: UsageEvent[]) => void | Promise<void>;\r\n /** Error handler callback */\r\n onError?: (error: Error, events: UsageEvent[]) => void;\r\n /** Markup multiplier for retail price calculations (e.g. 1.3 for 30% profit) */\r\n markupMultiplier?: number;\r\n /** Pricing options including profit margin and minimum charge */\r\n pricing?: PricingConfig;\r\n /** Enable debug console logging (default: false) */\r\n debug?: boolean;\r\n}\r\n\r\n/**\r\n * Stream wrap options\r\n */\r\nexport interface StreamWrapOptions extends CircuitBreakerOptions {\r\n /** Customer identifier or email or object */\r\n customer?: CustomerParam;\r\n /** Direct customer ID string */\r\n customerId?: string;\r\n /** Model override if not automatically detectable */\r\n model?: string;\r\n /** Provider override if not automatically detectable */\r\n provider?: string;\r\n /** Profit margin & minimum charge configuration */\r\n pricing?: PricingConfig;\r\n /** 1-line inline pricing rate card */\r\n rate?: InlineRateConfig;\r\n /** Whether to capture tokens if the client aborts or closes tab mid-stream (default: true) */\r\n captureOnAbort?: boolean;\r\n /** Execution runtime environment (default: 'auto') */\r\n runtime?: 'auto' | 'serverless' | 'edge' | 'node';\r\n /** Custom metadata attached to the usage event */\r\n metadata?: Record<string, string | number | boolean>;\r\n /** Custom usage callback for this specific stream */\r\n onUsage?: (event: UsageEvent) => void | Promise<void>;\r\n}\r\n\r\n/**\r\n * Direct usage recording options\r\n */\r\nexport interface RecordUsageOptions {\r\n model: string;\r\n provider?: string;\r\n inputTokens: number;\r\n outputTokens: number;\r\n reasoningTokens?: number;\r\n cachedTokens?: number;\r\n customer?: CustomerParam;\r\n customerId?: string;\r\n metadata?: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Model Pricing Rates (per 1 Million Tokens in USD)\r\n */\r\nexport interface ModelPricingRates {\r\n inputPer1M: number;\r\n outputPer1M: number;\r\n cachedInputPer1M?: number;\r\n reasoningPer1M?: number;\r\n cacheWritePer1M?: number;\r\n currency?: string;\r\n}\r\n\r\n/**\r\n * Aggregated Usage Summary\r\n */\r\nexport interface UsageSummary {\r\n totalRequests: number;\r\n totalTokens: number;\r\n totalInputTokens: number;\r\n totalOutputTokens: number;\r\n totalReasoningTokens: number;\r\n totalCostUSD: number;\r\n byModel: Record<\r\n string,\r\n {\r\n requests: number;\r\n tokens: number;\r\n costUSD: number;\r\n }\r\n >;\r\n}\r\n","import type { UsageEvent, UsageSummary, MeterOptions } from '../types';\r\n\r\n/**\r\n * Detects whether the current runtime is a serverless environment\r\n * (AWS Lambda, Vercel Serverless, Cloudflare Workers/Pages, Netlify, Deno Deploy, Next.js)\r\n */\r\nexport function isServerlessEnvironment(): boolean {\r\n if (typeof process !== 'undefined' && process.env) {\r\n if (\r\n process.env.VERCEL ||\r\n process.env.AWS_LAMBDA_FUNCTION_NAME ||\r\n process.env.LAMBDA_TASK_ROOT ||\r\n process.env.NETLIFY ||\r\n process.env.DENO_DEPLOYMENT_ID ||\r\n process.env.CF_PAGES ||\r\n process.env.NEXT_RUNTIME\r\n ) {\r\n return true;\r\n }\r\n }\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (g.EdgeRuntime || g.WebSocketPair) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n}\r\n\r\nconst activeBatchers = new Set<MeterBatcher>();\r\nlet exitListenerAttached = false;\r\n\r\nfunction ensureExitListener() {\r\n if (exitListenerAttached) return;\r\n if (typeof process !== 'undefined' && typeof process.once === 'function') {\r\n try {\r\n process.once('beforeExit', () => {\r\n for (const batcher of activeBatchers) {\r\n batcher.flush().catch(() => {});\r\n }\r\n });\r\n exitListenerAttached = true;\r\n } catch {\r\n // Fallback for restricted sandboxes\r\n }\r\n }\r\n}\r\n\r\nexport class MeterBatcher {\r\n private queue: UsageEvent[] = [];\r\n private timer: NodeJS.Timeout | null = null;\r\n private isFlushing: boolean = false;\r\n private readonly maxBatchSize: number;\r\n private readonly flushIntervalMs: number;\r\n private readonly isExplicitFlushInterval: boolean;\r\n private readonly onUsageCallback?: (event: UsageEvent) => void | Promise<void>;\r\n private readonly onBatchCallback?: (events: UsageEvent[]) => void | Promise<void>;\r\n private readonly onErrorCallback?: (error: Error, events: UsageEvent[]) => void;\r\n private readonly debug: boolean;\r\n\r\n // In-memory ledger for local stats\r\n private totalRequests = 0;\r\n private totalTokens = 0;\r\n private totalInputTokens = 0;\r\n private totalOutputTokens = 0;\r\n private totalReasoningTokens = 0;\r\n private totalCostUSD = 0;\r\n private byModel: Record<string, { requests: number; tokens: number; costUSD: number }> = {};\r\n\r\n constructor(options: MeterOptions = {}) {\r\n this.maxBatchSize = options.batching?.maxBatchSize ?? 50;\r\n this.flushIntervalMs = options.batching?.flushIntervalMs ?? 50;\r\n this.isExplicitFlushInterval = options.batching?.flushIntervalMs !== undefined;\r\n this.onUsageCallback = options.onUsage;\r\n this.onBatchCallback = options.onBatch;\r\n this.onErrorCallback = options.onError;\r\n this.debug = options.debug ?? false;\r\n\r\n activeBatchers.add(this);\r\n ensureExitListener();\r\n }\r\n\r\n /**\r\n * Enqueue a usage event for batch dispatching\r\n */\r\n public enqueue(event: UsageEvent): void {\r\n // 1. Update in-memory local ledger\r\n this.recordInLedger(event);\r\n\r\n // 2. Fire onUsage hook immediately\r\n if (this.onUsageCallback) {\r\n try {\r\n const res = this.onUsageCallback(event);\r\n if (res instanceof Promise) {\r\n res.catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Error in onUsage callback:', err);\r\n });\r\n }\r\n } catch (err) {\r\n if (this.debug) console.error('[vibezcheck] Error in onUsage callback:', err);\r\n }\r\n }\r\n\r\n // 3. If no onBatch handler is configured, we run in immediate local mode\r\n if (!this.onBatchCallback) {\r\n if (this.debug) {\r\n console.log(\r\n `[vibezcheck:local] 📊 ${event.model} | Tokens: ${event.usage.totalTokens} | Cost: $${event.cost.totalUSD.toFixed(6)}`\r\n );\r\n }\r\n return;\r\n }\r\n\r\n // 4. Queue for batch dispatch\r\n this.queue.push(event);\r\n\r\n if (this.queue.length >= this.maxBatchSize) {\r\n this.flush().catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Batch flush error:', err);\r\n });\r\n return;\r\n }\r\n\r\n // 5. Serverless Lifecycle Spooling: Auto-register with after() or waitUntil()\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (typeof g.after === 'function') {\r\n g.after(() => this.flush().catch(() => {}));\r\n return;\r\n }\r\n if (typeof g.waitUntil === 'function') {\r\n g.waitUntil(this.flush().catch(() => {}));\r\n return;\r\n }\r\n }\r\n\r\n // In serverless environments where timers are frozen on response, auto-flush immediately unless explicit interval given\r\n if (isServerlessEnvironment() && !this.isExplicitFlushInterval) {\r\n this.flush().catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Serverless auto-flush error:', err);\r\n });\r\n return;\r\n }\r\n\r\n if (!this.timer) {\r\n this.timer = setTimeout(() => {\r\n this.timer = null;\r\n this.flush().catch((err) => {\r\n if (this.debug) console.error('[vibezcheck] Debounce flush error:', err);\r\n });\r\n }, this.flushIntervalMs);\r\n }\r\n }\r\n\r\n /**\r\n * Immediately flush all queued events\r\n */\r\n public async flush(): Promise<void> {\r\n if (this.timer) {\r\n clearTimeout(this.timer);\r\n this.timer = null;\r\n }\r\n\r\n if (this.queue.length === 0 || !this.onBatchCallback || this.isFlushing) {\r\n return;\r\n }\r\n\r\n this.isFlushing = true;\r\n const eventsToSend = [...this.queue];\r\n this.queue = [];\r\n\r\n try {\r\n await this.onBatchCallback(eventsToSend);\r\n } catch (error) {\r\n const err = error instanceof Error ? error : new Error(String(error));\r\n if (this.debug) {\r\n console.error('[vibezcheck] Failed to flush meter event batch:', err);\r\n }\r\n if (this.onErrorCallback) {\r\n this.onErrorCallback(err, eventsToSend);\r\n }\r\n } finally {\r\n this.isFlushing = false;\r\n // If new items were queued while flushing, trigger another flush\r\n if (this.queue.length > 0) {\r\n this.flush().catch(() => {});\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Updates internal in-memory ledger\r\n */\r\n private recordInLedger(event: UsageEvent): void {\r\n this.totalRequests += 1;\r\n this.totalTokens += event.usage.totalTokens;\r\n this.totalInputTokens += event.usage.inputTokens;\r\n this.totalOutputTokens += event.usage.outputTokens;\r\n this.totalReasoningTokens += event.usage.reasoningTokens ?? 0;\r\n this.totalCostUSD += event.cost.totalUSD;\r\n\r\n const modelKey = event.model;\r\n if (!this.byModel[modelKey]) {\r\n this.byModel[modelKey] = { requests: 0, tokens: 0, costUSD: 0 };\r\n }\r\n this.byModel[modelKey].requests += 1;\r\n this.byModel[modelKey].tokens += event.usage.totalTokens;\r\n this.byModel[modelKey].costUSD += event.cost.totalUSD;\r\n }\r\n\r\n /**\r\n * Get in-memory usage summary\r\n */\r\n public getSummary(): UsageSummary {\r\n return {\r\n totalRequests: this.totalRequests,\r\n totalTokens: this.totalTokens,\r\n totalInputTokens: this.totalInputTokens,\r\n totalOutputTokens: this.totalOutputTokens,\r\n totalReasoningTokens: this.totalReasoningTokens,\r\n totalCostUSD: Number(this.totalCostUSD.toFixed(6)),\r\n byModel: { ...this.byModel },\r\n };\r\n }\r\n\r\n /**\r\n * Reset in-memory ledger\r\n */\r\n public resetLedger(): void {\r\n this.totalRequests = 0;\r\n this.totalTokens = 0;\r\n this.totalInputTokens = 0;\r\n this.totalOutputTokens = 0;\r\n this.totalReasoningTokens = 0;\r\n this.totalCostUSD = 0;\r\n this.byModel = {};\r\n }\r\n}\r\n","import type { TokenUsage } from '../../types';\r\n\r\nexport interface ExtractedUsage {\r\n model: string;\r\n provider: string;\r\n usage: TokenUsage;\r\n}\r\n\r\n/**\r\n * Extracts token usage from OpenAI synchronous responses (ChatCompletion, Responses, Embeddings)\r\n */\r\nexport function extractOpenAIResponseUsage(response: any): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // 1. Standard OpenAI ChatCompletion\r\n if ('choices' in response && 'usage' in response && response.usage) {\r\n const rawUsage = response.usage;\r\n const model = response.model || 'gpt-4o';\r\n\r\n const inputTokens = rawUsage.prompt_tokens ?? 0;\r\n const outputTokens = rawUsage.completion_tokens ?? 0;\r\n const reasoningTokens = rawUsage.completion_tokens_details?.reasoning_tokens ?? 0;\r\n const cachedTokens = rawUsage.prompt_tokens_details?.cached_tokens ?? 0;\r\n\r\n return {\r\n model,\r\n provider: 'openai',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n // 2. OpenAI Embeddings Response\r\n if ('data' in response && 'usage' in response && response.usage && 'model' in response) {\r\n const rawUsage = response.usage;\r\n const inputTokens = rawUsage.prompt_tokens ?? 0;\r\n\r\n return {\r\n model: response.model || 'text-embedding-3-small',\r\n provider: 'openai',\r\n usage: {\r\n inputTokens,\r\n outputTokens: 0,\r\n totalTokens: inputTokens,\r\n },\r\n };\r\n }\r\n\r\n // 3. OpenAI Responses API (New standard)\r\n if ('status' in response && 'usage' in response && response.usage) {\r\n const rawUsage = response.usage;\r\n const model = response.model || 'gpt-5.6-sol';\r\n\r\n const inputTokens = rawUsage.input_tokens ?? rawUsage.prompt_tokens ?? 0;\r\n const outputTokens = rawUsage.output_tokens ?? rawUsage.completion_tokens ?? 0;\r\n const reasoningTokens =\r\n rawUsage.output_token_details?.reasoning_tokens ??\r\n rawUsage.completion_tokens_details?.reasoning_tokens ??\r\n 0;\r\n const cachedTokens =\r\n rawUsage.input_token_details?.cached_tokens ??\r\n rawUsage.prompt_tokens_details?.cached_tokens ??\r\n 0;\r\n\r\n return {\r\n model,\r\n provider: 'openai',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Extracts token usage from an individual OpenAI stream chunk or stream accumulator\r\n */\r\nexport function inspectOpenAIStreamChunk(chunk: any): {\r\n model?: string;\r\n usage?: TokenUsage;\r\n} {\r\n if (!chunk || typeof chunk !== 'object') return {};\r\n\r\n const model = chunk.model;\r\n\r\n // Final chunk with usage object (when stream_options: { include_usage: true }, finish chunk, or Groq / DeepSeek / Mistral stream ending)\r\n const rawUsage =\r\n (chunk.type === 'finish' ? chunk.usage : null) ||\r\n chunk.usage ||\r\n chunk.token_usage ||\r\n chunk.x_groq?.usage ||\r\n chunk.usageMetadata;\r\n if (rawUsage) {\r\n let inputTokens = 0;\r\n let outputTokens = 0;\r\n let reasoningTokens = 0;\r\n let cachedTokens = 0;\r\n\r\n if (typeof rawUsage.inputTokens === 'object' && rawUsage.inputTokens !== null) {\r\n inputTokens = rawUsage.inputTokens.total ?? rawUsage.inputTokens.noCache ?? 0;\r\n cachedTokens = rawUsage.inputTokens.cacheRead ?? 0;\r\n } else if (typeof rawUsage.promptTokens === 'number') {\r\n inputTokens = rawUsage.promptTokens;\r\n } else if (typeof rawUsage.inputTokens === 'number') {\r\n inputTokens = rawUsage.inputTokens;\r\n } else {\r\n inputTokens =\r\n rawUsage.prompt_tokens ??\r\n rawUsage.input_tokens ??\r\n rawUsage.promptTokenCount ??\r\n 0;\r\n }\r\n\r\n if (typeof rawUsage.outputTokens === 'object' && rawUsage.outputTokens !== null) {\r\n outputTokens = rawUsage.outputTokens.total ?? rawUsage.outputTokens.text ?? 0;\r\n reasoningTokens = rawUsage.outputTokens.reasoning ?? 0;\r\n } else if (typeof rawUsage.completionTokens === 'number') {\r\n outputTokens = rawUsage.completionTokens;\r\n } else if (typeof rawUsage.outputTokens === 'number') {\r\n outputTokens = rawUsage.outputTokens;\r\n } else {\r\n outputTokens =\r\n rawUsage.completion_tokens ??\r\n rawUsage.output_tokens ??\r\n rawUsage.candidatesTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!reasoningTokens) {\r\n reasoningTokens =\r\n rawUsage.completion_tokens_details?.reasoning_tokens ??\r\n rawUsage.output_token_details?.reasoning_tokens ??\r\n rawUsage.reasoning_tokens ??\r\n rawUsage.reasoningTokens ??\r\n rawUsage.thoughtsTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!cachedTokens) {\r\n cachedTokens =\r\n rawUsage.prompt_tokens_details?.cached_tokens ??\r\n rawUsage.input_token_details?.cached_tokens ??\r\n rawUsage.prompt_cache_hit_tokens ??\r\n rawUsage.cached_tokens ??\r\n rawUsage.cachedTokens ??\r\n rawUsage.cachedContentTokenCount ??\r\n 0;\r\n }\r\n\r\n return {\r\n model,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n // Response API stream event (response.completed or response.done)\r\n if (chunk.type === 'response.completed' || chunk.type === 'response.done') {\r\n if (chunk.response?.usage) {\r\n const rawUsage = chunk.response.usage;\r\n const inputTokens = rawUsage.input_tokens ?? 0;\r\n const outputTokens = rawUsage.output_tokens ?? 0;\r\n const reasoningTokens = rawUsage.output_token_details?.reasoning_tokens ?? 0;\r\n const cachedTokens = rawUsage.input_token_details?.cached_tokens ?? 0;\r\n\r\n return {\r\n model: chunk.response.model || model,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n }\r\n\r\n return { model };\r\n}\r\n","import type { TokenUsage } from '../../types';\r\nimport type { ExtractedUsage } from './openai';\r\n\r\n/**\r\n * Extracts token usage from Anthropic synchronous responses\r\n */\r\nexport function extractAnthropicResponseUsage(response: any): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // Anthropic Message response has type: 'message' or role: 'assistant' with usage\r\n if (response.type === 'message' || ('content' in response && 'usage' in response)) {\r\n const rawUsage = response.usage || {};\r\n const model = response.model || 'claude-3-7-sonnet';\r\n\r\n const inputTokens = rawUsage.input_tokens ?? 0;\r\n const outputTokens = rawUsage.output_tokens ?? 0;\r\n const cachedTokens = rawUsage.cache_read_input_tokens ?? 0;\r\n const cacheWriteTokens = rawUsage.cache_creation_input_tokens ?? 0;\r\n\r\n // Check content blocks for thinking/reasoning tokens count or thinking blocks\r\n let reasoningTokens: number | undefined = undefined;\r\n if (Array.isArray(response.content)) {\r\n const thinkingBlocks = response.content.filter((b: any) => b.type === 'thinking');\r\n if (thinkingBlocks.length > 0) {\r\n // Approximate or extract explicit thinking tokens if present in metadata\r\n reasoningTokens = (rawUsage as any).thinking_tokens ?? undefined;\r\n }\r\n }\r\n\r\n return {\r\n model,\r\n provider: 'anthropic',\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens,\r\n visibleOutputTokens:\r\n reasoningTokens !== undefined ? Math.max(0, outputTokens - reasoningTokens) : outputTokens,\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/**\r\n * Accumulates stream events across an Anthropic raw message stream\r\n */\r\nexport class AnthropicStreamAccumulator {\r\n private model: string = 'claude-3-7-sonnet';\r\n private inputTokens: number = 0;\r\n private outputTokens: number = 0;\r\n private cachedTokens: number = 0;\r\n private cacheWriteTokens: number = 0;\r\n private reasoningTokens: number = 0;\r\n\r\n processEvent(event: any): void {\r\n if (!event || typeof event !== 'object') return;\r\n\r\n // 1. message_start (contains model and initial input usage)\r\n if (event.type === 'message_start' && event.message) {\r\n if (event.message.model) {\r\n this.model = event.message.model;\r\n }\r\n if (event.message.usage) {\r\n this.inputTokens = event.message.usage.input_tokens ?? 0;\r\n this.cachedTokens = event.message.usage.cache_read_input_tokens ?? 0;\r\n this.cacheWriteTokens = event.message.usage.cache_creation_input_tokens ?? 0;\r\n }\r\n }\r\n\r\n // 2. message_delta (contains final output usage)\r\n if (event.type === 'message_delta' && event.usage) {\r\n this.outputTokens = event.usage.output_tokens ?? 0;\r\n if (event.usage.thinking_tokens) {\r\n this.reasoningTokens = event.usage.thinking_tokens;\r\n }\r\n }\r\n\r\n // 3. content_block_start / content_block_delta for thinking blocks\r\n if (event.type === 'content_block_start' && event.content_block?.type === 'thinking') {\r\n // thinking block detected\r\n }\r\n }\r\n\r\n getUsage(): ExtractedUsage {\r\n return {\r\n model: this.model,\r\n provider: 'anthropic',\r\n usage: {\r\n inputTokens: this.inputTokens,\r\n outputTokens: this.outputTokens,\r\n totalTokens: this.inputTokens + this.outputTokens,\r\n reasoningTokens: this.reasoningTokens > 0 ? this.reasoningTokens : undefined,\r\n visibleOutputTokens:\r\n this.reasoningTokens > 0\r\n ? Math.max(0, this.outputTokens - this.reasoningTokens)\r\n : this.outputTokens,\r\n cachedTokens: this.cachedTokens > 0 ? this.cachedTokens : undefined,\r\n cacheWriteTokens: this.cacheWriteTokens > 0 ? this.cacheWriteTokens : undefined,\r\n },\r\n };\r\n }\r\n}\r\n","import type { TokenUsage } from '../../types';\r\nimport type { ExtractedUsage } from './openai';\r\n\r\n/**\r\n * Extracts token usage from Google Gemini API response or chunk\r\n */\r\nexport function extractGeminiResponseUsage(\r\n response: any,\r\n fallbackModel: string = 'gemini-3.7-flash'\r\n): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // Gemini returns usageMetadata on response or GenerateContentResult\r\n const usageMetadata = response.usageMetadata || response.response?.usageMetadata;\r\n\r\n if (usageMetadata) {\r\n const inputTokens = usageMetadata.promptTokenCount ?? 0;\r\n const baseOutputTokens = usageMetadata.candidatesTokenCount ?? 0;\r\n const thoughtsTokenCount =\r\n usageMetadata.thoughtsTokenCount ?? (usageMetadata as any).reasoningTokenCount ?? 0;\r\n const cachedTokens = usageMetadata.cachedContentTokenCount ?? 0;\r\n\r\n const totalOutput = baseOutputTokens + thoughtsTokenCount;\r\n const model = response.model || response.response?.model || fallbackModel;\r\n\r\n return {\r\n model,\r\n provider: 'google',\r\n usage: {\r\n inputTokens,\r\n outputTokens: totalOutput,\r\n totalTokens: inputTokens + totalOutput,\r\n reasoningTokens: thoughtsTokenCount > 0 ? thoughtsTokenCount : undefined,\r\n visibleOutputTokens: baseOutputTokens,\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n","import type { TokenUsage } from '../../types';\r\nimport type { ExtractedUsage } from './openai';\r\n\r\n/**\r\n * Extracts token usage from generic LLM provider objects (DeepSeek, Groq, Mistral, Ollama, Cohere, Together)\r\n */\r\nexport function extractGenericResponseUsage(\r\n response: any,\r\n fallbackModel: string = 'generic-llm',\r\n fallbackProvider: string = 'generic'\r\n): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // Check common usage property locations\r\n const usage = response.usage || response.token_usage || response.usageMetadata;\r\n\r\n if (usage) {\r\n let inputTokens = 0;\r\n let outputTokens = 0;\r\n let reasoningTokens = 0;\r\n let cachedTokens = 0;\r\n\r\n if (typeof usage.inputTokens === 'object' && usage.inputTokens !== null) {\r\n inputTokens = usage.inputTokens.total ?? usage.inputTokens.noCache ?? 0;\r\n cachedTokens = usage.inputTokens.cacheRead ?? 0;\r\n } else if (typeof usage.promptTokens === 'number') {\r\n inputTokens = usage.promptTokens;\r\n } else if (typeof usage.inputTokens === 'number') {\r\n inputTokens = usage.inputTokens;\r\n } else {\r\n inputTokens =\r\n usage.prompt_tokens ??\r\n usage.input_tokens ??\r\n usage.promptTokenCount ??\r\n usage.prompt_eval_count ??\r\n 0;\r\n }\r\n\r\n if (typeof usage.outputTokens === 'object' && usage.outputTokens !== null) {\r\n outputTokens = usage.outputTokens.total ?? usage.outputTokens.text ?? 0;\r\n reasoningTokens = usage.outputTokens.reasoning ?? 0;\r\n } else if (typeof usage.completionTokens === 'number') {\r\n outputTokens = usage.completionTokens;\r\n } else if (typeof usage.outputTokens === 'number') {\r\n outputTokens = usage.outputTokens;\r\n } else {\r\n outputTokens =\r\n usage.completion_tokens ??\r\n usage.output_tokens ??\r\n usage.candidatesTokenCount ??\r\n usage.eval_count ??\r\n 0;\r\n }\r\n\r\n if (!reasoningTokens) {\r\n reasoningTokens =\r\n usage.reasoning_tokens ??\r\n usage.thoughtsTokenCount ??\r\n usage.completion_tokens_details?.reasoning_tokens ??\r\n 0;\r\n }\r\n\r\n if (!cachedTokens) {\r\n cachedTokens =\r\n usage.prompt_tokens_details?.cached_tokens ??\r\n usage.cached_tokens ??\r\n usage.cachedContentTokenCount ??\r\n 0;\r\n }\r\n\r\n const model = response.model || fallbackModel;\r\n const provider = response.provider || fallbackProvider;\r\n\r\n return {\r\n model,\r\n provider,\r\n usage: {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n },\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n","import type { ExtractedUsage } from './openai';\r\nimport { extractOpenAIResponseUsage } from './openai';\r\nimport { extractAnthropicResponseUsage } from './anthropic';\r\nimport { extractGeminiResponseUsage } from './gemini';\r\nimport { extractGenericResponseUsage } from './generic';\r\n\r\nexport * from './openai';\r\nexport * from './anthropic';\r\nexport * from './gemini';\r\nexport * from './generic';\r\n\r\n/**\r\n * Universal polymorphic response detector\r\n */\r\nexport function detectAndExtractUsage(\r\n response: any,\r\n fallbackModel?: string,\r\n fallbackProvider?: string\r\n): ExtractedUsage | null {\r\n if (!response || typeof response !== 'object') return null;\r\n\r\n // 1. Try OpenAI\r\n const openaiResult = extractOpenAIResponseUsage(response);\r\n if (openaiResult) return openaiResult;\r\n\r\n // 2. Try Anthropic\r\n const anthropicResult = extractAnthropicResponseUsage(response);\r\n if (anthropicResult) return anthropicResult;\r\n\r\n // 3. Try Gemini\r\n const geminiResult = extractGeminiResponseUsage(response, fallbackModel);\r\n if (geminiResult) return geminiResult;\r\n\r\n // 4. Try Generic\r\n const genericResult = extractGenericResponseUsage(response, fallbackModel, fallbackProvider);\r\n if (genericResult) return genericResult;\r\n\r\n return null;\r\n}\r\n","import type { ModelPricingRates } from '../types';\nimport { normalizeModelKey } from './table';\n\nexport interface PricingSyncOptions {\n /**\n * Remote manifest URL to fetch pricing from.\n * Defaults to the official hosted pricing-v1.json manifest.\n */\n manifestUrl?: string;\n\n /**\n * Request timeout in milliseconds (default: 3000ms).\n */\n timeoutMs?: number;\n\n /**\n * Custom fetch implementation (defaults to globalThis.fetch).\n */\n fetch?: typeof fetch;\n\n /**\n * Maximum cache age in milliseconds before re-fetching (default: 3600_000 = 1 hour).\n */\n cacheTtlMs?: number;\n\n /**\n * If true, bypass cache TTL and force an immediate re-fetch.\n */\n force?: boolean;\n\n /**\n * Fallback manifest JSON string or object to seed cache if network fails.\n */\n fallbackManifest?: unknown;\n\n /**\n * Custom headers for authentication or versioning.\n */\n headers?: Record<string, string>;\n}\n\nexport interface PricingSyncStatus {\n status: 'idle' | 'syncing' | 'synced' | 'failed';\n lastSyncTime: number | null;\n lastSyncETag: string | null;\n cachedModelsCount: number;\n lastError: string | null;\n}\n\nexport interface StripePricingItem {\n publisher?: string;\n provider?: string;\n model: string;\n prices_per_1m: {\n input_token?: number | null;\n output_token?: number | null;\n cached_input?: number | null;\n cached_output?: number | null;\n cached_read?: number | null;\n cached_write?: number | null;\n };\n}\n\nexport const DEFAULT_MANIFEST_URL =\n 'https://raw.githubusercontent.com/seeyouin2x5x/vibezcheck-sdk/main/manifest/pricing-v1.json';\n\nexport const VERCEL_GATEWAY_MODELS_URL = 'https://ai-gateway.vercel.sh/v1/models';\n\nexport interface VercelGatewayModelItem {\n id: string;\n name?: string;\n owned_by?: string;\n type?: string;\n pricing?: {\n input?: string | number | null;\n output?: string | number | null;\n input_cache_read?: string | number | null;\n input_cache_write?: string | number | null;\n };\n prices_per_1m?: {\n input_token?: number | null;\n output_token?: number | null;\n cached_input?: number | null;\n cached_write?: number | null;\n };\n}\n\nconst DEFAULT_TIMEOUT_MS = 3000;\nconst DEFAULT_CACHE_TTL_MS = 3600_000; // 1 hour\n\n// In-memory fast cache\nconst dynamicPricingCache: Record<string, ModelPricingRates> = {};\n\nlet lastSyncTime: number | null = null;\nlet lastSyncETag: string | null = null;\nlet syncStatus: 'idle' | 'syncing' | 'synced' | 'failed' = 'idle';\nlet lastError: string | null = null;\n\n/**\n * Synchronously retrieves a rate from the dynamic pricing cache\n */\nexport function getDynamicRate(model: string): ModelPricingRates | undefined {\n if (!model) return undefined;\n const key = model.toLowerCase().trim();\n if (dynamicPricingCache[key]) {\n return dynamicPricingCache[key];\n }\n const normalized = normalizeModelKey(key);\n if (dynamicPricingCache[normalized]) {\n return dynamicPricingCache[normalized];\n }\n return undefined;\n}\n\n/**\n * Returns the count of models currently held in dynamic cache\n */\nexport function getDynamicCacheSize(): number {\n return Object.keys(dynamicPricingCache).length;\n}\n\n/**\n * Resets the in-memory dynamic pricing cache\n */\nexport function clearDynamicCache(): void {\n for (const k of Object.keys(dynamicPricingCache)) {\n delete dynamicPricingCache[k];\n }\n lastSyncTime = null;\n lastSyncETag = null;\n syncStatus = 'idle';\n lastError = null;\n}\n\n/**\n * Current synchronization status and telemetry\n */\nexport function getSyncStatus(): PricingSyncStatus {\n return {\n status: syncStatus,\n lastSyncTime,\n lastSyncETag,\n cachedModelsCount: Object.keys(dynamicPricingCache).length,\n lastError,\n };\n}\n\n/**\n * Ingests and registers an array of Stripe rate items or a manifest object into cache\n */\nexport function seedPricingCache(manifest: unknown): number {\n if (!manifest || typeof manifest !== 'object') {\n return 0;\n }\n\n let count = 0;\n\n // Case 1: Array of pricing items (Stripe or Vercel)\n if (Array.isArray(manifest)) {\n for (const item of manifest) {\n if (registerStripeItem(item) || registerVercelGatewayItem(item)) {\n count++;\n }\n }\n return count;\n }\n\n const obj = manifest as Record<string, any>;\n\n // Case 2: Vercel Gateway direct endpoint response: { object: \"list\", data: [...] }\n if (obj.object === 'list' && Array.isArray(obj.data)) {\n for (const item of obj.data) {\n if (registerVercelGatewayItem(item) || registerStripeItem(item)) {\n count++;\n }\n }\n return count;\n }\n\n // Case 3: Object with models array (e.g. { models: [...] })\n if (Array.isArray(obj.models)) {\n for (const item of obj.models) {\n if (registerStripeItem(item) || registerVercelGatewayItem(item)) {\n count++;\n }\n }\n }\n\n // Case 4: Object with vercel_gateway_models array\n if (Array.isArray(obj.vercel_gateway_models)) {\n for (const item of obj.vercel_gateway_models) {\n if (registerVercelGatewayItem(item) || registerStripeItem(item)) {\n count++;\n }\n }\n }\n\n // Case 5: Object with rates dictionary (e.g. { rates: { \"gpt-4o\": { inputPer1M: 2.5, ... } } })\n const ratesDict = obj.rates && typeof obj.rates === 'object' ? obj.rates : obj;\n for (const [key, val] of Object.entries(ratesDict)) {\n if (\n key === 'models' ||\n key === 'rates' ||\n key === 'version' ||\n key === '$schema' ||\n key === 'sources' ||\n key === 'vercel_gateway_models'\n ) {\n continue;\n }\n const v = val as any;\n if (v && typeof v === 'object' && typeof v.inputPer1M === 'number' && typeof v.outputPer1M === 'number') {\n registerRate(key, {\n inputPer1M: Math.max(0, v.inputPer1M),\n outputPer1M: Math.max(0, v.outputPer1M),\n cachedInputPer1M: typeof v.cachedInputPer1M === 'number' ? Math.max(0, v.cachedInputPer1M) : undefined,\n reasoningPer1M: typeof v.reasoningPer1M === 'number' ? Math.max(0, v.reasoningPer1M) : undefined,\n cacheWritePer1M: typeof v.cacheWritePer1M === 'number' ? Math.max(0, v.cacheWritePer1M) : undefined,\n currency: typeof v.currency === 'string' ? v.currency : 'USD',\n });\n count++;\n }\n }\n\n return count;\n}\n\nfunction registerRate(key: string, rate: ModelPricingRates): void {\n const cleanKey = key.toLowerCase().trim();\n dynamicPricingCache[cleanKey] = rate;\n const normalized = normalizeModelKey(cleanKey);\n dynamicPricingCache[normalized] = rate;\n}\n\nfunction registerVercelGatewayItem(entry: any): boolean {\n if (!entry || typeof entry !== 'object') return false;\n const modelId = typeof entry.id === 'string' ? entry.id : typeof entry.model === 'string' ? entry.model : null;\n if (!modelId) return false;\n\n // If entry has prices_per_1m already precomputed\n if (entry.prices_per_1m && typeof entry.prices_per_1m.input_token === 'number' && typeof entry.prices_per_1m.output_token === 'number') {\n return registerStripeItem({ ...entry, model: modelId });\n }\n\n const p = entry.pricing;\n if (!p || typeof p !== 'object') return false;\n\n const inSingle = p.input !== undefined && p.input !== null ? parseFloat(String(p.input)) : null;\n const outSingle = p.output !== undefined && p.output !== null ? parseFloat(String(p.output)) : null;\n if (inSingle === null || isNaN(inSingle) || outSingle === null || isNaN(outSingle)) {\n return false;\n }\n\n const roundRate = (v: number) => Math.round(v * 1e6) / 1e6;\n\n const rateObj: ModelPricingRates = {\n inputPer1M: Math.max(0, roundRate(inSingle * 1_000_000)),\n outputPer1M: Math.max(0, roundRate(outSingle * 1_000_000)),\n currency: 'USD',\n };\n\n if (p.input_cache_read !== undefined && p.input_cache_read !== null) {\n const cr = parseFloat(String(p.input_cache_read));\n if (!isNaN(cr)) {\n rateObj.cachedInputPer1M = Math.max(0, roundRate(cr * 1_000_000));\n }\n }\n if (p.input_cache_write !== undefined && p.input_cache_write !== null) {\n const cw = parseFloat(String(p.input_cache_write));\n if (!isNaN(cw)) {\n rateObj.cacheWritePer1M = Math.max(0, roundRate(cw * 1_000_000));\n }\n }\n\n const fullId = modelId.toLowerCase().trim();\n registerRate(fullId, rateObj);\n\n if (fullId.includes('/')) {\n const stripped = fullId.split('/').slice(1).join('/');\n registerRate(stripped, rateObj);\n }\n\n if (entry.owned_by && typeof entry.owned_by === 'string') {\n const owner = entry.owned_by.toLowerCase().replace(/\\s+/g, '-');\n dynamicPricingCache[`${owner}/${fullId}`] = rateObj;\n }\n\n return true;\n}\n\nfunction registerStripeItem(entry: any): boolean {\n const modelKey = typeof entry.model === 'string' ? entry.model : typeof entry.id === 'string' ? entry.id : null;\n if (!entry || typeof entry !== 'object' || !modelKey) {\n return false;\n }\n const p = entry.prices_per_1m;\n if (!p || typeof p !== 'object') return false;\n if (typeof p.input_token !== 'number' || typeof p.output_token !== 'number') return false;\n\n const rateObj: ModelPricingRates = {\n inputPer1M: Math.max(0, p.input_token),\n outputPer1M: Math.max(0, p.output_token),\n currency: 'USD',\n };\n\n if (typeof p.cached_input === 'number') {\n rateObj.cachedInputPer1M = Math.max(0, p.cached_input);\n } else if (typeof p.cached_read === 'number') {\n rateObj.cachedInputPer1M = Math.max(0, p.cached_read);\n }\n\n if (typeof p.cached_write === 'number') {\n rateObj.cacheWritePer1M = Math.max(0, p.cached_write);\n }\n\n const baseKey = modelKey.toLowerCase().trim();\n registerRate(baseKey, rateObj);\n\n if (entry.publisher && typeof entry.publisher === 'string') {\n const pub = entry.publisher.toLowerCase().replace(/\\s+/g, '-');\n dynamicPricingCache[`${pub}/${baseKey}`] = rateObj;\n if (pub === 'mistral-ai') {\n dynamicPricingCache[`mistral/${baseKey}`] = rateObj;\n }\n }\n\n if (entry.provider && typeof entry.provider === 'string') {\n const prov = entry.provider.toLowerCase().replace(/\\s+/g, '-');\n dynamicPricingCache[`${prov}/${baseKey}`] = rateObj;\n }\n\n return true;\n}\n\n/**\n * Asynchronously synchronizes the LLM pricing manifest from a remote endpoint.\n *\n * Guaranteed Safe & Non-Throwing:\n * If network is down, request times out, or manifest is invalid, returns false\n * and seamlessly preserves existing cached or bundled rates (offline fallback).\n */\nexport async function syncPricingManifest(options: PricingSyncOptions = {}): Promise<boolean> {\n const ttl = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;\n const now = Date.now();\n\n // If cache is fresh and not forced, reuse existing cache\n if (!options.force && lastSyncTime !== null && now - lastSyncTime < ttl && Object.keys(dynamicPricingCache).length > 0) {\n return true;\n }\n\n const url = options.manifestUrl || DEFAULT_MANIFEST_URL;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const fetchFn = options.fetch || globalThis.fetch;\n\n if (typeof fetchFn !== 'function') {\n // No fetch available in environment; try fallback manifest\n if (options.fallbackManifest) {\n seedPricingCache(options.fallbackManifest);\n lastSyncTime = now;\n syncStatus = 'synced';\n return true;\n }\n syncStatus = 'failed';\n lastError = 'Fetch API unavailable in runtime environment';\n return false;\n }\n\n syncStatus = 'syncing';\n\n const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;\n const timeoutId = controller ? setTimeout(() => controller.abort(), timeoutMs) : null;\n\n try {\n const reqHeaders: Record<string, string> = {\n Accept: 'application/json',\n ...(options.headers || {}),\n };\n\n if (lastSyncETag && !options.force) {\n reqHeaders['If-None-Match'] = lastSyncETag;\n }\n\n const response = await fetchFn(url, {\n method: 'GET',\n headers: reqHeaders,\n signal: controller?.signal,\n });\n\n if (timeoutId) clearTimeout(timeoutId);\n\n // 304 Not Modified: Existing dynamic cache is still up to date\n if (response.status === 304) {\n lastSyncTime = now;\n syncStatus = 'synced';\n lastError = null;\n return true;\n }\n\n if (!response.ok) {\n throw new Error(`HTTP ${response.status} ${response.statusText}`);\n }\n\n const etag = response.headers?.get ? response.headers.get('etag') : null;\n if (etag) {\n lastSyncETag = etag;\n }\n\n const data = await response.json();\n const seeded = seedPricingCache(data);\n\n if (seeded === 0) {\n throw new Error('Manifest contains no recognizable pricing rates');\n }\n\n lastSyncTime = now;\n syncStatus = 'synced';\n lastError = null;\n return true;\n } catch (err: any) {\n if (timeoutId) clearTimeout(timeoutId);\n\n syncStatus = 'failed';\n lastError = err?.message || 'Unknown network error';\n\n // Seed fallback if provided\n if (options.fallbackManifest) {\n seedPricingCache(options.fallbackManifest);\n }\n\n // Graceful offline fallback: Never throw, return false\n return false;\n }\n}\n\n/**\n * Non-blocking, fire-and-forget background synchronization.\n * Triggers sync in background without awaiting or crashing if network is unavailable.\n */\nexport function triggerBackgroundSync(options: PricingSyncOptions = {}): void {\n syncPricingManifest(options).catch(() => {\n // Silently caught - offline fallback preserved\n });\n}\n\n/**\n * Synchronizes LLM token pricing directly from Vercel AI Gateway (https://ai-gateway.vercel.sh/v1/models).\n * Converts single-token rates into per-1M-token rates and populates dynamic cache.\n */\nexport async function syncVercelGateway(options: PricingSyncOptions = {}): Promise<boolean> {\n return syncPricingManifest({\n manifestUrl: VERCEL_GATEWAY_MODELS_URL,\n ...options,\n });\n}\n\n/**\n * Non-blocking, fire-and-forget background synchronization from Vercel AI Gateway.\n */\nexport function triggerVercelGatewaySync(options: PricingSyncOptions = {}): void {\n syncVercelGateway(options).catch(() => {\n // Silently caught - offline fallback preserved\n });\n}\n\n","import type { ModelPricingRates } from '../types';\r\nimport { getDynamicRate } from './sync';\r\n\r\n/**\r\n * Built-in Registry of Model Pricing (USD per 1 Million Tokens)\r\n * Sourced from official 2026 provider pricing tables.\r\n */\r\nexport const MODEL_PRICING_TABLE: Record<string, ModelPricingRates> = {\r\n // --- OpenAI (Modern & Reasoning) ---\r\n 'gpt-5.6-sol': { inputPer1M: 4.0, outputPer1M: 20.0, cachedInputPer1M: 0.4 },\r\n 'gpt-5.6-terra': { inputPer1M: 2.0, outputPer1M: 12.0, cachedInputPer1M: 0.2 },\r\n 'gpt-5.6-luna': { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },\r\n 'gpt-5': { inputPer1M: 4.0, outputPer1M: 20.0, cachedInputPer1M: 0.4 },\r\n 'gpt-5-mini': { inputPer1M: 0.2, outputPer1M: 1.2, cachedInputPer1M: 0.02 },\r\n 'o1': { inputPer1M: 15.0, outputPer1M: 60.0, cachedInputPer1M: 7.5 },\r\n 'o1-mini': { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },\r\n 'o3': { inputPer1M: 15.0, outputPer1M: 60.0, cachedInputPer1M: 7.5 },\r\n 'o3-mini': { inputPer1M: 1.1, outputPer1M: 4.4, cachedInputPer1M: 0.55 },\r\n 'gpt-4o': { inputPer1M: 2.5, outputPer1M: 10.0, cachedInputPer1M: 1.25 },\r\n 'gpt-4o-mini': { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.075 },\r\n 'gpt-4.5': { inputPer1M: 75.0, outputPer1M: 150.0, cachedInputPer1M: 37.5 },\r\n 'gpt-4.5-preview': { inputPer1M: 75.0, outputPer1M: 150.0, cachedInputPer1M: 37.5 },\r\n 'chatgpt-4o-latest': { inputPer1M: 5.0, outputPer1M: 15.0 },\r\n 'gpt-4.1': { inputPer1M: 2.0, outputPer1M: 8.0, cachedInputPer1M: 1.0 },\r\n 'gpt-4.1-nano': { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.05 },\r\n 'gpt-6-astra': { inputPer1M: 5.0, outputPer1M: 25.0, cachedInputPer1M: 0.5 },\r\n 'gpt-6-astra-fast': { inputPer1M: 3.0, outputPer1M: 15.0, cachedInputPer1M: 0.3 },\r\n 'gpt-image-2.5-flare': { inputPer1M: 0.0, outputPer1M: 0.04 },\r\n 'gpt-image-2.5-sunburst': { inputPer1M: 0.0, outputPer1M: 0.08 },\r\n\r\n // --- OpenAI (Legacy & Backward Compatibility) ---\r\n 'gpt-4-turbo': { inputPer1M: 10.0, outputPer1M: 30.0, cachedInputPer1M: 5.0 },\r\n 'gpt-4-turbo-preview': { inputPer1M: 10.0, outputPer1M: 30.0, cachedInputPer1M: 5.0 },\r\n 'gpt-4': { inputPer1M: 30.0, outputPer1M: 60.0 },\r\n 'gpt-4-32k': { inputPer1M: 60.0, outputPer1M: 120.0 },\r\n 'gpt-3.5-turbo': { inputPer1M: 0.5, outputPer1M: 1.5 },\r\n 'gpt-3.5-turbo-16k': { inputPer1M: 3.0, outputPer1M: 4.0 },\r\n 'text-embedding-3-small': { inputPer1M: 0.02, outputPer1M: 0.0 },\r\n 'text-embedding-3-large': { inputPer1M: 0.13, outputPer1M: 0.0 },\r\n 'text-embedding-ada-002': { inputPer1M: 0.10, outputPer1M: 0.0 },\r\n\r\n // --- Anthropic (Modern & Extended Thinking) ---\r\n 'claude-haiku-5.5': { inputPer1M: 0.1, outputPer1M: 0.5, cachedInputPer1M: 0.01 },\r\n 'claude-sonnet-5.5': { inputPer1M: 2.0, outputPer1M: 10.0, cachedInputPer1M: 0.1 },\r\n 'claude-opus-5.5': { inputPer1M: 4.0, outputPer1M: 20.0, cachedInputPer1M: 0.2 },\r\n 'claude-opus-5.5-fast': { inputPer1M: 8.0, outputPer1M: 40.0, cachedInputPer1M: 0.4 },\r\n 'claude-3-7-sonnet': { inputPer1M: 0.59, outputPer1M: 2.93, cachedInputPer1M: 0.3 },\r\n 'claude-sonnet-5': { inputPer1M: 2.0, outputPer1M: 10.0, cachedInputPer1M: 0.3 },\r\n 'claude-3-5-sonnet': { inputPer1M: 3.0, outputPer1M: 15.0, cachedInputPer1M: 0.3 },\r\n 'claude-3-5-haiku': { inputPer1M: 0.8, outputPer1M: 4.0, cachedInputPer1M: 0.08 },\r\n 'haiku-4.5': { inputPer1M: 1.0, outputPer1M: 5.0, cachedInputPer1M: 0.1 },\r\n 'claude-opus-5': { inputPer1M: 5.0, outputPer1M: 25.0, cachedInputPer1M: 1.5 },\r\n 'claude-3-opus': { inputPer1M: 15.0, outputPer1M: 75.0, cachedInputPer1M: 1.5 },\r\n\r\n // --- Anthropic (Legacy & Backward Compatibility) ---\r\n 'claude-3-sonnet': { inputPer1M: 3.0, outputPer1M: 15.0, cachedInputPer1M: 0.3 },\r\n 'claude-3-haiku': { inputPer1M: 0.25, outputPer1M: 1.25, cachedInputPer1M: 0.025 },\r\n 'claude-2.1': { inputPer1M: 8.0, outputPer1M: 24.0 },\r\n 'claude-2.0': { inputPer1M: 8.0, outputPer1M: 24.0 },\r\n 'claude-instant-1.2': { inputPer1M: 1.63, outputPer1M: 5.51 },\r\n\r\n // --- Google Gemini (Modern & Thoughts) ---\r\n 'gemini-3.8-flash': { inputPer1M: 0.75, outputPer1M: 3.75, cachedInputPer1M: 0.075 },\r\n 'gemini-nano-banana-2.1': { inputPer1M: 1.5, outputPer1M: 7.5, cachedInputPer1M: 0.15 },\r\n 'gemini-3.7-flash': { inputPer1M: 0.75, outputPer1M: 3.75, cachedInputPer1M: 0.18 },\r\n 'gemini-3.1-pro': { inputPer1M: 2.0, outputPer1M: 12.0, cachedInputPer1M: 0.5 },\r\n 'gemini-3.5-flash': { inputPer1M: 1.5, outputPer1M: 9.0, cachedInputPer1M: 0.38 },\r\n 'gemini-3.1-flash-lite': { inputPer1M: 0.25, outputPer1M: 1.5, cachedInputPer1M: 0.06 },\r\n 'gemini-2.5-pro': { inputPer1M: 1.25, outputPer1M: 5.0, cachedInputPer1M: 0.3125 },\r\n 'gemini-2.5-flash': { inputPer1M: 0.15, outputPer1M: 0.6, cachedInputPer1M: 0.0375 },\r\n 'gemini-2.0-flash': { inputPer1M: 0.1, outputPer1M: 0.4, cachedInputPer1M: 0.025 },\r\n 'gemini-2.0-flash-lite': { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },\r\n 'gemini-2.0-pro': { inputPer1M: 1.25, outputPer1M: 5.0, cachedInputPer1M: 0.3125 },\r\n\r\n // --- Google Gemini (Legacy & Backward Compatibility) ---\r\n 'gemini-1.5-pro': { inputPer1M: 1.25, outputPer1M: 5.0, cachedInputPer1M: 0.3125 },\r\n 'gemini-1.5-flash': { inputPer1M: 0.075, outputPer1M: 0.3, cachedInputPer1M: 0.01875 },\r\n 'gemini-1.5-flash-8b': { inputPer1M: 0.0375, outputPer1M: 0.15, cachedInputPer1M: 0.009375 },\r\n 'gemini-1.0-pro': { inputPer1M: 0.5, outputPer1M: 1.5 },\r\n\r\n // --- xAI Grok ---\r\n 'grok-4.6': { inputPer1M: 3.0, outputPer1M: 15.0 },\r\n 'grok-3': { inputPer1M: 3.0, outputPer1M: 15.0 },\r\n 'grok-3-mini': { inputPer1M: 0.3, outputPer1M: 1.5 },\r\n 'grok-2': { inputPer1M: 2.0, outputPer1M: 10.0 },\r\n 'grok-2-vision': { inputPer1M: 2.0, outputPer1M: 10.0 },\r\n 'grok-beta': { inputPer1M: 5.0, outputPer1M: 15.0 },\r\n\r\n // --- Mistral ---\r\n 'mistral-large-4': { inputPer1M: 0.68, outputPer1M: 2.09, cachedInputPer1M: 0.07 },\r\n 'mistral-large-3': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n 'mistral-large-latest': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n 'mistral-large-2411': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n 'codestral-latest': { inputPer1M: 0.3, outputPer1M: 0.9 },\r\n 'mistral-medium-latest': { inputPer1M: 2.7, outputPer1M: 8.1 },\r\n 'mistral-medium-3-5': { inputPer1M: 2.0, outputPer1M: 6.0, cachedInputPer1M: 0.4 },\r\n 'mistral-medium-2604': { inputPer1M: 2.0, outputPer1M: 6.0, cachedInputPer1M: 0.4 },\r\n 'magistral-small-latest': { inputPer1M: 0.5, outputPer1M: 1.5, cachedInputPer1M: 0.1 },\r\n 'magistral-medium-latest': { inputPer1M: 2.0, outputPer1M: 6.0, cachedInputPer1M: 0.4 },\r\n 'mistral-small-latest': { inputPer1M: 0.2, outputPer1M: 0.6 },\r\n 'mistral-small-2603': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'mistral-vibe-cli-fast': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'mistral-vibe-cli-latest': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'codestral-2508': { inputPer1M: 0.3, outputPer1M: 0.9, cachedInputPer1M: 0.08 },\r\n 'codestral-embed': { inputPer1M: 0.1, outputPer1M: 0.0 },\r\n 'mistral-embed-2312': { inputPer1M: 0.1, outputPer1M: 0.0 },\r\n 'zai-glm-5-2': { inputPer1M: 0.6, outputPer1M: 2.2, cachedInputPer1M: 0.15 },\r\n 'glm-5-2': { inputPer1M: 0.6, outputPer1M: 2.2, cachedInputPer1M: 0.15 },\r\n 'labs-leanstral-1-5': { inputPer1M: 0.2, outputPer1M: 0.6, cachedInputPer1M: 0.05 },\r\n 'ministral-8b-latest': { inputPer1M: 0.1, outputPer1M: 0.1 },\r\n 'ministral-3b-latest': { inputPer1M: 0.04, outputPer1M: 0.04 },\r\n 'open-mistral-7b': { inputPer1M: 0.2, outputPer1M: 0.2 },\r\n 'open-mixtral-8x7b': { inputPer1M: 0.7, outputPer1M: 0.7 },\r\n 'open-mixtral-8x22b': { inputPer1M: 2.0, outputPer1M: 6.0 },\r\n\r\n // --- Groq & Meta Llama LPUs ---\r\n 'llama-3.3-70b-versatile': { inputPer1M: 0.59, outputPer1M: 0.79 },\r\n 'llama-3.1-405b': { inputPer1M: 3.0, outputPer1M: 3.0 },\r\n 'llama-3.1-70b-versatile': { inputPer1M: 0.59, outputPer1M: 0.79 },\r\n 'llama-3.1-8b-instant': { inputPer1M: 0.05, outputPer1M: 0.08 },\r\n 'llama-3.2-1b-preview': { inputPer1M: 0.04, outputPer1M: 0.04 },\r\n 'llama-3.2-3b-preview': { inputPer1M: 0.06, outputPer1M: 0.06 },\r\n 'llama-3.2-11b-vision': { inputPer1M: 0.18, outputPer1M: 0.18 },\r\n 'llama-3.2-90b-vision': { inputPer1M: 0.90, outputPer1M: 0.90 },\r\n 'deepseek-r1-distill-llama-70b': { inputPer1M: 0.75, outputPer1M: 0.99 },\r\n 'deepseek-r1-distill-qwen-32b': { inputPer1M: 0.49, outputPer1M: 0.49 },\r\n 'qwen-2.5-32b': { inputPer1M: 0.29, outputPer1M: 0.39 },\r\n 'qwen-2.5-72b': { inputPer1M: 0.35, outputPer1M: 0.40 },\r\n 'mixtral-8x7b-32768': { inputPer1M: 0.24, outputPer1M: 0.24 },\r\n 'gemma2-9b-it': { inputPer1M: 0.20, outputPer1M: 0.20 },\r\n\r\n // --- DeepSeek ---\r\n 'deepseek-v4-pro': { inputPer1M: 0.66, outputPer1M: 1.98, cachedInputPer1M: 0.15 },\r\n 'deepseek-v4.1-flash': { inputPer1M: 0.20, outputPer1M: 0.60, cachedInputPer1M: 0.05 },\r\n 'deepseek-v4-flash': { inputPer1M: 0.22, outputPer1M: 0.66, cachedInputPer1M: 0.05 },\r\n 'deepseek-v3': { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },\r\n 'deepseek-chat': { inputPer1M: 0.14, outputPer1M: 0.28, cachedInputPer1M: 0.014 },\r\n 'deepseek-r1': { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },\r\n 'deepseek-reasoner': { inputPer1M: 0.55, outputPer1M: 2.19, cachedInputPer1M: 0.14 },\r\n\r\n // --- Gateway, Inception & InclusionAI Models ---\r\n 'mercury-2.5': { inputPer1M: 0.25, outputPer1M: 0.75, cachedInputPer1M: 0.05 },\r\n 'mercury-2': { inputPer1M: 0.25, outputPer1M: 0.75, cachedInputPer1M: 0.05 },\r\n 'ling-3.0-flash-sante': { inputPer1M: 0.15, outputPer1M: 0.45, cachedInputPer1M: 0.03 },\r\n 'ling-3.0-flash': { inputPer1M: 0.15, outputPer1M: 0.45, cachedInputPer1M: 0.03 },\r\n\r\n // --- Cohere ---\r\n 'command-r-plus': { inputPer1M: 2.5, outputPer1M: 10.0 },\r\n 'command-r': { inputPer1M: 0.15, outputPer1M: 0.6 },\r\n 'command': { inputPer1M: 1.0, outputPer1M: 2.0 },\r\n 'command-light': { inputPer1M: 0.3, outputPer1M: 0.6 },\r\n 'embed-english-v3.0': { inputPer1M: 0.10, outputPer1M: 0.0 },\r\n\r\n // --- Perplexity ---\r\n 'sonar': { inputPer1M: 1.0, outputPer1M: 1.0 },\r\n 'sonar-pro': { inputPer1M: 3.0, outputPer1M: 15.0 },\r\n 'sonar-reasoning': { inputPer1M: 1.0, outputPer1M: 5.0 },\r\n 'sonar-reasoning-pro': { inputPer1M: 2.0, outputPer1M: 8.0 },\r\n};\r\n\r\n/**\r\n * Common model alias map to normalize nicknames, shorthands, and legacy IDs\r\n */\r\nexport const MODEL_ALIASES: Record<string, string> = {\r\n // OpenAI Shorthands & Aliases\r\n 'gpt4': 'gpt-4',\r\n 'gpt4o': 'gpt-4o',\r\n 'gpt-4-preview': 'gpt-4-turbo',\r\n 'gpt-4-0125-preview': 'gpt-4-turbo',\r\n 'gpt-4-1106-preview': 'gpt-4-turbo',\r\n 'gpt-3.5': 'gpt-3.5-turbo',\r\n 'gpt-3.5-turbo-0125': 'gpt-3.5-turbo',\r\n 'gpt-3.5-turbo-1106': 'gpt-3.5-turbo',\r\n 'gpt-3.5-turbo-16k-0613': 'gpt-3.5-turbo-16k',\r\n\r\n // Anthropic Shorthands\r\n 'sonnet': 'claude-3-5-sonnet',\r\n 'sonnet-3.7': 'claude-3-7-sonnet',\r\n 'sonnet-3.5': 'claude-3-5-sonnet',\r\n 'haiku': 'claude-3-5-haiku',\r\n 'haiku-3.5': 'claude-3-5-haiku',\r\n 'haiku-5.5': 'claude-haiku-5.5',\r\n 'sonnet-5.5': 'claude-sonnet-5.5',\r\n 'opus-5.5': 'claude-opus-5.5',\r\n 'opus': 'claude-3-opus',\r\n 'claude-2': 'claude-2.0',\r\n 'claude-instant': 'claude-instant-1.2',\r\n\r\n // DeepSeek Shorthands\r\n 'r1': 'deepseek-r1',\r\n 'v3': 'deepseek-v3',\r\n\r\n // Gemini Shorthands\r\n 'flash': 'gemini-2.0-flash',\r\n 'pro': 'gemini-1.5-pro',\r\n 'gemini-banana': 'gemini-nano-banana-2.1',\r\n\r\n // Meta / Groq Shorthands\r\n 'llama-3.3-70b': 'llama-3.3-70b-versatile',\r\n 'llama-3.1-70b': 'llama-3.1-70b-versatile',\r\n 'llama-3.1-8b': 'llama-3.1-8b-instant',\r\n 'llama-3-70b': 'llama-3.1-70b-versatile',\r\n 'llama-3-8b': 'llama-3.1-8b-instant',\r\n\r\n // Mistral Shorthands\r\n 'codestral': 'codestral-latest',\r\n 'mistral-large': 'mistral-large-latest',\r\n 'mistral-small': 'mistral-small-latest',\r\n 'magistral': 'magistral-small-latest',\r\n 'magistral-small': 'magistral-small-latest',\r\n 'magistral-medium': 'magistral-medium-latest',\r\n 'mistral-3.5': 'mistral-medium-3-5',\r\n 'mistral-medium-3.5': 'mistral-medium-3-5',\r\n 'gpt-image-2.5': 'gpt-image-2.5-flare',\r\n 'gpt-image-sunburst': 'gpt-image-2.5-sunburst',\r\n 'gpt-image-flare': 'gpt-image-2.5-flare',\r\n};\r\n\r\n/**\r\n * Dynamic in-memory registry allowing runtime custom price registration\r\n */\r\nconst customPricingRegistry: Record<string, ModelPricingRates> = {};\r\n\r\n/**\r\n * Normalize model identifier to match pricing table keys:\r\n * - Strips AWS Bedrock prefixes (e.g. 'anthropic.claude-3-5-sonnet-20241022-v2:0' -> 'claude-3-5-sonnet')\r\n * - Strips provider prefixes (e.g. 'openai/gpt-4o' -> 'gpt-4o', 'deepseek/deepseek-r1' -> 'deepseek-r1')\r\n * - Strips date suffixes (e.g. '-20240307', '-20250219')\r\n * - Resolves shorthands and aliases\r\n */\r\nexport function normalizeModelKey(rawModel: string): string {\r\n if (!rawModel) return 'unknown';\r\n\r\n let model = rawModel.toLowerCase().trim();\r\n\r\n // Strip AWS Bedrock model prefix (e.g. 'us.anthropic.claude-3-5-sonnet...', 'meta.llama3-...')\r\n model = model.replace(/^[a-z0-9_-]+\\.(anthropic|meta|amazon|cohere|mistral|ai21)\\./i, '');\r\n model = model.replace(/^(anthropic|meta|amazon|cohere|mistral|ai21)\\./i, '');\r\n\r\n // Strip AWS Bedrock version suffix (e.g. '-v1:0', '-v2:0', ':0')\r\n model = model.replace(/-v\\d+(:\\d+)?$/, '');\r\n model = model.replace(/:\\d+$/, '');\r\n\r\n // Strip provider prefix if present (e.g. 'openai/gpt-4o' -> 'gpt-4o', 'meta-llama/llama-3.3-70b-instruct' -> 'llama-3.3-70b-instruct')\r\n if (model.includes('/')) {\r\n model = model.split('/').slice(1).join('/');\r\n }\r\n\r\n // Remove trailing version/mode tags (e.g. ':latest', ':free', ':beta')\r\n model = model.replace(/:(latest|free|beta)$/, '');\r\n\r\n // Remove date suffixes like -20240307 or -20250219 or -2024-08-06\r\n model = model.replace(/-\\d{8}$/, '');\r\n model = model.replace(/-\\d{4}-\\d{2}-\\d{2}$/, '');\r\n\r\n // Normalize Bedrock Meta format (e.g. llama3-1-70b -> llama-3.1-70b)\r\n model = model.replace(/llama(\\d+)-(\\d+)-/g, 'llama-$1.$2-');\r\n model = model.replace(/llama(\\d+)\\.(\\d+)-/g, 'llama-$1.$2-');\r\n\r\n // Check aliases before fine-tuning\r\n if (MODEL_ALIASES[model]) {\r\n return MODEL_ALIASES[model];\r\n }\r\n\r\n // Remove common modifier suffixes if not directly matching table\r\n if (!MODEL_PRICING_TABLE[model]) {\r\n const withoutInstruct = model.replace(/-(instruct|chat|preview)$/, '');\r\n if (MODEL_PRICING_TABLE[withoutInstruct]) {\r\n return withoutInstruct;\r\n }\r\n if (MODEL_ALIASES[withoutInstruct]) {\r\n return MODEL_ALIASES[withoutInstruct];\r\n }\r\n }\r\n\r\n return model;\r\n}\r\n\r\n/**\r\n * Retrieve pricing rates for a given model\r\n */\r\nexport function getModelPricing(modelName: string): ModelPricingRates {\r\n const normalized = normalizeModelKey(modelName);\r\n\r\n // Check custom registry first\r\n if (customPricingRegistry[normalized]) {\r\n return customPricingRegistry[normalized];\r\n }\r\n if (customPricingRegistry[modelName]) {\r\n return customPricingRegistry[modelName];\r\n }\r\n\r\n // Check dynamic synced manifest cache\r\n const dynamicRate = getDynamicRate(modelName) || getDynamicRate(normalized);\r\n if (dynamicRate) {\r\n return dynamicRate;\r\n }\r\n\r\n // Check built-in table with normalized key\r\n if (MODEL_PRICING_TABLE[normalized]) {\r\n return MODEL_PRICING_TABLE[normalized];\r\n }\r\n // Check built-in table with direct key\r\n if (MODEL_PRICING_TABLE[modelName]) {\r\n return MODEL_PRICING_TABLE[modelName];\r\n }\r\n\r\n // Check alias table fallback\r\n const alias = MODEL_ALIASES[modelName.toLowerCase().trim()];\r\n if (alias) {\r\n const dynamicAlias = getDynamicRate(alias);\r\n if (dynamicAlias) return dynamicAlias;\r\n if (MODEL_PRICING_TABLE[alias]) {\r\n return MODEL_PRICING_TABLE[alias];\r\n }\r\n }\r\n\r\n // Fallback defaults for unknown models (conservative estimates: $1.00 in, $3.00 out)\r\n return {\r\n inputPer1M: 1.0,\r\n outputPer1M: 3.0,\r\n cachedInputPer1M: 0.5,\r\n };\r\n}\r\n\r\n/**\r\n * Register or override pricing rates for a custom model\r\n */\r\nexport function registerModelPricing(modelName: string, rates: ModelPricingRates): void {\r\n const normalized = normalizeModelKey(modelName);\r\n customPricingRegistry[normalized] = rates;\r\n customPricingRegistry[modelName] = rates;\r\n}\r\n","import type { InferenceCost, TokenUsage, InlineRateConfig, ModelPricingRates } from '../types';\nimport { getModelPricing } from './table';\n\nexport interface CalculateCostParams {\n model: string;\n inputTokens?: number;\n outputTokens?: number;\n promptTokens?: number;\n completionTokens?: number;\n reasoningTokens?: number;\n cachedTokens?: number;\n cacheWriteTokens?: number;\n markupMultiplier?: number;\n markup?: number;\n margin?: number;\n minimumChargeUSD?: number;\n customRate?: InlineRateConfig;\n}\n\nexport interface TokenUsageInput {\n inputTokens?: number;\n outputTokens?: number;\n promptTokens?: number;\n completionTokens?: number;\n reasoningTokens?: number;\n cachedTokens?: number;\n cacheWriteTokens?: number;\n}\n\nexport interface CalculateCostOptions {\n markupMultiplier?: number;\n markup?: number;\n margin?: number;\n minimumChargeUSD?: number;\n customRate?: InlineRateConfig;\n}\n\n/**\n * BigInt Nano-Precision Financial Math Engine\n * 1 USD = 1,000,000,000 Nano-USD (10^9)\n * 1 token at $1.00 / 1M = $0.000001 = 1,000 Nano-USD\n * Prevents IEEE 754 floating point precision drift on micro-transactions.\n *\n * Supports both:\n * 1. calculateCost('gpt-4o-mini', { promptTokens: 1240, completionTokens: 150 })\n * 2. calculateCost({ model: 'gpt-4o-mini', inputTokens: 1240, outputTokens: 150 })\n */\nexport function calculateCost(\n modelOrParams: string | CalculateCostParams,\n usage?: TokenUsageInput,\n optionsOrMarkup?: number | CalculateCostOptions\n): InferenceCost {\n let params: CalculateCostParams;\n\n if (typeof modelOrParams === 'string') {\n const opts =\n typeof optionsOrMarkup === 'number'\n ? { markupMultiplier: optionsOrMarkup }\n : optionsOrMarkup || {};\n params = {\n model: modelOrParams,\n inputTokens: usage?.inputTokens ?? usage?.promptTokens ?? 0,\n outputTokens: usage?.outputTokens ?? usage?.completionTokens ?? 0,\n reasoningTokens: usage?.reasoningTokens,\n cachedTokens: usage?.cachedTokens,\n cacheWriteTokens: usage?.cacheWriteTokens,\n markupMultiplier: opts.markupMultiplier ?? opts.markup ?? opts.margin,\n minimumChargeUSD: opts.minimumChargeUSD,\n customRate: opts.customRate,\n };\n } else {\n params = {\n ...modelOrParams,\n inputTokens: modelOrParams.inputTokens ?? modelOrParams.promptTokens ?? 0,\n outputTokens: modelOrParams.outputTokens ?? modelOrParams.completionTokens ?? 0,\n markupMultiplier:\n modelOrParams.markupMultiplier ?? modelOrParams.markup ?? modelOrParams.margin,\n };\n }\n let rates: ModelPricingRates;\n\n if (params.customRate) {\n const outRate = params.customRate.out ?? params.customRate.output ?? 0;\n rates = {\n inputPer1M: params.customRate.in,\n outputPer1M: outRate,\n reasoningPer1M: params.customRate.reasoning ?? outRate,\n cachedInputPer1M: params.customRate.cached ?? params.customRate.in * 0.15,\n currency: 'USD',\n };\n } else {\n rates = getModelPricing(params.model);\n }\n\n const inputTokens = BigInt(Math.max(0, params.inputTokens ?? 0));\n const outputTokens = BigInt(Math.max(0, params.outputTokens ?? 0));\n const reasoningTokens = BigInt(Math.max(0, params.reasoningTokens ?? 0));\n const cachedTokens = BigInt(Math.max(0, params.cachedTokens ?? 0));\n\n // Regular input tokens (minus any cached tokens)\n const regularInputTokens = inputTokens > cachedTokens ? inputTokens - cachedTokens : 0n;\n\n // Convert rate per 1M tokens to integer nano-dollars per single token (rate * 1,000)\n // Using 10^9 nano-precision\n const rateInputNano = BigInt(Math.round(rates.inputPer1M * 1_000));\n const cachedPer1M = rates.cachedInputPer1M ?? rates.inputPer1M * 0.15;\n const rateCachedNano = BigInt(Math.round(cachedPer1M * 1_000));\n const rateOutputNano = BigInt(Math.round(rates.outputPer1M * 1_000));\n const reasoningPer1M = rates.reasoningPer1M ?? rates.outputPer1M;\n const rateReasoningNano = BigInt(Math.round(reasoningPer1M * 1_000));\n\n // Compute component nano costs\n const regularInputCostNano = regularInputTokens * rateInputNano;\n const cachedInputCostNano = cachedTokens * rateCachedNano;\n const inputCostNano = regularInputCostNano + cachedInputCostNano;\n const outputCostNano = outputTokens * rateOutputNano;\n const reasoningCostNano = reasoningTokens * rateReasoningNano;\n\n // Prompt cache savings discount\n const standardCacheCostNano = cachedTokens * rateInputNano;\n const cachedDiscountNano =\n standardCacheCostNano > cachedInputCostNano ? standardCacheCostNano - cachedInputCostNano : 0n;\n\n // Total wholesale cost\n const wholesaleNano = inputCostNano + outputCostNano;\n\n // Retail calculation\n const markup = params.markupMultiplier ?? 1.0;\n let billedNano = wholesaleNano;\n let hasRetail = false;\n\n if (markup !== 1.0 || params.minimumChargeUSD !== undefined) {\n hasRetail = true;\n const markupMultiplierNano = BigInt(Math.round(markup * 1_000));\n billedNano = (wholesaleNano * markupMultiplierNano) / 1_000n;\n\n if (params.minimumChargeUSD !== undefined && params.minimumChargeUSD > 0) {\n const minChargeNano = BigInt(Math.round(params.minimumChargeUSD * 1_000_000_000));\n if (billedNano < minChargeNano) {\n billedNano = minChargeNano;\n }\n }\n }\n\n const inputCostUSD = Number(inputCostNano) / 1_000_000_000;\n const outputCostUSD = Number(outputCostNano) / 1_000_000_000;\n const reasoningCostUSD = Number(reasoningCostNano) / 1_000_000_000;\n const cachedDiscountUSD = Number(cachedDiscountNano) / 1_000_000_000;\n const totalUSD = Number(wholesaleNano) / 1_000_000_000;\n const wholesaleTotalUSD = totalUSD;\n const billedUSD = Number(billedNano) / 1_000_000_000;\n const profitUSD = Math.max(0, billedUSD - wholesaleTotalUSD);\n const retailUSD = hasRetail ? billedUSD : undefined;\n\n return {\n inputCostUSD: Number(inputCostUSD.toFixed(8)),\n outputCostUSD: Number(outputCostUSD.toFixed(8)),\n reasoningCostUSD: reasoningTokens > 0n ? Number(reasoningCostUSD.toFixed(8)) : undefined,\n cachedDiscountUSD: cachedTokens > 0n ? Number(cachedDiscountUSD.toFixed(8)) : undefined,\n savingsUSD: cachedTokens > 0n ? Number(cachedDiscountUSD.toFixed(8)) : undefined,\n totalUSD: Number(totalUSD.toFixed(8)),\n wholesaleTotalUSD: Number(wholesaleTotalUSD.toFixed(8)),\n wholesaleUSD: Number(wholesaleTotalUSD.toFixed(8)),\n billedUSD: Number(billedUSD.toFixed(8)),\n profitUSD: Number(profitUSD.toFixed(8)),\n retailUSD: retailUSD !== undefined ? Number(retailUSD.toFixed(8)) : undefined,\n currency: rates.currency || 'USD',\n };\n}\n\n/**\n * Calculates cost directly from a TokenUsage object\n */\nexport function calculateUsageCost(\n model: string,\n usage: TokenUsage,\n optionsOrMarkup?: number | { markupMultiplier?: number; minimumChargeUSD?: number; customRate?: InlineRateConfig }\n): InferenceCost {\n const options =\n typeof optionsOrMarkup === 'number'\n ? { markupMultiplier: optionsOrMarkup }\n : optionsOrMarkup || {};\n\n return calculateCost({\n model,\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n reasoningTokens: usage.reasoningTokens,\n cachedTokens: usage.cachedTokens,\n cacheWriteTokens: usage.cacheWriteTokens,\n markupMultiplier: options.markupMultiplier,\n minimumChargeUSD: options.minimumChargeUSD,\n customRate: options.customRate,\n });\n}\n","import type { CustomerParam, CustomerInfo } from '../types';\r\n\r\nexport interface NormalizedCustomer {\r\n customerId?: string;\r\n customerEmail?: string;\r\n customerObj?: CustomerInfo;\r\n customerMetadata: Record<string, string | number | boolean>;\r\n}\r\n\r\n/**\r\n * Normalizes string or object customer into structured identifiers and metadata\r\n */\r\nexport function normalizeCustomer(customer?: CustomerParam, extraCustomerId?: string): NormalizedCustomer {\r\n if (!customer && !extraCustomerId) {\r\n return {\r\n customerId: undefined,\r\n customerEmail: undefined,\r\n customerObj: undefined,\r\n customerMetadata: {},\r\n };\r\n }\r\n\r\n if (typeof customer === 'string') {\r\n const isEmail = customer.includes('@');\r\n const customerObj: CustomerInfo = {\r\n id: customer,\r\n email: isEmail ? customer : undefined,\r\n };\r\n return {\r\n customerId: customer,\r\n customerEmail: isEmail ? customer : undefined,\r\n customerObj,\r\n customerMetadata: {},\r\n };\r\n }\r\n\r\n const customerObj = customer || (extraCustomerId ? { id: extraCustomerId } : undefined);\r\n const customerId = customerObj?.id || customerObj?.userId || extraCustomerId;\r\n const customerEmail = customerObj?.email;\r\n\r\n const customerMetadata: Record<string, string | number | boolean> = {};\r\n\r\n if (customerObj) {\r\n const orgId = customerObj.orgId || customerObj.organizationId;\r\n if (orgId) customerMetadata.org_id = String(orgId);\r\n\r\n const teamId = customerObj.teamId || customerObj.workspaceId;\r\n if (teamId) customerMetadata.team_id = String(teamId);\r\n\r\n if (customerObj.plan) customerMetadata.plan = String(customerObj.plan);\r\n if (customerObj.tier) customerMetadata.tier = String(customerObj.tier);\r\n if (customerObj.role) customerMetadata.role = String(customerObj.role);\r\n if (customerObj.orgName) customerMetadata.org_name = String(customerObj.orgName);\r\n\r\n if (customerObj.metadata) {\r\n for (const [key, val] of Object.entries(customerObj.metadata)) {\r\n if (val !== null && val !== undefined) {\r\n customerMetadata[key] = val as string | number | boolean;\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n customerId,\r\n customerEmail,\r\n customerObj,\r\n customerMetadata,\r\n };\r\n}\r\n","import type { UsageEvent, StreamWrapOptions } from '../types';\r\nimport { inspectOpenAIStreamChunk } from './extractors/openai';\r\nimport { AnthropicStreamAccumulator } from './extractors/anthropic';\r\nimport { extractGeminiResponseUsage } from './extractors/gemini';\r\nimport { calculateUsageCost } from '../pricing/calculator';\r\nimport { normalizeCustomer } from '../customers/helpers';\r\n\r\nexport type UsageDispatchedCallback = (event: UsageEvent) => void;\r\n\r\n/**\r\n * Wraps an OpenAI async iterable stream to capture usage at stream conclusion\r\n */\r\nexport function wrapOpenAIStream<T extends AsyncIterable<any>>(\r\n stream: T,\r\n options: StreamWrapOptions,\r\n onComplete: UsageDispatchedCallback\r\n): T {\r\n let detectedModel = options.model || 'gpt-4o';\r\n let finalUsage: any = null;\r\n\r\n const wrappedAsyncIterable = {\r\n async *[Symbol.asyncIterator]() {\r\n try {\r\n for await (const chunk of stream) {\r\n const inspected = inspectOpenAIStreamChunk(chunk);\r\n if (inspected.model) {\r\n detectedModel = inspected.model;\r\n }\r\n if (inspected.usage) {\r\n finalUsage = inspected.usage;\r\n }\r\n yield chunk;\r\n }\r\n } finally {\r\n if (finalUsage) {\r\n const cost = calculateUsageCost(detectedModel, finalUsage);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model: detectedModel,\r\n provider: 'openai',\r\n usage: finalUsage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n },\r\n };\r\n\r\n onComplete(event);\r\n if (options.onUsage) {\r\n options.onUsage(event);\r\n }\r\n }\r\n }\r\n },\r\n };\r\n\r\n return wrappedAsyncIterable as unknown as T;\r\n}\r\n\r\n/**\r\n * Wraps an Anthropic message stream to accumulate message_start and message_delta usage\r\n */\r\nexport function wrapAnthropicStream<T extends AsyncIterable<any>>(\r\n stream: T,\r\n options: StreamWrapOptions,\r\n onComplete: UsageDispatchedCallback\r\n): T {\r\n const accumulator = new AnthropicStreamAccumulator();\r\n\r\n const wrappedAsyncIterable = {\r\n async *[Symbol.asyncIterator]() {\r\n try {\r\n for await (const event of stream) {\r\n accumulator.processEvent(event);\r\n yield event;\r\n }\r\n } finally {\r\n const extracted = accumulator.getUsage();\r\n const model = options.model || extracted.model;\r\n const cost = calculateUsageCost(model, extracted.usage);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const usageEvent: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model,\r\n provider: 'anthropic',\r\n usage: extracted.usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n },\r\n };\r\n\r\n onComplete(usageEvent);\r\n if (options.onUsage) {\r\n options.onUsage(usageEvent);\r\n }\r\n }\r\n },\r\n };\r\n\r\n return wrappedAsyncIterable as unknown as T;\r\n}\r\n\r\n/**\r\n * Wraps a Google Gemini GenerateContentStreamResult\r\n */\r\nexport function wrapGeminiStream(\r\n result: any,\r\n options: StreamWrapOptions,\r\n onComplete: UsageDispatchedCallback\r\n): any {\r\n if (!result || !result.stream) return result;\r\n\r\n const originalStream = result.stream;\r\n const model = options.model || 'gemini-3.7-flash';\r\n let lastChunkWithUsage: any = null;\r\n\r\n const wrappedStream = (async function* () {\r\n try {\r\n for await (const chunk of originalStream) {\r\n if (chunk.usageMetadata) {\r\n lastChunkWithUsage = chunk;\r\n }\r\n yield chunk;\r\n }\r\n } finally {\r\n if (lastChunkWithUsage) {\r\n const extracted = extractGeminiResponseUsage(lastChunkWithUsage, model);\r\n if (extracted) {\r\n const cost = calculateUsageCost(extracted.model, extracted.usage);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model: extracted.model,\r\n provider: 'google',\r\n usage: extracted.usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n },\r\n };\r\n\r\n onComplete(event);\r\n if (options.onUsage) {\r\n options.onUsage(event);\r\n }\r\n }\r\n }\r\n }\r\n })();\r\n\r\n return {\r\n ...result,\r\n stream: wrappedStream,\r\n };\r\n}\r\n\r\n/**\r\n * Universal Stream Wrapper\r\n */\r\nexport function wrapUniversalStream<T>(\r\n stream: T,\r\n options: StreamWrapOptions = {},\r\n onComplete: UsageDispatchedCallback\r\n): T {\r\n if (!stream || typeof stream !== 'object') return stream;\r\n\r\n // 1. Check Gemini stream\r\n if ('stream' in stream && 'response' in stream) {\r\n return wrapGeminiStream(stream, options, onComplete);\r\n }\r\n\r\n // 2. Check if stream is an AsyncIterable\r\n if (Symbol.asyncIterator in stream) {\r\n // If provider is explicitly anthropic or model is claude\r\n if (options.provider === 'anthropic' || options.model?.toLowerCase().includes('claude')) {\r\n return wrapAnthropicStream(stream as any, options, onComplete);\r\n }\r\n // Default to universal stream wrapper which detects usage chunks polymorphically\r\n return wrapOpenAIStream(stream as any, options, onComplete);\r\n }\r\n\r\n return stream;\r\n}\r\n","import type {\r\n MeterOptions,\r\n StreamWrapOptions,\r\n RecordUsageOptions,\r\n UsageEvent,\r\n UsageSummary,\r\n CustomerParam,\r\n} from '../types';\r\nimport { MeterBatcher } from './batcher';\r\nimport { detectAndExtractUsage } from './extractors';\r\nimport { calculateUsageCost } from '../pricing/calculator';\r\nimport { wrapUniversalStream } from './stream';\r\nimport { normalizeCustomer } from '../customers/helpers';\r\n\r\nexport class VibezMeter {\r\n private batcher: MeterBatcher;\r\n private markupMultiplier?: number;\r\n\r\n constructor(options: MeterOptions = {}) {\r\n this.markupMultiplier = options.pricing?.margin ?? options.pricing?.markup ?? options.markupMultiplier;\r\n this.batcher = new MeterBatcher(options);\r\n }\r\n\r\n /**\r\n * Track token usage from a non-streaming response object (OpenAI, Anthropic, Gemini, etc.)\r\n */\r\n public trackUsage(\r\n response: any,\r\n options: {\r\n customer?: CustomerParam;\r\n customerId?: string;\r\n model?: string;\r\n provider?: string;\r\n metadata?: Record<string, string | number | boolean>;\r\n } = {}\r\n ): UsageEvent | null {\r\n const extracted = detectAndExtractUsage(response, options.model, options.provider);\r\n if (!extracted) {\r\n return null;\r\n }\r\n\r\n const model = options.model || extracted.model;\r\n const cost = calculateUsageCost(model, extracted.usage, this.markupMultiplier);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const mergedMeta = {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n };\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model,\r\n provider: extracted.provider,\r\n usage: extracted.usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: mergedMeta,\r\n };\r\n\r\n this.batcher.enqueue(event);\r\n return event;\r\n }\r\n\r\n /**\r\n * Wrap any LLM stream (OpenAI, Anthropic, Gemini) with zero added latency\r\n */\r\n public wrapStream<T>(stream: T, options: StreamWrapOptions = {}): T {\r\n return wrapUniversalStream(stream, options, (event) => {\r\n this.batcher.enqueue(event);\r\n });\r\n }\r\n\r\n /**\r\n * Directly record token usage manually\r\n */\r\n public recordUsage(options: RecordUsageOptions & { customer?: CustomerParam }): UsageEvent {\r\n const inputTokens = options.inputTokens ?? 0;\r\n const outputTokens = options.outputTokens ?? 0;\r\n const reasoningTokens = options.reasoningTokens;\r\n const cachedTokens = options.cachedTokens;\r\n\r\n const usage = {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens,\r\n visibleOutputTokens:\r\n reasoningTokens !== undefined ? Math.max(0, outputTokens - reasoningTokens) : outputTokens,\r\n cachedTokens,\r\n };\r\n\r\n const cost = calculateUsageCost(options.model, usage, this.markupMultiplier);\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n\r\n const mergedMeta = {\r\n ...normalized.customerMetadata,\r\n ...options.metadata,\r\n };\r\n\r\n const event: UsageEvent = {\r\n timestamp: new Date().toISOString(),\r\n model: options.model,\r\n provider: options.provider || 'custom',\r\n usage,\r\n cost,\r\n customerId: normalized.customerId,\r\n customerEmail: normalized.customerEmail,\r\n customer: normalized.customerObj,\r\n metadata: mergedMeta,\r\n };\r\n\r\n this.batcher.enqueue(event);\r\n return event;\r\n }\r\n\r\n /**\r\n * Flush pending events (vital for Serverless & Edge environments)\r\n */\r\n public async flush(): Promise<void> {\r\n await this.batcher.flush();\r\n }\r\n\r\n /**\r\n * Get in-memory aggregated usage statistics\r\n */\r\n public getUsageSummary(): UsageSummary {\r\n return this.batcher.getSummary();\r\n }\r\n\r\n /**\r\n * Reset in-memory ledger\r\n */\r\n public resetSummary(): void {\r\n this.batcher.resetLedger();\r\n }\r\n}\r\n\r\n/**\r\n * Factory function to create a VibezMeter instance\r\n */\r\nexport function createMeter(options: MeterOptions = {}): VibezMeter {\r\n return new VibezMeter(options);\r\n}\r\n","import type {\r\n CustomerParam,\r\n UsageEvent,\r\n CircuitBreakerOptions,\r\n BudgetExceededEvent,\r\n PricingConfig,\r\n InlineRateConfig,\r\n} from '../types';\r\nimport { VibezCircuitBreakerError } from '../types';\r\nimport { createMeter, VibezMeter } from '../meter/client';\r\nimport { calculateUsageCost } from '../pricing/calculator';\r\nimport { normalizeCustomer } from '../customers/helpers';\r\n\r\nexport interface WithBillingOptions extends CircuitBreakerOptions {\r\n /** Customer email, user ID, or rich customer object with metadata */\r\n customer?: CustomerParam;\r\n /** Direct customer ID */\r\n customerId?: string;\r\n /** Thread or conversation identifier for session attribution */\r\n threadId?: string;\r\n /** Profit margin & minimum charge configuration */\r\n pricing?: PricingConfig;\r\n /** 1-line inline pricing rate card */\r\n rate?: InlineRateConfig;\r\n /** Pluggable Database Sink (Supabase, Postgres, Firebase, or 1-line callback) */\r\n database?: any | ((event: UsageEvent) => void | Promise<void>);\r\n /** Whether to capture tokens if the client aborts or closes tab mid-stream (default: true) */\r\n captureOnAbort?: boolean;\r\n /** Execution runtime environment (default: 'auto') */\r\n runtime?: 'auto' | 'serverless' | 'edge' | 'node';\r\n /** API Key override */\r\n apiKey?: string;\r\n /** Existing VibezMeter instance (optional) */\r\n meter?: VibezMeter;\r\n /** Custom meter event name */\r\n eventName?: string;\r\n /** Usage callback fired upon generation/stream completion */\r\n onUsage?: (event: UsageEvent) => void | Promise<void>;\r\n /** Custom developer metadata */\r\n metadata?: Record<string, string | number | boolean>;\r\n /** Suppress console warnings (default: true in test environment) */\r\n silent?: boolean;\r\n}\r\n\r\n/**\r\n * Wraps any Vercel AI SDK LanguageModel (v2 or v3) with automated token metering, cost intelligence, and agent circuit breakers.\r\n *\r\n * Sane Defaults Built-In:\r\n * - $0.50 safety ceiling per call (overridable)\r\n * - Automatic in-flight token capture on abort\r\n * - Automatic prompt caching discount parsing\r\n * - Serverless lifecycle preservation\r\n */\r\nexport function withBilling<T extends object>(\r\n model: T,\r\n optionsOrCustomer?: CustomerParam | WithBillingOptions,\r\n extraOptions: WithBillingOptions = {}\r\n): T {\r\n if (!model || typeof model !== 'object') {\r\n return model;\r\n }\r\n\r\n let options: WithBillingOptions = {};\r\n if (typeof optionsOrCustomer === 'string') {\r\n options = { ...extraOptions, customer: optionsOrCustomer };\r\n } else if (typeof optionsOrCustomer === 'object' && optionsOrCustomer !== null) {\r\n if ('userId' in optionsOrCustomer || 'email' in optionsOrCustomer || 'id' in optionsOrCustomer) {\r\n options = { ...extraOptions, customer: optionsOrCustomer as CustomerParam };\r\n } else {\r\n options = { ...(optionsOrCustomer as WithBillingOptions), ...extraOptions };\r\n }\r\n }\r\n\r\n const meter =\r\n options.meter ||\r\n createMeter({\r\n apiKey: options.apiKey,\r\n });\r\n\r\n const normalized = normalizeCustomer(options.customer, options.customerId);\r\n const customerId = normalized.customerId;\r\n const customerEmail = normalized.customerEmail;\r\n const customerObj = normalized.customerObj;\r\n const customerMetadata = normalized.customerMetadata;\r\n\r\n const modelId = (model as any).modelId || 'unknown-model';\r\n const provider = (model as any).provider?.replace(/^@ai-sdk\\//, '') || 'ai-sdk';\r\n\r\n // Sane Default: $0.50 circuit breaker ceiling unless explicitly disabled or configured\r\n const maxCostPerCall = options.maxCostPerCallUSD !== undefined ? options.maxCostPerCallUSD : 0.50;\r\n const captureOnAbort = options.captureOnAbort !== false; // Default: true\r\n\r\n // Helper to safely schedule serverless flushes\r\n const scheduleFlush = () => {\r\n try {\r\n const flushPromise = meter.flush();\r\n // Next.js 15+ after() or Cloudflare Workers / Vercel Edge waitUntil()\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (typeof g.after === 'function') {\r\n g.after(() => flushPromise);\r\n return;\r\n }\r\n if (typeof g.waitUntil === 'function') {\r\n g.waitUntil(flushPromise);\r\n return;\r\n }\r\n }\r\n flushPromise.catch(() => {});\r\n } catch {\r\n // Fallback in environments without after() or waitUntil()\r\n }\r\n };\r\n\r\n // Helper to record usage and enforce circuit breakers\r\n const handleUsage = (rawUsage: any, extraMeta?: Record<string, any>) => {\r\n if (!rawUsage) return;\r\n\r\n let inputTokens = 0;\r\n let outputTokens = 0;\r\n let reasoningTokens = 0;\r\n let cachedTokens = 0;\r\n let cacheWriteTokens = 0;\r\n\r\n // AI SDK v4+ (LanguageModelV4Usage) structured object or legacy flat number\r\n if (typeof rawUsage.inputTokens === 'object' && rawUsage.inputTokens !== null) {\r\n inputTokens = rawUsage.inputTokens.total ?? rawUsage.inputTokens.noCache ?? 0;\r\n cachedTokens = rawUsage.inputTokens.cacheRead ?? 0;\r\n cacheWriteTokens = rawUsage.inputTokens.cacheWrite ?? 0;\r\n } else if (typeof rawUsage.promptTokens === 'number') {\r\n inputTokens = rawUsage.promptTokens;\r\n } else if (typeof rawUsage.inputTokens === 'number') {\r\n inputTokens = rawUsage.inputTokens;\r\n } else {\r\n inputTokens =\r\n rawUsage.prompt_tokens ??\r\n rawUsage.input_tokens ??\r\n rawUsage.promptTokenCount ??\r\n 0;\r\n }\r\n\r\n if (typeof rawUsage.outputTokens === 'object' && rawUsage.outputTokens !== null) {\r\n outputTokens = rawUsage.outputTokens.total ?? rawUsage.outputTokens.text ?? 0;\r\n reasoningTokens = rawUsage.outputTokens.reasoning ?? 0;\r\n } else if (typeof rawUsage.completionTokens === 'number') {\r\n outputTokens = rawUsage.completionTokens;\r\n } else if (typeof rawUsage.outputTokens === 'number') {\r\n outputTokens = rawUsage.outputTokens;\r\n } else {\r\n outputTokens =\r\n rawUsage.completion_tokens ??\r\n rawUsage.output_tokens ??\r\n rawUsage.candidatesTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!reasoningTokens) {\r\n reasoningTokens =\r\n rawUsage.reasoningTokens ??\r\n rawUsage.completionTokensDetails?.reasoningTokens ??\r\n rawUsage.outputTokenDetails?.reasoningTokens ??\r\n rawUsage.reasoning_tokens ??\r\n rawUsage.completion_tokens_details?.reasoning_tokens ??\r\n rawUsage.output_token_details?.reasoning_tokens ??\r\n rawUsage.thoughtsTokenCount ??\r\n 0;\r\n }\r\n\r\n if (!cachedTokens) {\r\n cachedTokens =\r\n rawUsage.promptTokensDetails?.cachedTokens ??\r\n rawUsage.inputTokenDetails?.cachedTokens ??\r\n rawUsage.cachedTokens ??\r\n rawUsage.cached_tokens ??\r\n rawUsage.prompt_tokens_details?.cached_tokens ??\r\n rawUsage.input_token_details?.cached_tokens ??\r\n rawUsage.cachedContentTokenCount ??\r\n rawUsage.cache_read_input_tokens ??\r\n 0;\r\n }\r\n\r\n if (!cacheWriteTokens) {\r\n cacheWriteTokens =\r\n rawUsage.cacheWriteTokens ??\r\n rawUsage.cache_creation_input_tokens ??\r\n rawUsage.cacheCreationTokens ??\r\n 0;\r\n }\r\n\r\n const usage = {\r\n inputTokens,\r\n outputTokens,\r\n totalTokens: inputTokens + outputTokens,\r\n reasoningTokens: reasoningTokens > 0 ? reasoningTokens : undefined,\r\n visibleOutputTokens: Math.max(0, outputTokens - reasoningTokens),\r\n cachedTokens: cachedTokens > 0 ? cachedTokens : undefined,\r\n cacheWriteTokens: cacheWriteTokens > 0 ? cacheWriteTokens : undefined,\r\n };\r\n\r\n // Calculate cost with profit margin & minimum charge & custom rates\r\n const cost = calculateUsageCost(modelId, usage, {\r\n markupMultiplier: options.pricing?.margin ?? options.pricing?.markup,\r\n minimumChargeUSD: options.pricing?.minimumChargeUSD,\r\n customRate: options.rate,\r\n });\r\n\r\n // 🛡️ Agent Circuit Breakers Check ($0.50 default safety fuse)\r\n if (maxCostPerCall > 0 && maxCostPerCall !== Infinity && cost.totalUSD > maxCostPerCall) {\r\n const budgetEvent: BudgetExceededEvent = {\r\n reason: 'cost_per_call_exceeded',\r\n limit: maxCostPerCall,\r\n current: cost.totalUSD,\r\n model: modelId,\r\n customerId,\r\n message: `[vibezcheck] Circuit Breaker tripped: Call cost ($${cost.totalUSD.toFixed(4)}) exceeded budget ceiling ($${maxCostPerCall.toFixed(4)}).`,\r\n };\r\n\r\n if (options.onBudgetExceeded) {\r\n options.onBudgetExceeded(budgetEvent);\r\n }\r\n\r\n if (options.throwOnBudgetExceeded) {\r\n throw new VibezCircuitBreakerError(budgetEvent);\r\n }\r\n }\r\n\r\n if (options.maxTokensPerCall && usage.totalTokens > options.maxTokensPerCall) {\r\n const budgetEvent: BudgetExceededEvent = {\r\n reason: 'max_tokens_exceeded',\r\n limit: options.maxTokensPerCall,\r\n current: usage.totalTokens,\r\n model: modelId,\r\n customerId,\r\n message: `[vibezcheck] Circuit Breaker tripped: Token count (${usage.totalTokens}) exceeded maxTokensPerCall limit (${options.maxTokensPerCall}).`,\r\n };\r\n\r\n if (options.onBudgetExceeded) {\r\n options.onBudgetExceeded(budgetEvent);\r\n }\r\n\r\n if (options.throwOnBudgetExceeded) {\r\n throw new VibezCircuitBreakerError(budgetEvent);\r\n }\r\n }\r\n\r\n const mergedMetadata: Record<string, string | number | boolean> = {\r\n ...customerMetadata,\r\n ...options.metadata,\r\n ...(options.threadId ? { threadId: options.threadId } : {}),\r\n ...extraMeta,\r\n };\r\n\r\n const event: UsageEvent = {\r\n id: `evt_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,\r\n timestamp: new Date().toISOString(),\r\n model: modelId,\r\n provider,\r\n usage,\r\n cost,\r\n customerId,\r\n customerEmail,\r\n customer: customerObj,\r\n metadata: mergedMetadata,\r\n };\r\n\r\n // Record via meter batcher\r\n meter.recordUsage({\r\n model: modelId,\r\n provider,\r\n inputTokens,\r\n outputTokens,\r\n reasoningTokens: usage.reasoningTokens,\r\n cachedTokens: usage.cachedTokens,\r\n customerId,\r\n customer: customerObj,\r\n metadata: event.metadata,\r\n });\r\n\r\n if (options.onUsage) {\r\n options.onUsage(event);\r\n }\r\n\r\n // 🛡️ Duck-Typed Database Sink Execution (Airbag Isolated)\r\n if (options.database) {\r\n const dbTarget = options.database;\r\n const executeDbWrite = async () => {\r\n try {\r\n // 1. Direct Supabase client duck-typing (has .from()) or wrapped { client, table }\r\n const supabaseClient = typeof dbTarget === 'object' && dbTarget !== null && typeof dbTarget.from === 'function'\r\n ? dbTarget\r\n : (typeof dbTarget === 'object' && dbTarget !== null && typeof dbTarget.client?.from === 'function' ? dbTarget.client : null);\r\n\r\n if (supabaseClient) {\r\n const tableName = (dbTarget as any)?.table || 'vibez_usage';\r\n await supabaseClient.from(tableName).insert({\r\n customer_id: customerId,\r\n user_id: customerObj?.userId || customerId,\r\n model: modelId,\r\n input_tokens: usage.inputTokens,\r\n output_tokens: usage.outputTokens,\r\n total_tokens: usage.totalTokens,\r\n cached_tokens: usage.cachedTokens,\r\n reasoning_tokens: usage.reasoningTokens,\r\n cost_usd: cost.totalUSD,\r\n created_at: event.timestamp,\r\n metadata: event.metadata,\r\n });\r\n return;\r\n }\r\n\r\n // 2. Typed DatabaseAdapter (has .save())\r\n if (typeof dbTarget === 'object' && dbTarget !== null && typeof dbTarget.save === 'function') {\r\n await dbTarget.save(event);\r\n return;\r\n }\r\n\r\n // 3. 1-line callback function\r\n if (typeof dbTarget === 'function') {\r\n await dbTarget(event);\r\n return;\r\n }\r\n } catch (err: any) {\r\n // Zero Blast Radius: Third-party DB errors never crash the user's stream\r\n if (process.env.NODE_ENV !== 'test' && !options.silent) {\r\n console.warn(`[vibezcheck] Database record failed safely:`, err?.message || err);\r\n }\r\n }\r\n };\r\n\r\n if (typeof globalThis !== 'undefined') {\r\n const g = globalThis as any;\r\n if (typeof g.after === 'function') {\r\n g.after(() => executeDbWrite());\r\n return;\r\n }\r\n if (typeof g.waitUntil === 'function') {\r\n g.waitUntil(executeDbWrite());\r\n return;\r\n }\r\n }\r\n executeDbWrite().catch(() => {});\r\n }\r\n\r\n scheduleFlush();\r\n return event;\r\n };\r\n\r\n // Proxy to intercept LanguageModel calls\r\n const handler: ProxyHandler<any> = {\r\n get(target, prop, receiver) {\r\n const originalValue = Reflect.get(target, prop, receiver);\r\n\r\n // Intercept doStream (Vercel AI SDK v1/v2/v3)\r\n if (prop === 'doStream' && typeof originalValue === 'function') {\r\n return async function (...args: any[]) {\r\n const result = await originalValue.apply(target, args);\r\n if (!result || !result.stream) {\r\n return result;\r\n }\r\n\r\n const originalStream = result.stream;\r\n let streamCompleted = false;\r\n let accumulatedChars = 0;\r\n\r\n // Estimate input prompt tokens from args if available\r\n let estimatedInputTokens = 0;\r\n try {\r\n if (args[0]?.prompt) {\r\n const str = typeof args[0].prompt === 'string' ? args[0].prompt : JSON.stringify(args[0].prompt);\r\n estimatedInputTokens = Math.ceil(str.length / 4);\r\n }\r\n } catch {}\r\n\r\n // In-flight abort signal listener\r\n const abortSignal = args[0]?.abortSignal;\r\n if (abortSignal && captureOnAbort) {\r\n abortSignal.addEventListener(\r\n 'abort',\r\n () => {\r\n if (!streamCompleted && accumulatedChars > 0) {\r\n streamCompleted = true;\r\n const estimatedOutputTokens = Math.ceil(accumulatedChars / 3.8);\r\n handleUsage(\r\n {\r\n inputTokens: estimatedInputTokens,\r\n outputTokens: estimatedOutputTokens,\r\n },\r\n { aborted: true, partial: true }\r\n );\r\n }\r\n },\r\n { once: true }\r\n );\r\n }\r\n\r\n // Wrap stream to capture tokens upon finish chunk or abort\r\n const transformStream = new TransformStream({\r\n transform(chunk, controller) {\r\n controller.enqueue(chunk);\r\n\r\n if (chunk.type === 'text-delta' && typeof chunk.delta === 'string') {\r\n accumulatedChars += chunk.delta.length;\r\n } else if (chunk.type === 'reasoning-delta' && typeof chunk.delta === 'string') {\r\n accumulatedChars += chunk.delta.length;\r\n } else {\r\n const delta = chunk.textDelta || chunk.text || chunk.delta;\r\n if (delta && typeof delta === 'string') {\r\n accumulatedChars += delta.length;\r\n } else if (chunk.type === 'reasoning' || chunk.type === 'reasoning-delta') {\r\n const reasoning = chunk.reasoning || chunk.textDelta || chunk.text || chunk.delta || '';\r\n if (typeof reasoning === 'string') {\r\n accumulatedChars += reasoning.length;\r\n }\r\n }\r\n }\r\n\r\n // AI SDK stream finish chunk or direct usage payload (OpenAI, Anthropic, Gemini, DeepSeek, Groq, Mistral)\r\n const chunkUsage =\r\n (chunk.type === 'finish' ? chunk.usage : null) ||\r\n chunk.usage ||\r\n chunk.token_usage ||\r\n chunk.usageMetadata;\r\n if (chunkUsage) {\r\n streamCompleted = true;\r\n const event = handleUsage(chunkUsage);\r\n if (chunk.type === 'finish' && event) {\r\n chunk.providerMetadata = {\r\n ...chunk.providerMetadata,\r\n vibezcheck: {\r\n type: 'vibezcheck',\r\n cost: event.cost,\r\n usage: event.usage,\r\n model: modelId,\r\n provider,\r\n customerId,\r\n customerEmail,\r\n timestamp: event.timestamp,\r\n },\r\n };\r\n }\r\n }\r\n },\r\n flush() {\r\n // If stream ended without finish chunk (e.g. cancelled/aborted), record partial tokens\r\n if (!streamCompleted && captureOnAbort && accumulatedChars > 0) {\r\n streamCompleted = true;\r\n const estimatedOutputTokens = Math.ceil(accumulatedChars / 3.8);\r\n handleUsage(\r\n {\r\n inputTokens: estimatedInputTokens,\r\n outputTokens: estimatedOutputTokens,\r\n },\r\n { aborted: true, partial: true }\r\n );\r\n }\r\n },\r\n });\r\n\r\n return {\r\n ...result,\r\n stream: originalStream.pipeThrough(transformStream),\r\n };\r\n };\r\n }\r\n\r\n // Intercept doGenerate (Vercel AI SDK v1/v2/v3/v4/v5+)\r\n if (prop === 'doGenerate' && typeof originalValue === 'function') {\r\n return async function (...args: any[]) {\r\n const result = await originalValue.apply(target, args);\r\n const usage = result?.usage || result?.tokenUsage || result?.usageMetadata;\r\n if (usage) {\r\n handleUsage(usage);\r\n }\r\n return result;\r\n };\r\n }\r\n\r\n return originalValue;\r\n },\r\n apply(target, thisArg, argArray) {\r\n if (typeof target === 'function') {\r\n return Reflect.apply(target, thisArg, argArray);\r\n }\r\n return target;\r\n },\r\n has(target, prop) {\r\n return Reflect.has(target, prop);\r\n },\r\n ownKeys(target) {\r\n return Reflect.ownKeys(target);\r\n },\r\n getPrototypeOf(target) {\r\n return Reflect.getPrototypeOf(target);\r\n },\r\n };\r\n\r\n return new Proxy(model, handler);\r\n}\r\n\r\n/**\r\n * Convenient alias for withBilling\r\n */\r\nexport const meteredModel = withBilling;\r\n","import { withBilling, type WithBillingOptions } from './with-billing';\n\n/**\n * VibezCheck Middleware for Vercel AI SDK wrapLanguageModel({ model, middleware })\n */\nexport function vibezcheckMiddleware(options: WithBillingOptions = {}) {\n return {\n specificationVersion: 'v1' as const,\n\n wrapGenerate: async ({ doGenerate, params, model }: any) => {\n const target = { ...model, doGenerate };\n const metered = withBilling(target, options);\n return (metered as any).doGenerate(params);\n },\n\n wrapStream: async ({ doStream, params, model }: any) => {\n const target = { ...model, doStream };\n const metered = withBilling(target, options);\n return (metered as any).doStream(params);\n },\n };\n}\n\nexport default vibezcheckMiddleware;\n"],"mappings":"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","names":["rawUsage","customerObj"]}