/** * @module @arcis/node/middleware/token-budget * * Token-budget protection middleware. Caps per-key token spend over a * sliding window — meant for routes that proxy LLM calls, where a tight * 100-req/min rate limit isn't enough because a single 50KB prompt costs * the same as 1000 small requests. * * @example * import express from 'express'; * import { tokenBudget } from '@arcis/node'; * * const guard = tokenBudget({ * maxTokens: 100_000, // 100K tokens per window * windowMs: 60 * 60 * 1000, // 1-hour window * maxRequestTokens: 5_000, // reject any single request over this * keyGenerator: (req) => req.user?.id ?? req.ip, * }); * * app.post('/chat', guard, chatHandler); * * The default token estimator is `Math.ceil(bytesOf(body+query) / 4)` — * close to OpenAI's "1 token ≈ 4 English characters" rule. Override via * `estimateTokens` for accurate counting (tiktoken, etc.). */ import type { Request, RequestHandler } from 'express'; export interface TokenBudgetOptions { /** Max tokens a single key can spend in one window. Default: 100,000. */ maxTokens?: number; /** Window length in milliseconds. Default: 60 * 60 * 1000 (1 hour). */ windowMs?: number; /** * Max tokens a single request may consume. Requests over this size are * rejected with 413 BEFORE counting against the window budget. Default: * unset (no per-request cap). */ maxRequestTokens?: number; /** * Function that returns the budget key for a request. Default: client IP * (req.ip), falling back to `unknown` when unresolvable. */ keyGenerator?: (req: Request) => string; /** * Function that estimates the number of tokens a request will consume. * Default: `Math.ceil((req.body + req.query stringified bytes) / 4)`, * which approximates OpenAI's "1 token ≈ 4 characters" rule. Override * with tiktoken/accurate counting when you need precision. */ estimateTokens?: (req: Request) => number; /** Status code for budget-exceeded responses. Default: 429. */ statusCode?: number; /** Status code for oversize-request rejections. Default: 413. */ statusCodeOversize?: number; /** Error message when budget is exceeded. */ message?: string; /** Error message when a single request exceeds maxRequestTokens. */ messageOversize?: string; /** Skip budget enforcement for certain requests. */ skip?: (req: Request) => boolean; } export interface TokenBudgetMiddleware extends RequestHandler { /** Release internal cleanup resources. */ close: () => void; /** Inspect current usage for a key (read-only; for tests/telemetry). */ inspect: (key: string) => { used: number; resetTime: number; } | null; } /** * Build a token-budget middleware. See module-level JSDoc for usage. */ export declare function tokenBudget(options?: TokenBudgetOptions): TokenBudgetMiddleware; export default tokenBudget; //# sourceMappingURL=token-budget.d.ts.map