import mongoose from 'mongoose' const { Schema } = mongoose export type UsageKind = 'stt' | 'tts' | 'llm' export type UsageProvider = 'openai' | 'speaches' | 'piper' | 'cache' // Plain attribute shape (not extending mongoose.Document). Extending Document // collides on `model` (Document.model is a method); passing the attrs type to // the Schema/Model generics is the recommended pattern and still yields // hydrated documents with all Document methods from queries/create. export interface UsageEventAttrs { user?: mongoose.Types.ObjectId sessionId?: string kind: UsageKind provider: UsageProvider model: string endpoint: string /** Audio length for STT in seconds */ audioSeconds?: number /** Synthesized text length for TTS */ characters?: number inputTokens?: number outputTokens?: number /** Estimated cost in USD (0 for self-hosted providers and cache hits) */ costUsd: number createdAt: Date } const usageEventSchema = new mongoose.Schema({ user: { type: Schema.Types.ObjectId, ref: 'User', index: true }, sessionId: { type: String }, kind: { type: String, enum: ['stt', 'tts', 'llm'], required: true }, provider: { type: String, enum: ['openai', 'speaches', 'piper', 'cache'], required: true }, model: { type: String, required: true }, endpoint: { type: String, required: true }, audioSeconds: { type: Number }, characters: { type: Number }, inputTokens: { type: Number }, outputTokens: { type: Number }, costUsd: { type: Number, required: true, default: 0 }, createdAt: { type: Date, default: () => new Date(), index: true }, }) usageEventSchema.index({ user: 1, createdAt: -1 }) export const UsageEvent = (mongoose.models.UsageEvent as mongoose.Model | undefined) || mongoose.model('UsageEvent', usageEventSchema)