/** * Register a usage reporter. Returns an `unregister` callback for * apps that want to swap reporters at runtime (test setup/teardown, * tenant isolation, etc.). */ export declare function onUsage(reporter: UsageReporter): () => void; /** * Drop every registered reporter. Useful for tests. */ export declare function clearUsageReporters(): void; /** * Emit a usage record to every registered reporter. Called by * driver completion paths after the response lands. Reporter * errors are caught + logged so a misbehaving sink doesn't * propagate up to the caller. */ export declare function recordUsage(record: UsageRecord): void; /** * Snapshot the currently-registered reporters. Useful for tests * to assert behavior without exposing the internal array. */ export declare function listUsageReporters(): readonly UsageReporter[]; /** * AI usage tracking (stacksjs/stacks#1878 A-6). * * Background: `AIResult.usage` returns token counts per-call but * nothing aggregates them. Apps that want "this user has spent * $X this month" build the aggregation themselves — wiring a * listener on every model invocation, persisting the running * total, etc. * * This module ships a singleton recorder that drivers emit to on * each completion. Apps install one or more `UsageReporter` * functions that get called with `{ provider, model, prompt_tokens, * completion_tokens, timestamp, durationMs }` and decide what to * do (store to DB, push to Datadog, etc.). Default behavior with * no reporter is a no-op — the framework doesn't impose a sink. */ export declare interface UsageRecord { provider: string model: string promptTokens: number completionTokens: number totalTokens: number durationMs: number timestamp: number metadata?: Record } /** * A reporter is called once per recorded completion. Multiple * reporters can be installed simultaneously; they fire in * registration order. Reporters MUST NOT throw — errors are * caught and logged but otherwise ignored so a flaky metrics * sink doesn't break the user's completion call. */ export type UsageReporter = (record: UsageRecord) => void | Promise;