import { type UsageBillingMode } from "./store.js"; export type UsageMetricsScope = "me" | "workspace"; /** * Selects usage from every app instead of one app's identities. A symbol, not * a reserved string, so no real app key can ever be mistaken for it. */ export declare const ALL_USAGE_APPS: unique symbol; /** `get-usage-metrics` app filter values that select every app / this app. */ export declare const USAGE_APP_FILTER_ALL = "all"; export declare const USAGE_APP_FILTER_CURRENT = "current"; /** One app's key (its configured legacy identities merge in), or every app. */ export type UsageAppSelection = string | typeof ALL_USAGE_APPS; export interface UsageMetricBucket { key: string; label: string; costCents: number; calls: number; inputTokens: number; outputTokens: number; cacheReadTokens: number; cacheWriteTokens: number; builderCredits?: number; estimatedBuilderCredits?: number; otherCostCents?: number; activeUsers: number; lastActiveAt: number | null; } export interface UsageDailyMetric { date: string; costCents: number; calls: number; tokens: number; builderCredits?: number; estimatedBuilderCredits?: number; otherCostCents?: number; otherCalls?: number; } export interface UsageRecentMetric { id: number; createdAt: number; ownerEmail: string; app: string; label: string; model: string; inputTokens: number; outputTokens: number; cacheReadTokens: number; cacheWriteTokens: number; costCents: number; builderCredits?: number; estimatedBuilderCredits?: number; otherCostCents?: number; engineName?: string | null; prompt: string | null; promptSource: "thread" | "thread-preview" | "not-captured" | "unavailable"; threadId: string | null; } export interface UsageAppOption { /** Normalized app key, as used by `byApp` and accepted as an app filter. */ key: string; calls: number; lastActiveAt: number | null; } /** Dimensions the daily usage history can be split by. */ export type UsageBreakdownDimension = "feature" | "app" | "model" | "surface"; /** Key of the series that folds every key past a breakdown's limit. */ export declare const USAGE_OTHER_BREAKDOWN_KEY = "other"; /** * One day of one breakdown key. Feature keys are `chat`, `sub-agents`, * `automations`, `integration:{platform}`, or `other`; surface keys are `app` * (used in the app itself) or the integration platform the call came from. */ export interface UsageDailyBreakdownRow { date: string; key: string; costCents: number; calls: number; tokens: number; builderCredits?: number; estimatedBuilderCredits?: number; otherCostCents?: number; } export interface UsageChatMetric { threadId: string; title: string | null; titleSource: "thread" | "thread-preview" | "not-captured" | "unavailable"; ownerEmail: string; /** Normalized app key, as in `byApp`. */ app: string; lastActiveAt: number; costCents: number; calls: number; builderCredits?: number; estimatedBuilderCredits?: number; otherCostCents?: number; } export interface UsageToolCallDay { date: string; /** Tool name, or `other` past the top tools. */ key: string; calls: number; } /** * Tool calls come from the agent trace spans, which have their own retention * window. "unavailable" means the traces could not be read, which is not the * same as a period with no tool calls. */ export type UsageToolCallMetrics = { status: "ok"; daily: UsageToolCallDay[]; } | { status: "unavailable"; }; export interface UsageUserOption { email: string; role: string | null; } export interface UsageMetricsAccess { viewerEmail: string; orgId: string | null; role: string | null; canViewWorkspace: boolean; totalUsers: number; } export interface AppUsageMetrics { billing: UsageBillingMode; /** "all" when every app is included; "app" when filtered to one app. */ appScope: "all" | "app"; app: string; /** Normalized key of the filtered app; null when every app is included. */ appKey: string | null; /** Normalized key of the app serving this request; null when unconfigured. */ currentAppKey: string | null; /** * Apps with usage for the selected people in the range, ignoring the app * filter, so a filter picker can list them while one app is selected. */ apps: UsageAppOption[]; viewScope: UsageMetricsScope; selectedUserEmail: string | null; availableUsers: UsageUserOption[]; sinceMs: number; sinceDays: number; generatedAt: number; access: UsageMetricsAccess; totals: { costCents: number; calls: number; inputTokens: number; outputTokens: number; cacheReadTokens: number; cacheWriteTokens: number; activeUsers: number; builderCredits?: number; estimatedBuilderCredits?: number; otherCostCents?: number; otherCalls?: number; }; currentDay: { costCents: number; credits: number; estimatedBuilderCredits?: number; otherCostCents?: number; otherCalls?: number; calls: number; tokens: number; }; byLabel: UsageMetricBucket[]; byModel: UsageMetricBucket[]; /** * Every app within the app filter, never truncated, so the per-app buckets * always sum to `totals`. */ byApp: UsageMetricBucket[]; /** * People by spend, keyed by lowercased email. Only for the organization * view (workspace scope with no one selected); empty otherwise. */ byUser: UsageMetricBucket[]; daily: UsageDailyMetric[]; /** The daily history split by each dimension; each day sums to `daily`. */ dailyBy: Record; topChats: UsageChatMetric[]; toolCalls: UsageToolCallMetrics; recent: UsageRecentMetric[]; } export interface UsageMetricsAccessInput { ownerEmail: string; orgId?: string | null; app: UsageAppSelection; } interface MemberRecord { email: string; role: string | null; } interface QueryScope { where: string; args: unknown[]; } export declare function numberField(row: Record, key: string): number; export declare function stringField(row: Record, key: string): string; export declare function normalizeUsageAppKey(value: string): string; export declare function usageAppScope(app: string): QueryScope; export declare function canViewWorkspaceUsage(input: Pick): Promise; export declare function resolveScope(input: UsageMetricsAccessInput, scope: UsageMetricsScope, requestedUserEmail?: string | null): Promise<{ ownerScope: QueryScope; /** The lowercased owner emails `ownerScope` selects. */ ownerEmails: string[]; /** The org predicate inside `ownerScope`, for tables with an `org_id`. */ orgScope: QueryScope; selectedUserEmail: string | null; members: MemberRecord[]; access: UsageMetricsAccess; }>; /** Each run's own prompt and the agent's reply to it, keyed by run id. */ export declare function loadRunExchanges(rows: Array>): Promise>; export declare function detectUsageEngineName(): Promise; export declare function listAppUsageMetrics(input: { sinceDays?: number; scope?: UsageMetricsScope; userEmail?: string | null; builderCreditsEnabled?: boolean; }, accessInput: UsageMetricsAccessInput): Promise; export {};