/** * WorthDoing.ai * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * File: src/lib/anthropic/client.ts * Description: Anthropic adapter — singleton client and model configuration for the agent. */ import Anthropic from "@anthropic-ai/sdk"; import { env } from "@/lib/env"; const globalForAnthropic = globalThis as unknown as { __wdAnthropic?: Anthropic }; export function anthropic(): Anthropic { if (!globalForAnthropic.__wdAnthropic) { globalForAnthropic.__wdAnthropic = new Anthropic({ apiKey: env().ANTHROPIC_API_KEY, maxRetries: 3, }); } return globalForAnthropic.__wdAnthropic; } export function agentModel(): string { return env().CLAUDE_AGENT_MODEL; } export function synthesisModel(): string { return env().CLAUDE_SYNTHESIS_MODEL; } /** Approximate USD cost for a request, for observability (list prices, claude-opus-5). */ export function estimateCostUsd(model: string, inputTokens: number, outputTokens: number): number { // Per-million-token list prices; fall back to Opus-tier if unknown. const prices: Record = { "claude-opus-5": { in: 5, out: 25 }, "claude-sonnet-5": { in: 3, out: 15 }, "claude-haiku-4-5": { in: 1, out: 5 }, }; const p = prices[model] ?? { in: 5, out: 25 }; return (inputTokens * p.in + outputTokens * p.out) / 1_000_000; }