mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-06-27 19:05:48 +08:00
The previous `vue-tsc --noEmit` step was a no-op: the root tsconfig uses `files: []` with project references, so without `--build` it checks zero files and always passes. Switch to `vue-tsc --build` (new `yarn typecheck` script) and make the job blocking. Fix the one error this surfaced: UsageEventDocument extended mongoose.Document, whose `model` method collides with the `model: string` field. Use the recommended pattern — a plain attrs interface passed to the Schema/Model generics (hydrated docs still expose Document methods). Typecheck is now clean. Bump actions/checkout@v5 and actions/setup-node@v5 to silence the Node.js 20 runtime deprecation (forced to Node 24 from 2026-06-16). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
50 lines
1.8 KiB
TypeScript
50 lines
1.8 KiB
TypeScript
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<UsageEventAttrs>({
|
|
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<UsageEventAttrs> | undefined) ||
|
|
mongoose.model<UsageEventAttrs>('UsageEvent', usageEventSchema)
|