{"version":3,"sources":["../../src/utils/tokenCounter.ts","../../src/pricing/PricingCalculator.ts","../../src/pricing/CostTracker.ts","../../src/pricing/budgets/Alerting.ts"],"names":["EventEmitter"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Simple token counter using approximate heuristics\n * For more accurate counting, consider using tiktoken library\n */\n\nconst CHARS_PER_TOKEN = 4; // OpenAI's rule of thumb\nconst AVG_TOKENS_PER_MESSAGE = 4; // Message formatting overhead\n\nexport interface TokenEstimate {\n  tokens: number;\n  characters: number;\n  method: 'approximate' | 'exact';\n}\n\nexport class TokenCounter {\n  /**\n   * Estimate tokens for a string\n   */\n  static estimateTokens(text: string): TokenEstimate {\n    const characters = text.length;\n    const tokens = Math.ceil(characters / CHARS_PER_TOKEN);\n\n    return {\n      tokens,\n      characters,\n      method: 'approximate',\n    };\n  }\n\n  /**\n   * Estimate tokens for chat messages\n   */\n  static estimateMessageTokens(messages: Array<{ role: string; content: string }>): TokenEstimate {\n    let totalTokens = 0;\n    let totalCharacters = 0;\n\n    for (const message of messages) {\n      const contentTokens = this.estimateTokens(message.content);\n      totalTokens += contentTokens.tokens + AVG_TOKENS_PER_MESSAGE;\n      totalCharacters += contentTokens.characters;\n    }\n\n    return {\n      tokens: totalTokens,\n      characters: totalCharacters,\n      method: 'approximate',\n    };\n  }\n\n  /**\n   * Estimate completion cost\n   */\n  static estimateCost(\n    inputTokens: number,\n    outputTokens: number,\n    inputPrice: number, // per 1M tokens\n    outputPrice: number, // per 1M tokens\n  ): number {\n    const inputCost = (inputTokens / 1_000_000) * inputPrice;\n    const outputCost = (outputTokens / 1_000_000) * outputPrice;\n    return inputCost + outputCost;\n  }\n\n  /**\n   * Check if text exceeds token limit\n   */\n  static exceedsLimit(text: string, limit: number): boolean {\n    const estimate = this.estimateTokens(text);\n    return estimate.tokens > limit;\n  }\n\n  /**\n   * Truncate text to fit within token limit\n   */\n  static truncateToLimit(text: string, limit: number): string {\n    const estimate = this.estimateTokens(text);\n\n    if (estimate.tokens <= limit) {\n      return text;\n    }\n\n    const ratio = limit / estimate.tokens;\n    const maxChars = Math.floor(text.length * ratio * 0.95); // 5% buffer\n    return text.substring(0, maxChars);\n  }\n}\n","import { CostEstimate, TokenUsage, CostComparison } from '../types/pricing';\nimport { ModelCatalog } from '../models/ModelCatalog';\nimport { TokenCounter } from '../utils/tokenCounter';\n\nexport class PricingCalculator {\n  constructor(private catalog: ModelCatalog) {}\n\n  /**\n   * Estimate cost for a specific model\n   */\n  estimateCost(\n    modelId: string,\n    tokens: TokenUsage | { input: number; output: number },\n  ): CostEstimate {\n    const model = this.catalog.getModel(modelId);\n\n    if (!model) {\n      throw new Error(`Model not found: ${modelId}`);\n    }\n\n    const tokenUsage: TokenUsage =\n      'totalTokens' in tokens\n        ? tokens\n        : {\n            promptTokens: tokens.input,\n            completionTokens: tokens.output,\n            totalTokens: tokens.input + tokens.output,\n          };\n\n    const inputCost = (tokenUsage.promptTokens / 1_000_000) * model.pricing.inputTokens;\n    const outputCost = (tokenUsage.completionTokens / 1_000_000) * model.pricing.outputTokens;\n    const totalCost = inputCost + outputCost;\n\n    return {\n      inputCost,\n      outputCost,\n      totalCost,\n      currency: model.pricing.currency || 'USD',\n      tokenUsage,\n      modelId,\n    };\n  }\n\n  /**\n   * Estimate cost from text (approximation)\n   */\n  estimateFromText(\n    modelId: string,\n    inputText: string,\n    estimatedOutputTokens: number,\n  ): CostEstimate {\n    const inputEstimate = TokenCounter.estimateTokens(inputText);\n\n    return this.estimateCost(modelId, {\n      input: inputEstimate.tokens,\n      output: estimatedOutputTokens,\n    });\n  }\n\n  /**\n   * Compare costs across multiple models\n   */\n  compareModels(\n    modelIds: string[],\n    tokens: TokenUsage | { input: number; output: number },\n  ): CostComparison {\n    const estimates = new Map<string, CostEstimate>();\n    let cheapestId = '';\n    let cheapestCost = Infinity;\n    let mostExpensiveId = '';\n    let mostExpensiveCost = -Infinity;\n    let totalCost = 0;\n\n    for (const modelId of modelIds) {\n      try {\n        const estimate = this.estimateCost(modelId, tokens);\n        estimates.set(modelId, estimate);\n\n        totalCost += estimate.totalCost;\n\n        if (estimate.totalCost < cheapestCost) {\n          cheapestCost = estimate.totalCost;\n          cheapestId = modelId;\n        }\n\n        if (estimate.totalCost > mostExpensiveCost) {\n          mostExpensiveCost = estimate.totalCost;\n          mostExpensiveId = modelId;\n        }\n      } catch {\n        // Skip models that don't exist\n        continue;\n      }\n    }\n\n    const averageCost = estimates.size > 0 ? totalCost / estimates.size : 0;\n\n    // Add savings calculation to each estimate\n    estimates.forEach((estimate) => {\n      estimate.savingsVsDefault = cheapestCost - estimate.totalCost;\n      estimate.percentileCost =\n        estimates.size > 0\n          ? (Array.from(estimates.values()).filter((e) => e.totalCost <= estimate.totalCost)\n              .length /\n              estimates.size) *\n            100\n          : 0;\n    });\n\n    return {\n      models: estimates,\n      cheapest: {\n        modelId: cheapestId,\n        cost: cheapestCost,\n      },\n      mostExpensive: {\n        modelId: mostExpensiveId,\n        cost: mostExpensiveCost,\n      },\n      averageCost,\n    };\n  }\n\n  /**\n   * Get cheapest model for a task\n   */\n  getCheapestModel(\n    modelIds: string[],\n    tokens: TokenUsage | { input: number; output: number },\n  ): {\n    modelId: string;\n    estimate: CostEstimate;\n  } {\n    const comparison = this.compareModels(modelIds, tokens);\n    const estimate = comparison.models.get(comparison.cheapest.modelId);\n\n    if (!estimate) {\n      throw new Error('No valid models found');\n    }\n\n    return {\n      modelId: comparison.cheapest.modelId,\n      estimate,\n    };\n  }\n\n  /**\n   * Calculate potential savings\n   */\n  calculateSavings(\n    currentModelId: string,\n    alternativeModelId: string,\n    tokens: TokenUsage | { input: number; output: number },\n  ): {\n    savings: number;\n    savingsPercentage: number;\n    currentCost: number;\n    alternativeCost: number;\n  } {\n    const currentCost = this.estimateCost(currentModelId, tokens).totalCost;\n    const alternativeCost = this.estimateCost(alternativeModelId, tokens).totalCost;\n    const savings = currentCost - alternativeCost;\n    const savingsPercentage = currentCost > 0 ? (savings / currentCost) * 100 : 0;\n\n    return {\n      savings,\n      savingsPercentage,\n      currentCost,\n      alternativeCost,\n    };\n  }\n}\n","import { UsageRecord, CostSummary } from '../types/pricing';\nimport { EventEmitter } from 'eventemitter3';\n\ninterface CostTrackerEvents {\n  'usage:recorded': (record: UsageRecord) => void;\n  'threshold:exceeded': (\n    period: 'daily' | 'monthly' | 'total',\n    current: number,\n    limit: number,\n  ) => void;\n}\n\nexport class CostTracker extends EventEmitter<CostTrackerEvents> {\n  private usageHistory: UsageRecord[] = [];\n  private totalCost: number = 0;\n  private costByModel: Map<string, number> = new Map();\n  private costByProvider: Map<string, number> = new Map();\n\n  constructor(private retentionDays: number = 30) {\n    super();\n    this.startCleanupInterval();\n  }\n\n  /**\n   * Record a usage event\n   */\n  recordUsage(record: UsageRecord): void {\n    this.usageHistory.push(record);\n\n    // Update totals\n    this.totalCost += record.cost.totalCost;\n\n    // Update by model\n    const modelCost = this.costByModel.get(record.modelId) || 0;\n    this.costByModel.set(record.modelId, modelCost + record.cost.totalCost);\n\n    // Update by provider\n    const providerCost = this.costByProvider.get(record.provider) || 0;\n    this.costByProvider.set(record.provider, providerCost + record.cost.totalCost);\n\n    this.emit('usage:recorded', record);\n  }\n\n  /**\n   * Get usage summary for a time period\n   */\n  getSummary(startDate?: Date, endDate?: Date): CostSummary {\n    const end = endDate || new Date();\n    const start = startDate || new Date(end.getTime() - 30 * 24 * 60 * 60 * 1000); // 30 days ago\n\n    const records = this.usageHistory.filter((r) => r.timestamp >= start && r.timestamp <= end);\n\n    const totalCost = records.reduce(\n      (sum, r) => sum + (isNaN(r.cost.totalCost) ? 0 : r.cost.totalCost),\n      0,\n    );\n    const totalTokens = records.reduce(\n      (sum, r) => sum + (isNaN(r.tokenUsage.totalTokens) ? 0 : r.tokenUsage.totalTokens),\n      0,\n    );\n    const totalRequests = records.length;\n    const averageCostPerRequest = totalRequests > 0 ? totalCost / totalRequests : 0;\n\n    const costByModel = new Map<string, number>();\n    const costByProvider = new Map<string, number>();\n\n    for (const record of records) {\n      costByModel.set(\n        record.modelId,\n        (costByModel.get(record.modelId) || 0) + record.cost.totalCost,\n      );\n\n      costByProvider.set(\n        record.provider,\n        (costByProvider.get(record.provider) || 0) + record.cost.totalCost,\n      );\n    }\n\n    return {\n      totalCost,\n      totalRequests,\n      totalTokens,\n      averageCostPerRequest,\n      costByModel,\n      costByProvider,\n      period: { start, end },\n    };\n  }\n\n  /**\n   * Get daily costs\n   */\n  getDailyCost(date?: Date): number {\n    const targetDate = date || new Date();\n    const start = new Date(targetDate.getFullYear(), targetDate.getMonth(), targetDate.getDate());\n    const end = new Date(start.getTime() + 24 * 60 * 60 * 1000);\n\n    return this.usageHistory\n      .filter((r) => r.timestamp >= start && r.timestamp < end)\n      .reduce((sum, r) => sum + r.cost.totalCost, 0);\n  }\n\n  /**\n   * Get monthly costs\n   */\n  getMonthlyCost(year?: number, month?: number): number {\n    const now = new Date();\n    const targetYear = year ?? now.getFullYear();\n    const targetMonth = month ?? now.getMonth();\n\n    const start = new Date(targetYear, targetMonth, 1);\n    const end = new Date(targetYear, targetMonth + 1, 1);\n\n    return this.usageHistory\n      .filter((r) => r.timestamp >= start && r.timestamp < end)\n      .reduce((sum, r) => sum + r.cost.totalCost, 0);\n  }\n\n  /**\n   * Get total cost\n   */\n  getTotalCost(): number {\n    return this.totalCost;\n  }\n\n  /**\n   * Get usage by model\n   */\n  getUsageByModel(): Map<string, CostSummary> {\n    const modelSummaries = new Map<string, CostSummary>();\n\n    for (const modelId of this.costByModel.keys()) {\n      const records = this.usageHistory.filter((r) => r.modelId === modelId);\n      const totalCost = records.reduce((sum, r) => sum + r.cost.totalCost, 0);\n      const totalTokens = records.reduce((sum, r) => sum + r.tokenUsage.totalTokens, 0);\n      const totalRequests = records.length;\n\n      modelSummaries.set(modelId, {\n        totalCost,\n        totalRequests,\n        totalTokens,\n        averageCostPerRequest: totalRequests > 0 ? totalCost / totalRequests : 0,\n        costByModel: new Map([[modelId, totalCost]]),\n        costByProvider: new Map(),\n        period: {\n          start: records[0]?.timestamp,\n          end: records[records.length - 1]?.timestamp,\n        },\n      });\n    }\n\n    return modelSummaries;\n  }\n\n  /**\n   * Get usage by provider\n   */\n  getUsageByProvider(): Map<string, CostSummary> {\n    const providerSummaries = new Map<string, CostSummary>();\n\n    for (const provider of this.costByProvider.keys()) {\n      const records = this.usageHistory.filter((r) => r.provider === provider);\n      const totalCost = records.reduce((sum, r) => sum + r.cost.totalCost, 0);\n      const totalTokens = records.reduce((sum, r) => sum + r.tokenUsage.totalTokens, 0);\n      const totalRequests = records.length;\n\n      providerSummaries.set(provider, {\n        totalCost,\n        totalRequests,\n        totalTokens,\n        averageCostPerRequest: totalRequests > 0 ? totalCost / totalRequests : 0,\n        costByModel: new Map(),\n        costByProvider: new Map([[provider, totalCost]]),\n        period: {\n          start: records[0]?.timestamp,\n          end: records[records.length - 1]?.timestamp,\n        },\n      });\n    }\n\n    return providerSummaries;\n  }\n\n  /**\n   * Clear old records\n   */\n  private cleanup(): void {\n    const cutoffDate = new Date(Date.now() - this.retentionDays * 24 * 60 * 60 * 1000);\n    this.usageHistory = this.usageHistory.filter((r) => r.timestamp >= cutoffDate);\n  }\n\n  private startCleanupInterval(): void {\n    setInterval(() => this.cleanup(), 24 * 60 * 60 * 1000); // Daily cleanup\n  }\n\n  /**\n   * Export usage data\n   */\n  exportData(): UsageRecord[] {\n    return [...this.usageHistory];\n  }\n\n  /**\n   * Reset all tracking data\n   */\n  reset(): void {\n    this.usageHistory = [];\n    this.totalCost = 0;\n    this.costByModel.clear();\n    this.costByProvider.clear();\n  }\n}\n","/**\n * Budget Alerting System\n * Monitors spending and triggers alerts\n */\n\nimport { EventEmitter } from 'eventemitter3';\nimport type { Logger } from '../../utils/logger';\n\nexport interface AlertThreshold {\n  percentage: number; // Percentage of budget (e.g., 80 for 80%)\n  action: 'warn' | 'notify' | 'block';\n  message?: string;\n}\n\nexport interface AlertConfig {\n  daily?: AlertThreshold[];\n  monthly?: AlertThreshold[];\n  total?: AlertThreshold[];\n  email?: string;\n  webhook?: string;\n}\n\nexport interface AlertEvent {\n  type: 'daily' | 'monthly' | 'total';\n  threshold: number;\n  current: number;\n  limit: number;\n  percentage: number;\n  action: 'warn' | 'notify' | 'block';\n  timestamp: number;\n}\n\nexport class BudgetAlerting extends EventEmitter {\n  private config: AlertConfig;\n  private logger: Logger;\n  private triggeredAlerts: Set<string>;\n\n  constructor(config: AlertConfig, logger: Logger) {\n    super();\n    this.config = config;\n    this.logger = logger;\n    this.triggeredAlerts = new Set();\n  }\n\n  /**\n   * Check if budget threshold is exceeded\n   */\n  check(type: 'daily' | 'monthly' | 'total', current: number, limit: number): AlertEvent | null {\n    const thresholds = this.config[type];\n\n    if (!thresholds || thresholds.length === 0) {\n      return null;\n    }\n\n    const percentage = (current / limit) * 100;\n\n    // Find highest triggered threshold\n    let triggeredThreshold: AlertThreshold | null = null;\n\n    for (const threshold of thresholds.sort((a, b) => b.percentage - a.percentage)) {\n      if (percentage >= threshold.percentage) {\n        triggeredThreshold = threshold;\n        break;\n      }\n    }\n\n    if (!triggeredThreshold) {\n      return null;\n    }\n\n    // Create alert key to prevent duplicate alerts\n    const alertKey = `${type}-${triggeredThreshold.percentage}-${Math.floor(percentage)}`;\n\n    // Check if already triggered\n    if (this.triggeredAlerts.has(alertKey)) {\n      return null;\n    }\n\n    // Mark as triggered\n    this.triggeredAlerts.add(alertKey);\n\n    const alert: AlertEvent = {\n      type,\n      threshold: triggeredThreshold.percentage,\n      current,\n      limit,\n      percentage,\n      action: triggeredThreshold.action,\n      timestamp: Date.now(),\n    };\n\n    // Emit appropriate event\n    this.emitAlert(alert);\n\n    return alert;\n  }\n\n  /**\n   * Emit alert events\n   */\n  private emitAlert(alert: AlertEvent): void {\n    this.emit('alert', alert);\n    this.emit(`alert:${alert.action}`, alert);\n    this.emit(`alert:${alert.type}`, alert);\n\n    // Log alert\n    const message = `Budget alert: ${alert.type} spending at ${alert.percentage.toFixed(1)}% ($${alert.current.toFixed(2)}/$${alert.limit.toFixed(2)})`;\n\n    if (alert.action === 'block') {\n      this.logger.error(message, { alert });\n    } else if (alert.action === 'warn') {\n      this.logger.warn(message, { alert });\n    } else {\n      this.logger.info(message, { alert });\n    }\n\n    // Send notifications if configured\n    if (this.config.email) {\n      this.sendEmailAlert(alert);\n    }\n\n    if (this.config.webhook) {\n      this.sendWebhookAlert(alert);\n    }\n  }\n\n  /**\n   * Send email alert\n   */\n  private sendEmailAlert(alert: AlertEvent): void {\n    // Placeholder - implement email sending\n    this.logger.info('Sending email alert', {\n      to: this.config.email,\n      alert,\n    });\n\n    this.emit('alert:email:sent', { to: this.config.email, alert });\n  }\n\n  /**\n   * Send webhook alert\n   */\n  private sendWebhookAlert(alert: AlertEvent): void {\n    // Placeholder - implement webhook POST\n    this.logger.info('Sending webhook alert', {\n      url: this.config.webhook,\n      alert,\n    });\n\n    this.emit('alert:webhook:sent', { url: this.config.webhook, alert });\n  }\n\n  /**\n   * Reset triggered alerts\n   */\n  reset(): void {\n    this.triggeredAlerts.clear();\n    this.logger.info('Reset triggered alerts');\n  }\n\n  /**\n   * Update alert configuration\n   */\n  updateConfig(config: Partial<AlertConfig>): void {\n    this.config = {\n      ...this.config,\n      ...config,\n    };\n\n    this.logger.info('Updated alert configuration', { config: this.config });\n  }\n\n  /**\n   * Get alert configuration\n   */\n  getConfig(): AlertConfig {\n    return { ...this.config };\n  }\n\n  /**\n   * Check if alert has been triggered\n   */\n  hasTriggered(type: string, threshold: number): boolean {\n    const key = `${type}-${threshold}`;\n    return Array.from(this.triggeredAlerts).some((k) => k.startsWith(key));\n  }\n}\n"]}