wulf-pulse/lib/services/llm/pricing.ts
lorentz 1112a06afe feat: RMM Overshell, IT Glue audit/write-back, LogLift, link-aware bundles, dashboard overhaul
- RMM Overshell (migration 077): admin page, dispatch UI, executor/worker, target
  resolver, script registry (AD/DHCP/DNS/event-log/services/software/network/loglift)
- LogLift evidence pipeline (migration 078): upload webhook, B2 storage client,
  receiver/matcher, EventLogCollector PowerShell script
- IT Glue audit + write-back (migrations 075, 076): asset-audit runner, ticket
  xrefs, applications/configurations browse pages + apply/revert/audit endpoints
- Link-aware analyzer bundles (migration 073) + provider toggle (migration 074):
  link-discovery service, OpenRouter LLM provider, related-tickets/itglue-suggestion
  panels, analyze-bundle endpoint
- Endpoint data model + device-link reconciliation (migrations 079, 080): conflicts
  admin page, reconciler service, resolve endpoints
- Dashboard overhaul: integration-health service + alerts, overview/health endpoints
- Permissions: add itglue + rmm scopes; middleware: public /api/rmm/loglift route

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 07:13:18 -04:00

71 lines
2.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Per-model token pricing for cost estimation in analyzer_analyses.estimated_cost_usd.
*
* Rates are USD per 1,000,000 tokens.
*
* VERIFY QUARTERLY against:
* - https://docs.claude.com/en/docs/about-claude/pricing
* - https://openrouter.ai/api/v1/models (deepseek/* entries)
*
* Last verified: 2026-05-02 (V4 Pro/Flash + R1-0528 added from OpenRouter live list)
*/
import {
HAIKU,
SONNET,
OPUS,
DEEPSEEK_V4_FLASH,
DEEPSEEK_V4_PRO,
DEEPSEEK_R1,
type ModelId,
} from './models';
interface ModelRate {
/** USD per 1M input tokens */
input: number;
/** USD per 1M output tokens */
output: number;
/** USD per 1M tokens read from prompt cache (~0.1× input on Anthropic; not applicable on OpenRouter — set equal to input). */
cacheRead: number;
/** USD per 1M tokens written to 5-minute prompt cache (~1.25× input on Anthropic; not applicable on OpenRouter — set equal to input). */
cacheWrite5m: number;
}
export const PRICING: Record<ModelId, ModelRate> = {
// Anthropic
[HAIKU]: { input: 1.0, output: 5.0, cacheRead: 0.1, cacheWrite5m: 1.25 },
[SONNET]: { input: 3.0, output: 15.0, cacheRead: 0.3, cacheWrite5m: 3.75 },
[OPUS]: { input: 5.0, output: 25.0, cacheRead: 0.5, cacheWrite5m: 6.25 },
// OpenRouter / DeepSeek (no prompt-cache discount surfaced via the OpenAI-
// compatible API; we treat cacheRead/cacheWrite as the input rate so the
// estimator stays additive even if those usage fields ever come back filled).
[DEEPSEEK_V4_FLASH]: { input: 0.14, output: 0.28, cacheRead: 0.14, cacheWrite5m: 0.14 },
[DEEPSEEK_V4_PRO]: { input: 0.435, output: 0.87, cacheRead: 0.435, cacheWrite5m: 0.435 },
[DEEPSEEK_R1]: { input: 0.50, output: 2.15, cacheRead: 0.50, cacheWrite5m: 0.50 },
};
export interface TokenUsage {
input_tokens: number;
output_tokens: number;
cache_creation_input_tokens?: number;
cache_read_input_tokens?: number;
}
/**
* USD cost of a single LLM call given its token usage. Caches are billed
* separately from raw input tokens — cache_read at ~0.1×, cache_write at ~1.25×.
*/
export function estimateCostUsd(model: ModelId, usage: TokenUsage): number {
const rate = PRICING[model];
const cacheRead = usage.cache_read_input_tokens ?? 0;
const cacheWrite = usage.cache_creation_input_tokens ?? 0;
const uncachedInput = usage.input_tokens; // SDK reports this as the uncached remainder
const cost =
(uncachedInput / 1_000_000) * rate.input +
(usage.output_tokens / 1_000_000) * rate.output +
(cacheRead / 1_000_000) * rate.cacheRead +
(cacheWrite / 1_000_000) * rate.cacheWrite5m;
// Round to 4 decimals (matches analyzer_analyses.estimated_cost_usd numeric(10,4)).
return Math.round(cost * 10_000) / 10_000;
}