🏁 Final commit: Project Token Usage Viewer completed

This commit is contained in:
2026-01-21 14:21:43 +08:00
parent b967deb4b1
commit a77fcdd3dc
24 changed files with 1087 additions and 651 deletions

View File

@@ -0,0 +1,84 @@
/**
* Token 使用量处理器
*
* 从远程 API 获取数据,筛选 Opus/Thinking 模型,并存储历史记录
*/
import { usageHistoryTable } from '@/db/schema'
import { env } from '@/env'
import { dbProvider } from '@/orpc/middlewares'
import { os } from '@/orpc/server'
/** 远程 API 响应中的模型数据结构 */
interface RemoteModelData {
model: string
displayName?: string
remainingFraction: number
resetTime?: string
}
/** 远程 API 响应结构 */
interface RemoteResponse {
result: Record<string, RemoteModelData[]>
}
export const getUsage = os.usage.getUsage
.use(dbProvider)
.handler(async ({ context }) => {
// 1. 获取远程数据
const response = await fetch(env.TOKEN_USAGE_URL)
if (!response.ok) {
throw new Error(`Failed to fetch usage data: ${response.statusText}`)
}
const data = (await response.json()) as RemoteResponse
// 2. 解析并筛选每个账户的 claude-opus-4-5-thinking 模型
const opusModels: Array<{
account: string
model: string
displayName?: string
remainingFraction: number
resetTime?: string
}> = []
for (const [accountFile, models] of Object.entries(data.result)) {
const account = accountFile.replace('.json', '')
// 只找 claude-opus-4-5-thinking 模型
const opusModel = models.find(
(m) => m.model === 'claude-opus-4-5-thinking',
)
if (opusModel) {
opusModels.push({
account,
model: opusModel.model,
displayName: opusModel.displayName,
remainingFraction: opusModel.remainingFraction,
resetTime: opusModel.resetTime,
})
}
}
// 3. 存储到历史表(仅在 Bun 环境下工作)
try {
if (opusModels.length > 0 && context.db) {
await context.db.insert(usageHistoryTable).values(
opusModels.map((m) => ({
account: m.account,
model: m.model,
displayName: m.displayName,
remainingFraction: m.remainingFraction,
resetTime: m.resetTime,
})),
)
}
} catch (err) {
// 在非 Bun 环境下,数据库可能不可用,忽略错误
console.warn('Database insert skipped:', err)
}
return {
opusModels,
fetchedAt: new Date().toISOString(),
}
})