From d9e7bce9a27c7dcf01881e6d6e9ddc6b38a7e5a2 Mon Sep 17 00:00:00 2001 From: indifferentketchup Date: Sun, 7 Jun 2026 17:57:11 +0000 Subject: [PATCH] feat(contracts): add TokenBreakdownSchema and ContestantShape.token_breakdown --- packages/contracts/src/arena.ts | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/packages/contracts/src/arena.ts b/packages/contracts/src/arena.ts index 9855e55..531fc09 100644 --- a/packages/contracts/src/arena.ts +++ b/packages/contracts/src/arena.ts @@ -1,10 +1,23 @@ /** Arena types — single source of truth for cross-app Arena wire contracts. */ +import { z } from 'zod'; + export type BattleType = 'coding' | 'qa'; export type BattleStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'; export type ContestantStatus = 'queued' | 'running' | 'done' | 'error'; export type ContestantLane = 'local' | 'cloud'; +export const TokenBreakdownSchema = z.object({ + system: z.number().int().nonnegative(), + user: z.number().int().nonnegative(), + assistant: z.number().int().nonnegative(), + tools: z.number().int().nonnegative(), + reasoning: z.number().int().nonnegative(), + total: z.number().int().nonnegative(), +}); + +export type TokenBreakdown = z.infer; + // Pane state — carried on the WorkspacePane row, mirrors OrchestratorState. export interface ArenaState { battle_id: string; @@ -38,6 +51,7 @@ export interface ContestantShape { duration_ms: number | null; tokens_per_sec: number | null; cost_tokens: number | null; + token_breakdown: TokenBreakdown | null; result_path: string | null; error: string | null; created_at: string;