import { useMemo } from 'react'; export interface UseTokenCountOptions { /** * Per-1k-token USD cost (input price). Default 0 (no cost computed). * Override per-model, e.g. `0.00015` for gpt-4o-mini input. */ costPer1kUsd?: number; /** * Chars-per-token approximation. Default 4 — the OpenAI rule-of-thumb * for English. Pass 3.5 for code-heavy contexts, ~6 for tightly * tokenised Indic / CJK scripts. */ charsPerToken?: number; } export interface UseTokenCountValue { /** Approximate token count (rounded up). */ tokens: number; /** Character count (raw length of `text`). */ chars: number; /** Approximate USD cost. 0 if `costPer1kUsd` is 0 / undefined. */ costUsd: number; } /** * `useTokenCount` — cheap, dependency-free token estimator for live * input previews. * * Wave 9.E.5. Not for billing. Hosts that need accurate counts should * call the model provider's tokenizer; this hook is for UI feedback in * composer surfaces ("you're typing ~412 tokens, ≈ \$0.0001"). * * Pure function under the hood — wrapped in `useMemo` so the result * is stable across renders when `text` is unchanged. */ export function useTokenCount( text: string, options: UseTokenCountOptions = {}, ): UseTokenCountValue { const { costPer1kUsd = 0, charsPerToken = 4 } = options; return useMemo(() => { const chars = text.length; const cpt = charsPerToken > 0 ? charsPerToken : 4; const tokens = chars === 0 ? 0 : Math.ceil(chars / cpt); const costUsd = costPer1kUsd > 0 ? (tokens / 1000) * costPer1kUsd : 0; return { tokens, chars, costUsd }; }, [text, costPer1kUsd, charsPerToken]); }