UNPKG

ai-sdk-token-usage

Version:

A lightweight Typescript library to track and visualize token usage across multiple AI model providers.

284 lines (276 loc) 11.7 kB
import { UIMessage, LanguageModelUsage } from 'ai'; /** * Formats a numeric token count into a compact, human-readable string. * * Uses the built-in `Intl.NumberFormat` API with `"compact"` notation * (e.g., `1K`, `2.5M`) and a U.S. English locale. * * @example * ```ts * formatTokenAmount(15230) // "15.2K" * formatTokenAmount(1000000) // "1M" * ``` * * @param tokens - The number of tokens to format. * @returns A compact, localized string representation of the token amount. */ declare function formatTokenAmount(tokens: number): string; /** * Formats a numeric value as a localized currency string. * * Uses the built-in `Intl.NumberFormat` API to format the given price * in the specified currency. Defaults to USD if no currency code is provided. * * @example * ```ts * formatPrice(0.032) // "$0.03" * formatPrice(1.2, "EUR") // "€1.20" * ``` * * @param price - The numeric value to format as a currency. * @param currency - The ISO 4217 currency code (defaults to `"USD"`). * @returns A localized currency string representing the formatted price. */ declare function formatPrice(price: number, currency?: string): string; /** * Represents the result state of an asynchronous token usage computation. * * This type follows the SWR-style pattern used throughout the library, * providing a consistent structure for all React hooks in the package. * * @typeParam T - The type of the resolved data (e.g., {@link Cost}, {@link Context}, or {@link ModelDetails}). * * @property data - The resolved data, or `undefined` if still loading or an error occurred. * @property isLoading - Indicates whether the data is still being loaded. * @property error - A {@link TokenUsageError} object if an error occurred, otherwise `null`. */ type Result<T> = { data: T | undefined; isLoading: boolean; error: TokenUsageError | null; }; /** * Represents an error that occurred in a hook. * * All errors surfaced by hooks such as {@link useTokenContext}, {@link useTokenCost}, * and {@link useModelDetails} are normalized to this structure. This allows a * consistent error-handling interface across the library, regardless of the * underlying error type or source. * * @property name - The name of the error (e.g., `"MissingMetadataError"`, `"ModelNotFoundError"`). * @property message - A human-readable description of what went wrong. * @property status - The numeric status code representing the error category (e.g., `400`, `404`, `500`). * @property info - Additional structured information about the error, such as model IDs or provider details. */ type TokenUsageError = { name: string; message: string; status: number; info: unknown; }; /** * Represents a raw token usage breakdown across different token categories. * * @property input - Number of standard input tokens processed by the model. * @property output - Number of output tokens generated by the model. * @property reasoning - Number of reasoning tokens used (for models that support them). * @property cachedInput - Number of cached input tokens, used when the provider offers token reuse. */ type Breakdown = { input: number; output: number; reasoning: number; cachedInput: number; }; /** * Represents the detailed cost breakdown across different token categories. * * Each property corresponds to a token type and includes both the number of * tokens consumed (`amount`) and the monetary cost (`cost`) for that category. * * This structure mirrors {@link Breakdown}, but augments it with cost data, * enabling detailed per-category cost analysis and visualization. * * @property input - Cost and token count for standard input tokens. * @property output - Cost and token count for output tokens generated by the model. * @property reasoning - Cost and token count for reasoning tokens (if supported by the model). * @property cachedInput - Cost and token count for cached input tokens, when token reuse is supported. */ type CostBreakdown = { input: { amount: number; cost: number; }; output: { amount: number; cost: number; }; reasoning: { amount: number; cost: number; }; cachedInput: { amount: number; cost: number; }; }; /** * Represents the contextual token usage information for a model response. * * This structure quantifies how much of the model’s context window is used * and how much remains, based on aggregated token usage data. * * It is returned by {@link useTokenContext} and used to visualize context * consumption, detect truncation risks, and provide real-time feedback * in chat or reporting interfaces. * * @property breakdown - Detailed token usage across input, output, reasoning, and cached input tokens. * @property used - The total number of tokens used by the model in this context window. * @property limit - The maximum number of tokens the model can process in its context window. * @property remaining - The number of tokens still available before reaching the context limit. * @property fractionUsed - The fraction of the context window that has been used (between `0` and `1`). * @property percentageUsed - The percentage of the context window that has been used (between `0` and `100`). * @property isExceeded - Whether the total token usage exceeds the model’s context window limit. */ type Context = { breakdown: Breakdown; used: number; limit: number; remaining: number; fractionUsed: number; percentageUsed: number; isExceeded: boolean; }; /** * Represents the total monetary cost of token usage for a model response. * * This structure combines a detailed {@link CostBreakdown} with the aggregated * total cost and the currency used for pricing. It provides a unified view of * how much a model interaction costs, both overall and per token category. * * It is returned by {@link useTokenCost} and used to display or calculate * pricing information in dashboards, analytics, or chat interfaces. * * @property breakdown - Detailed per-category cost and token count information. * @property total - The total computed cost across all token categories. * @property currency - The currency code for the total cost, currently fixed to `"USD"`. */ type Cost = { breakdown: CostBreakdown; total: number; currency: "USD"; }; /** * Represents the detailed configuration and limits of a specific model. * * This structure includes the model’s canonical identifier, per-token pricing, * and token limits for both context and output. It provides the necessary data * for computing token costs and for displaying model information in UIs. * * It is returned by {@link useModelDetails} and used internally by other hooks * to resolve pricing, compute costs, and calculate remaining context window capacity. * * @property canonicalSlug - The canonical model identifier, combining provider and model ID * (e.g., `"openai/gpt-5"`). * @property pricing - The per-token pricing structure for input, output, reasoning, and cached input tokens. * @property limit - The token limits for the model, defining both the total context window * (`context`) and the maximum number of output tokens (`output`). */ type ModelDetails = { canonicalSlug: string; pricing: Breakdown; limit: { context: number; output: number; }; }; /** * React hook that retrieves **model details**, such as pricing and token limits. * * The hook derives model information directly from the model registry based on * the provided {@link canonicalSlug}. It returns structured data including * per-token pricing (input, output, reasoning, cached input) and context/output * token limits. * * Internally, the hook leverages SWR and follows the SWR-style return pattern with * `data`, `isLoading`, and `error` states for consistent asynchronous handling. * * @param params - The parameters for the hook. * @param params.canonicalSlug - The canonical model identifier, composed of provider and model ID * (e.g. `"openai/gpt-5"`). * * @returns A {@link Result} object containing: * - `data`: The resolved {@link ModelDetails}, including pricing and limits. * - `isLoading`: Whether model data is still being loaded. * - `error`: A {@link TokenUsageError} if an error occurred. */ declare function useModelDetails({ canonicalSlug }: { canonicalSlug: string; }): Result<ModelDetails>; /** * React hook that provides insight into how much of the model’s context window is remaining. * * The hook derives usage information directly from the message metadata and the model’s defined * context window. It returns pre-computed values such as used and remaining tokens, percentage used, * and whether the context limit has been exceeded. * * Internally, the hook leverages SWR and follows the SWR-style return pattern with * `data`, `isLoading`, and `error` states for consistent asynchronous handling. * * @param params - The parameters for the hook. * @param params.messages - The messages in the chat, typically returned from `useChat`. * @param params.canonicalSlug - The canonical model identifier, composed of provider and model ID (e.g. `"openai/gpt-5"`). * * @returns A {@link Result} object containing: * - `data`: The computed {@link Context} with usage metrics. * - `isLoading`: Whether model data is still being loaded. * - `error`: A {@link TokenUsageError} if an error occurred. */ declare function useTokenContext({ messages, canonicalSlug, }: { messages: readonly UIMessage[]; canonicalSlug: string; }): Result<Context>; /** * React hook that computes the **monetary cost** of token usage for assistant messages. * * The hook derives cost directly from message metadata and the model’s pricing * information. It returns pre-computed values such as the total cost, a detailed * cost breakdown per token type (input, output, reasoning, cached input), and the * currency. * * Internally, the hook leverages SWR and follows the SWR-style return pattern with * `data`, `isLoading`, and `error` states for consistent asynchronous handling. * * @param params - The parameters for the hook. Exactly one of the following must be provided: * - `messages`: All chat messages (typically returned from `useChat`). * - `message`: A single assistant message. * * @returns A {@link Result} object containing: * - `data`: The computed {@link Cost} with `breakdown`, `total`, and `currency`. * - `isLoading`: Whether model pricing data is still being loaded. * - `error`: A {@link TokenUsageError} if an error occurred. */ declare function useTokenCost({ messages }: { messages: readonly UIMessage[]; }): Result<Cost>; declare function useTokenCost({ message }: { message: UIMessage; }): Result<Cost>; /** * Represents the token usage metadata attached to a message. * * This metadata is generated by AI SDK Token Usage and includes * both the total token usage reported by the model and the * canonical model identifier. * * Used by the `messageMetadata` callback in * `toUIMessageStreamResponse` to store cost and usage information * for each completed model response. */ type TokenUsageMetadata = { /** The total token usage for the model response, as reported by the provider. */ totalUsage: LanguageModelUsage; /** The canonical model identifier (e.g., "openai/gpt-5"). */ canonicalSlug: string; }; export { type Breakdown, type Context, type Cost, type CostBreakdown, type ModelDetails, type Result, type TokenUsageError, type TokenUsageMetadata, formatPrice, formatTokenAmount, useModelDetails, useTokenContext, useTokenCost };