mission-control/src/lib/__tests__/task-costs.test.ts

71 lines
2.6 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { buildTaskCostReport, calculateStats, type TaskCostMetadata, type TokenCostRecord } from '@/lib/task-costs'
describe('task-cost analytics', () => {
it('calculates stats correctly', () => {
const stats = calculateStats([
{ model: 'a', agentName: 'alpha', timestamp: 1000, totalTokens: 100, cost: 0.1 },
{ model: 'b', agentName: 'alpha', timestamp: 2000, totalTokens: 300, cost: 0.3 },
])
expect(stats.totalTokens).toBe(400)
expect(stats.totalCost).toBeCloseTo(0.4)
expect(stats.requestCount).toBe(2)
expect(stats.avgTokensPerRequest).toBe(200)
expect(stats.avgCostPerRequest).toBeCloseTo(0.2)
})
it('builds task, agent, project and unattributed rollups', () => {
const records: TokenCostRecord[] = [
{ model: 'sonnet', agentName: 'alpha', timestamp: Date.parse('2026-03-05T01:00:00Z'), totalTokens: 100, cost: 0.1, taskId: 101 },
{ model: 'sonnet', agentName: 'alpha', timestamp: Date.parse('2026-03-05T02:00:00Z'), totalTokens: 150, cost: 0.15, taskId: 101 },
{ model: 'haiku', agentName: 'beta', timestamp: Date.parse('2026-03-05T03:00:00Z'), totalTokens: 50, cost: 0.02, taskId: 202 },
{ model: 'haiku', agentName: 'beta', timestamp: Date.parse('2026-03-05T03:30:00Z'), totalTokens: 75, cost: 0.03 },
]
const taskMetadata: Record<number, TaskCostMetadata> = {
101: {
id: 101,
title: 'Task One',
status: 'in_progress',
priority: 'high',
assigned_to: 'alpha',
project_id: 1,
project_name: 'Core',
project_slug: 'core',
project_prefix: 'CORE',
project_ticket_no: 12,
},
202: {
id: 202,
title: 'Task Two',
status: 'assigned',
priority: 'medium',
assigned_to: 'beta',
project_id: 2,
project_name: 'Ops',
project_slug: 'ops',
project_prefix: 'OPS',
project_ticket_no: 7,
},
}
const report = buildTaskCostReport(records, taskMetadata)
expect(report.tasks).toHaveLength(2)
expect(report.tasks[0]?.taskId).toBe(101)
expect(report.tasks[0]?.stats.totalCost).toBeCloseTo(0.25)
expect(report.tasks[0]?.project.ticketRef).toBe('CORE-012')
expect(report.agents.alpha?.stats.totalCost).toBeCloseTo(0.25)
expect(report.agents.alpha?.taskIds).toEqual([101])
expect(report.agents.beta?.taskIds).toEqual([202])
expect(report.projects['1']?.taskCount).toBe(1)
expect(report.projects['2']?.taskCount).toBe(1)
expect(report.summary.totalCost).toBeCloseTo(0.27)
expect(report.unattributed.totalCost).toBeCloseTo(0.03)
})
})