@mauricode/token-derby 2.4.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/commands/stable-create.ts","../src/ui/HorseCreator.tsx","../src/ui/HorseSprite.tsx","../src/ui/sprite.ts","../src/ui/sprite-render.ts","../src/ui/palette.ts","../src/config.ts","../src/version.ts","../../shared/src/constants.ts","../../shared/src/version-match.ts","../../shared/src/levels.ts","../../shared/src/midrace.ts","../src/identity/identity.ts","../src/paths.ts","../src/api/client.ts","../src/api/endpoints.ts","../src/commands/stable-list.tsx","../src/commands/stable-delete.ts","../src/commands/stable-edit.ts","../src/commands/create.ts","../src/commands/join.ts","../src/ui/HorsePicker.tsx","../src/stable/active-race.ts","../src/runtime/run-race.tsx","../src/ui/StatusScreen.tsx","../src/runtime/heartbeat-loop.ts","../src/tokens/transcripts.ts","../src/tokens/baseline.ts","../src/commands/end.ts","../src/commands/init.ts","../src/commands/update.ts","../src/commands/org-create.ts","../src/commands/org-join.ts","../src/commands/org-list.ts","../src/commands/org-info.ts","../src/commands/org-webhook-set.ts","../src/commands/org-webhook-get.ts","../src/commands/org-webhook-clear.ts","../src/bin.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport { HorseCreator } from '../ui/HorseCreator.js';\nimport { createStableHorse } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function stableCreateCommand(): Promise<number> {\n let exitCode = 0;\n const app = render(\n React.createElement(HorseCreator, {\n onSubmit: async (name, colors) => {\n try {\n await createStableHorse({ name, colors });\n app.unmount();\n console.log(`✓ Saved \"${name}\" to your stable.`);\n } catch (e) {\n app.unmount();\n if (e instanceof ApiError) {\n if (e.code === 'STABLE_HORSE_NAME_TAKEN') {\n console.error(`A horse named \"${name}\" already exists. Pick a different name or use \\`token-derby stable edit ${name}\\` to modify it.`);\n } else {\n console.error(`Error: ${e.code} ${e.message}`);\n }\n exitCode = 1;\n return;\n }\n throw e;\n }\n },\n onCancel: () => {\n app.unmount();\n console.log('Cancelled.');\n exitCode = 1;\n },\n }),\n );\n await app.waitUntilExit();\n return exitCode;\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport type { HorseColors } from '@token-derby/shared';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MAIN_SPRITE } from './sprite.js';\nimport { SLOTS, PALETTES, nextColor, prevColor, defaultColors, type Slot } from './palette.js';\n\ntype Props = {\n onSubmit: (name: string, colors: HorseColors) => void;\n onCancel: () => void;\n initialColors?: HorseColors;\n initialName?: string;\n lockName?: boolean;\n initialLevel?: number;\n};\n\nexport function HorseCreator({ onSubmit, onCancel, initialColors, initialName, lockName, initialLevel }: Props) {\n const [colors, setColors] = useState<HorseColors>(initialColors ?? defaultColors());\n const [slotIdx, setSlotIdx] = useState(0);\n const [namingMode, setNamingMode] = useState(false);\n const [name, setName] = useState(initialName ?? '');\n const [error, setError] = useState<string | null>(null);\n\n const slot: Slot = SLOTS[slotIdx]!;\n\n useInput((input, key) => {\n if (namingMode) return;\n if (key.escape) { onCancel(); return; }\n if (key.upArrow) { setSlotIdx((slotIdx - 1 + SLOTS.length) % SLOTS.length); return; }\n if (key.downArrow) { setSlotIdx((slotIdx + 1) % SLOTS.length); return; }\n if (key.leftArrow) { setColors({ ...colors, [slot]: prevColor(slot, colors[slot]) }); return; }\n if (key.rightArrow) { setColors({ ...colors, [slot]: nextColor(slot, colors[slot]) }); return; }\n if (key.return) {\n if (lockName) { onSubmit(initialName ?? '', colors); return; }\n setNamingMode(true);\n return;\n }\n });\n\n const handleNameSubmit = (value: string) => {\n if (!value.trim()) {\n setError('Name required');\n return;\n }\n onSubmit(value.trim(), colors);\n };\n\n return (\n <Box flexDirection=\"column\">\n {lockName && initialName && (\n <Box marginBottom={1}>\n <Text bold>{initialName}</Text>\n {typeof initialLevel === 'number' && (\n <Text color=\"cyan\"> [Lvl. {initialLevel}]</Text>\n )}\n </Box>\n )}\n\n <Box marginBottom={1}>\n <HorseSprite sprite={MAIN_SPRITE} colors={colors} />\n </Box>\n\n <Box flexDirection=\"column\">\n {SLOTS.map((s, i) => (\n <Text key={s}>\n {i === slotIdx ? '►' : ' '} {s.padEnd(7)} <Text color={colors[s]}>██</Text> {colors[s]}\n </Text>\n ))}\n </Box>\n\n {!namingMode && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>↑/↓ select slot · ←/→ cycle color · Enter accept · Esc cancel</Text>\n </Box>\n )}\n\n {namingMode && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text>Name your horse: </Text>\n <TextInput value={name} onChange={(v) => { setName(v); setError(null); }} onSubmit={handleNameSubmit} />\n {error && <Text color=\"red\">{error}</Text>}\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { HorseColors } from '@token-derby/shared';\nimport { renderSprite, type Cell } from './sprite-render.js';\nimport type { SlotTag } from './sprite.js';\n\ntype Props = {\n sprite: readonly (readonly SlotTag[])[];\n colors: HorseColors;\n};\n\nexport function HorseSprite({ sprite, colors }: Props) {\n const grid = renderSprite(sprite, colors);\n return (\n <Box flexDirection=\"column\">\n {grid.map((row, y) => (\n <Text key={y}>{rowToAnsi(row)}</Text>\n ))}\n </Box>\n );\n}\n\nfunction rowToAnsi(row: Cell[]): string {\n let out = '';\n for (const cell of row) {\n if (cell.top === null && cell.bottom === null) {\n out += ' ';\n } else if (cell.top !== null && cell.bottom !== null) {\n out += ansiFg(cell.top) + ansiBg(cell.bottom) + '▀' + RESET;\n } else if (cell.top !== null) {\n out += ansiFg(cell.top) + '▀' + RESET;\n } else {\n out += ansiFg(cell.bottom!) + '▄' + RESET;\n }\n }\n return out;\n}\n\nconst RESET = '\\x1b[0m';\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const h = hex.replace('#', '');\n return [\n parseInt(h.slice(0, 2), 16),\n parseInt(h.slice(2, 4), 16),\n parseInt(h.slice(4, 6), 16),\n ];\n}\n\nfunction ansiFg(hex: string): string {\n const [r, g, b] = hexToRgb(hex);\n return `\\x1b[38;2;${r};${g};${b}m`;\n}\n\nfunction ansiBg(hex: string): string {\n const [r, g, b] = hexToRgb(hex);\n return `\\x1b[48;2;${r};${g};${b}m`;\n}\n","// Pixel slot tags. `null` = transparent.\n// B = body, M = mane, T = tail, S = saddle, E = eye (fixed black), H = hoof (fixed dark)\nexport type SlotTag = 'B' | 'M' | 'T' | 'S' | 'E' | 'H' | null;\n\nexport const FIXED_COLORS = {\n E: '#000000',\n H: '#1F1108',\n} as const;\n\n// Each pair of adjacent rows is intentionally identical so every half-block\n// cell renders as a solid color. The only intentional split is the last row\n// (legs/hooves transition).\nconst MAIN_ROWS: readonly string[] = [\n '................................',\n '................................',\n '..........................MMM...',\n '..........................MMM...',\n '.........................MBBEBB.',\n '.........................MBBEBB.',\n '........................MBBBBBBB',\n '........................MBBBBBBB',\n '..................MMMMMMMBBB....',\n '..................MMMMMMMBBB....',\n '....BBBBBBBBSSSSSSMMBBBBBB......',\n '...BBBBBBBBBSSSSSSMMBBBBBB......',\n '.TTBBBBBBBBBSSSSSSBBBBBBBB......',\n '.TTBBBBBBBBBSSSSSSBBBBBBBB......',\n 'TTTBBBBBBBBBBBBBBBBBBBBBBB......',\n 'TTTBBBBBBBBBBBBBBBBBBBBB........',\n '...BBB.BBB.....BBB.BBB..........',\n '...BBB.BBB.....BBB.BBB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '...HHH.HHH.....HHH.HHH..........',\n];\n\nconst MINI_ROWS: readonly string[] = [\n '.BBSSMBB',\n '.BBSSMBB',\n 'TBBBBBB.',\n 'THH..HH.',\n];\n\nexport const MAIN_SPRITE: readonly (readonly SlotTag[])[] = parse(MAIN_ROWS, 32, 24);\nexport const MINI_SPRITE: readonly (readonly SlotTag[])[] = parse(MINI_ROWS, 8, 4);\n\nfunction parse(rows: readonly string[], width: number, height: number): SlotTag[][] {\n if (rows.length !== height) {\n throw new Error(`sprite has ${rows.length} rows, expected ${height}`);\n }\n return rows.map((row, y) => {\n if (row.length !== width) {\n throw new Error(`sprite row ${y} has length ${row.length}, expected ${width}`);\n }\n return [...row].map(c => toTag(c));\n });\n}\n\nfunction toTag(c: string): SlotTag {\n switch (c) {\n case 'B': return 'B';\n case 'M': return 'M';\n case 'T': return 'T';\n case 'S': return 'S';\n case 'E': return 'E';\n case 'H': return 'H';\n case '.': return null;\n default: throw new Error(`unknown sprite char: ${c}`);\n }\n}\n","import type { HorseColors } from '@token-derby/shared';\nimport { FIXED_COLORS, type SlotTag } from './sprite.js';\n\nexport type Cell = {\n top: string | null;\n bottom: string | null;\n};\n\nexport function renderSprite(\n sprite: readonly (readonly SlotTag[])[],\n colors: HorseColors,\n): Cell[][] {\n const out: Cell[][] = [];\n for (let y = 0; y + 1 < sprite.length || y < sprite.length; y += 2) {\n const topRow = sprite[y];\n const bottomRow = sprite[y + 1];\n if (!topRow) break;\n const row: Cell[] = [];\n for (let x = 0; x < topRow.length; x++) {\n row.push({\n top: tagColor(topRow[x] ?? null, colors),\n bottom: tagColor(bottomRow?.[x] ?? null, colors),\n });\n }\n out.push(row);\n if (!bottomRow) break;\n }\n return out;\n}\n\nfunction tagColor(tag: SlotTag, colors: HorseColors): string | null {\n if (tag === null) return null;\n if (tag === 'E') return FIXED_COLORS.E;\n if (tag === 'H') return FIXED_COLORS.H;\n if (tag === 'B') return colors.body;\n if (tag === 'M') return colors.mane;\n if (tag === 'T') return colors.tail;\n if (tag === 'S') return colors.saddle;\n return null;\n}\n","import type { HorseColors } from '@token-derby/shared';\n\nexport type Slot = keyof HorseColors;\n\nexport const SLOTS: readonly Slot[] = ['body', 'mane', 'tail', 'saddle'] as const;\n\nexport const PALETTES: Record<Slot, readonly string[]> = {\n body: [\n '#8B4513', '#A0522D', '#D2691E', '#CD853F', '#DEB887', '#F5DEB3',\n '#FFFFFF', '#000000', '#4A2C2A', '#5D3A1A', '#704214', '#9C5919',\n '#B87333', '#E5B783', '#F0E1C9', '#2F1B0C',\n ],\n mane: [\n '#000000', '#1C1C1C', '#2F1B0C', '#4A2C2A', '#5D3A1A', '#8B4513',\n '#FFFFFF', '#F5F5DC', '#DEB887', '#CD853F', '#FF4500', '#B22222',\n '#191970', '#4B0082', '#2E8B57', '#FFD700',\n ],\n tail: [\n '#000000', '#1C1C1C', '#2F1B0C', '#4A2C2A', '#5D3A1A', '#8B4513',\n '#FFFFFF', '#F5F5DC', '#DEB887', '#CD853F', '#FF4500', '#B22222',\n '#191970', '#4B0082', '#2E8B57', '#FFD700',\n ],\n saddle: [\n '#C0392B', '#922B21', '#7B241C', '#641E16', '#1F618D', '#21618C',\n '#1B4F72', '#0E6655', '#117A65', '#196F3D', '#7D6608', '#9A7D0A',\n '#6E2C00', '#4D5656', '#212F3D', '#000000',\n ],\n};\n\nexport function nextColor(slot: Slot, current: string): string {\n const palette = PALETTES[slot];\n const idx = palette.indexOf(current);\n return palette[(idx + 1 + palette.length) % palette.length] ?? palette[0]!;\n}\n\nexport function prevColor(slot: Slot, current: string): string {\n const palette = PALETTES[slot];\n const idx = palette.indexOf(current);\n if (idx < 0) return palette[0]!;\n return palette[(idx - 1 + palette.length) % palette.length]!;\n}\n\nexport function defaultColors(): HorseColors {\n return {\n body: PALETTES.body[0]!,\n mane: PALETTES.mane[0]!,\n tail: PALETTES.tail[0]!,\n saddle: PALETTES.saddle[0]!,\n };\n}\n","export const DEFAULT_API_BASE = 'https://token-derby.mauricode.co.uk/api';\n\nexport function apiBase(): string {\n return process.env.TOKEN_DERBY_API_BASE ?? DEFAULT_API_BASE;\n}\n\nexport const HEARTBEAT_INTERVAL_MS = 60_000;\nexport const HEARTBEAT_RETRY_DELAYS_MS = [1_000, 2_000, 4_000, 8_000, 15_000];\n","import { createRequire } from 'node:module';\n\ndeclare const __CLI_VERSION__: string | undefined;\n\nfunction readVersion(): string {\n if (typeof __CLI_VERSION__ === 'string' && __CLI_VERSION__.length > 0) {\n return __CLI_VERSION__;\n }\n try {\n const req = createRequire(import.meta.url);\n const pkg = req('../package.json') as { version?: string };\n if (typeof pkg.version === 'string') return pkg.version;\n } catch {\n // fall through\n }\n return '0.0.0-dev';\n}\n\nexport const CLI_VERSION: string = readVersion();\n","export const DEFAULT_MAX_PARTICIPANTS = 30;\nexport const JOIN_CODE_LENGTH = 6;\nexport const JOIN_CODE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\nexport const CLI_VERSION_HEADER = 'x-cli-version';\nexport const USER_ID_HEADER = 'x-user-id';\nexport const USER_NAME_HEADER = 'x-user-name';\nexport const USER_TOKEN_HEADER = 'x-user-token';\nexport const USER_NAME_MAX_LENGTH = 40;\nexport const SECRET_TOKEN_BYTES = 32;\nexport const ORG_NAME_MAX_LENGTH = 12;\nexport const ORG_NAME_PATTERN = /^[A-Za-z0-9]{1,12}$/;\n","export type ParsedSemver = { major: number; minor: number; patch: number };\n\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:[-+].*)?$/;\n\nexport function parseSemver(v: string | undefined | null): ParsedSemver | null {\n if (typeof v !== 'string') return null;\n const m = SEMVER_RE.exec(v.trim());\n if (!m) return null;\n return {\n major: Number(m[1]),\n minor: Number(m[2]),\n patch: Number(m[3]),\n };\n}\n\nexport function minorMatches(a: string | undefined | null, b: string | undefined | null): boolean {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return false;\n return pa.major === pb.major && pa.minor === pb.minor;\n}\n\n/**\n * Returns true when `a` is the same as or newer than `b` by semver MAJOR.MINOR.PATCH.\n * Returns false if either side is unparseable.\n */\nexport function gteSemver(a: string | undefined | null, b: string | undefined | null): boolean {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return false;\n if (pa.major !== pb.major) return pa.major > pb.major;\n if (pa.minor !== pb.minor) return pa.minor > pb.minor;\n return pa.patch >= pb.patch;\n}\n","/**\n * Horse XP / level curve.\n *\n * The cost (in XP) to advance from level `n` to level `n+1` is given by:\n *\n * xpForLevel(n) = 1.8 n^3 + 18 n^2 + 50 n − 19.8\n *\n * So the cumulative XP at which a horse becomes each level is:\n *\n * Level 1 → 0 (every new horse starts here at 0 XP)\n * Level 2 → xpForLevel(1) = 50\n * Level 3 → xpForLevel(2) = 166.6\n * Level 4 → xpForLevel(3) = 340.8\n * ...\n * Level 30 → xpForLevel(29) = 60,468.4\n *\n * To redesign the curve, edit `xpForLevel` below or bump `MAX_LEVEL`.\n * Levels are derived from XP — they are not stored on the horse, so changing\n * this file re-levels every horse without needing a migration.\n */\n\nexport const MAX_LEVEL = 30;\n\nexport function xpForLevel(n: number): number {\n return 1.8 * n ** 3 + 18 * n ** 2 + 50 * n - 19.8;\n}\n\n/**\n * Cumulative XP at which a horse first becomes `level`. Level 1 is the\n * starting state, so its threshold is 0.\n */\nexport function thresholdForLevel(level: number): number {\n if (level <= 1) return 0;\n return Math.round(xpForLevel(level - 1));\n}\n\n/**\n * Convenience: total XP thresholds for each level, in order.\n * `XP_THRESHOLDS[i]` is the cumulative XP needed to be level `i+1`.\n */\nexport const XP_THRESHOLDS: readonly number[] = Array.from(\n { length: MAX_LEVEL },\n (_, i) => thresholdForLevel(i + 1),\n);\n\nexport type LevelInfo = {\n level: number;\n xp: number;\n level_start_xp: number;\n next_level_xp: number | null;\n xp_into_level: number;\n xp_for_level: number | null;\n progress: number;\n};\n\nexport function levelFromXp(xp: number): number {\n const v = Math.max(0, Math.floor(xp));\n let level = 1;\n while (level < MAX_LEVEL && v >= thresholdForLevel(level + 1)) {\n level++;\n }\n return level;\n}\n\nexport function levelInfo(xp: number): LevelInfo {\n const v = Math.max(0, Math.floor(xp));\n const level = levelFromXp(v);\n const level_start_xp = thresholdForLevel(level);\n const isMax = level >= MAX_LEVEL;\n const next_level_xp = isMax ? null : thresholdForLevel(level + 1);\n const xp_into_level = v - level_start_xp;\n const xp_for_level = isMax ? null : (next_level_xp! - level_start_xp);\n const progress = isMax ? 1 : Math.min(1, xp_into_level / Math.max(1, xp_for_level!));\n return { level, xp: v, level_start_xp, next_level_xp, xp_into_level, xp_for_level, progress };\n}\n\n/**\n * XP awarded for finishing a race. Components stack:\n * compete → every horse that joined gets this\n * podium → top 3 finishers\n * runner_up → 2nd place\n * winner → 1st place\n *\n * So a winner gets compete + podium + winner = 80 XP.\n * Edit these values to retune.\n */\nexport const XP_AWARDS = {\n compete: 25,\n podium: 25,\n runner_up: 15,\n winner: 30,\n token_bonus_max: 15,\n} as const;\n\nexport function xpForRaceResult(rank: number): number {\n let xp = XP_AWARDS.compete;\n if (rank <= 3) xp += XP_AWARDS.podium;\n if (rank === 2) xp += XP_AWARDS.runner_up;\n if (rank === 1) xp += XP_AWARDS.winner;\n return xp;\n}\n\n/**\n * Token-proportional XP bonus, layered on top of {@link xpForRaceResult}.\n * Winner always gets the full `token_bonus_max` (15).\n * Everyone else gets `round(tokens / winner_tokens * token_bonus_max)`.\n * Falls back to 0 if `winner_tokens` is non-positive (degenerate race).\n */\nexport function xpForTokenBonus(rank: number, tokens: number, winner_tokens: number): number {\n if (rank === 1) return XP_AWARDS.token_bonus_max;\n if (winner_tokens <= 0) return 0;\n const ratio = Math.max(0, tokens) / winner_tokens;\n return Math.round(Math.min(1, ratio) * XP_AWARDS.token_bonus_max);\n}\n\n// Total XP a horse earns from a finished race: rank bonus + token bonus + any\n// live XP it already banked during the race.\nexport function xpForRaceFinish(\n rank: number,\n tokens: number,\n winner_tokens: number,\n live_xp: number | undefined = 0,\n): number {\n return xpForRaceResult(rank) + xpForTokenBonus(rank, tokens, winner_tokens) + (live_xp ?? 0);\n}\n","export const ACHIEVEMENT_NAMES = [\n 'Racer!',\n 'Overtake!',\n 'Pacesetter!',\n 'Stampede!',\n 'Took the lead!',\n 'Comeback!',\n 'Pulled Away!',\n] as const;\n\nexport type AchievementName = typeof ACHIEVEMENT_NAMES[number];\n\nexport const ACHIEVEMENT_DESCRIPTIONS: Record<AchievementName, string> = {\n 'Racer!': 'Raced continuously for an hour',\n 'Overtake!': 'Overtook another horse',\n 'Pacesetter!': 'Led the race for an hour straight',\n 'Stampede!': 'Gained 7,000+ tokens in a single minute',\n 'Took the lead!': 'Charged into first place',\n 'Comeback!': 'Climbed from last place to the top half',\n 'Pulled Away!': 'Grew the lead by 5,000+ tokens in a minute',\n};\n\n// Describe an Overtake! event with multi-position climb.\nexport function overtakeDescription(positionsClimbed: number): string {\n if (positionsClimbed <= 1) return 'Overtook another horse';\n return `Overtook ${positionsClimbed} horses`;\n}\n\n// Multiplier applied to token thresholds (Stampede!, Pulled Away!, rate cap)\n// when a race counts input+output. Calibrated against real Claude Code\n// transcripts: with cache_read_input_tokens excluded (they're passive,\n// reflect context size rather than work), the aggregate ratio of\n// (fresh_input + cache_creation + output) / output is ~8x. Set to 10 so the\n// rate cap clears all but the busiest peak minutes (~p90).\nexport const TOKEN_INPUT_MULTIPLIER = 10;\n\nexport function tokenMultiplier(race: { counts_input?: boolean }): number {\n return race.counts_input ? TOKEN_INPUT_MULTIPLIER : 1;\n}\n\n// Race-aware description for an event. Stampede!/Pulled Away! report their\n// scaled thresholds for input+output races; everything else is static.\nexport function describeAchievement(\n event: { name: AchievementName; xp: number },\n race: { counts_input?: boolean },\n): string {\n if (event.name === 'Overtake!') {\n return overtakeDescription(Math.floor(event.xp / 3));\n }\n const m = tokenMultiplier(race);\n if (event.name === 'Stampede!') {\n return `Gained ${(MIDRACE_THRESHOLDS.stampede_tokens * m).toLocaleString('en-US')}+ tokens in a single minute`;\n }\n if (event.name === 'Pulled Away!') {\n return `Grew the lead by ${(MIDRACE_THRESHOLDS.pulled_away_gap * m).toLocaleString('en-US')}+ tokens in a minute`;\n }\n return ACHIEVEMENT_DESCRIPTIONS[event.name];\n}\n\nexport const MIDRACE_XP = {\n racer: 1,\n overtake: 3,\n pacesetter: 3,\n stampede: 2,\n took_lead: 5,\n comeback: 5,\n pulled_away: 3,\n} as const;\n\nexport const MIDRACE_CAPS = {\n racer_awards: 5,\n overtake_awards: 5,\n pacesetter_awards: 3,\n lead_take_awards: 3,\n // Stampede! and Pulled Away! are cooldown-based, not per-race-capped.\n // Comeback! is tracked as a boolean (comeback_awarded) — not a counter.\n} as const;\n\nexport const MIDRACE_THRESHOLDS = {\n warm_up_fraction: 0.08, // first 8% of race time\n streak_hour_ms: 3_600_000, // 1 hour for Racer!/Pacesetter!\n racer_dt_cap_ms: 90_000, // single-tick credit cap for Racer!\n stampede_tokens: 7_000, // tokens-in-a-minute threshold\n stampede_cooldown_ms: 7_200_000, // 2 hours\n pulled_away_gap: 5_000, // gap-growth threshold per minute\n pulled_away_cooldown_ms: 7_200_000, // 2 hours\n recent_events_retention_ms: 90_000, // sliding window for recent_events\n} as const;\n\nexport type RecentEvent = {\n at: number;\n name: AchievementName;\n xp: number;\n};\n","import { promises as fs } from 'node:fs';\nimport * as path from 'node:path';\nimport { USER_NAME_MAX_LENGTH } from '@token-derby/shared';\nimport { identityFile, homeDir } from '../paths.js';\n\nexport type Identity = {\n user_id: string;\n display_name: string;\n secret_token: string;\n created_at: string;\n};\n\nexport async function loadIdentity(): Promise<Identity | null> {\n try {\n const raw = await fs.readFile(identityFile(), 'utf8');\n const parsed = JSON.parse(raw) as Partial<Identity>;\n if (\n typeof parsed.user_id === 'string' &&\n typeof parsed.display_name === 'string' &&\n typeof parsed.secret_token === 'string' &&\n typeof parsed.created_at === 'string'\n ) {\n return parsed as Identity;\n }\n return null;\n } catch (e: any) {\n if (e?.code === 'ENOENT') return null;\n return null;\n }\n}\n\nexport async function saveIdentity(identity: Identity): Promise<void> {\n await fs.mkdir(homeDir(), { recursive: true });\n await fs.writeFile(identityFile(), JSON.stringify(identity, null, 2) + '\\n', 'utf8');\n}\n\nexport async function deleteIdentity(): Promise<void> {\n try {\n await fs.unlink(identityFile());\n } catch (e: any) {\n if (e?.code !== 'ENOENT') throw e;\n }\n}\n\nexport function validateDisplayName(name: string): { ok: true; name: string } | { ok: false; error: string } {\n const trimmed = name.trim();\n if (trimmed.length < 1) return { ok: false, error: 'Name cannot be empty.' };\n if (trimmed.length > USER_NAME_MAX_LENGTH) {\n return { ok: false, error: `Name must be ${USER_NAME_MAX_LENGTH} characters or fewer.` };\n }\n return { ok: true, name: trimmed };\n}\n\nexport function identityFilePath(): string {\n return identityFile();\n}\n\nexport function identityFileDir(): string {\n return path.dirname(identityFile());\n}\n","import * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport function homeDir(): string {\n return process.env.TOKEN_DERBY_HOME ?? path.join(os.homedir(), '.token-derby');\n}\n\nexport function identityFile(): string {\n return path.join(homeDir(), 'identity.json');\n}\n\nexport function activeRaceFile(joinCode: string): string {\n return path.join(homeDir(), 'active-races', `${joinCode}.json`);\n}\n\nexport function activeRacesDir(): string {\n return path.join(homeDir(), 'active-races');\n}\n\nexport function claudeProjectsDir(): string {\n return process.env.TOKEN_DERBY_CLAUDE_DIR ?? path.join(os.homedir(), '.claude', 'projects');\n}\n","import { apiBase } from '../config.js';\nimport { CLI_VERSION } from '../version.js';\nimport { CLI_VERSION_HEADER, USER_ID_HEADER, USER_TOKEN_HEADER } from '@token-derby/shared';\nimport { loadIdentity, type Identity } from '../identity/identity.js';\n\nexport type ApiErrorCode =\n | 'RACE_NOT_FOUND'\n | 'RACE_FULL'\n | 'RACE_FINISHED'\n | 'INVALID_TOKEN'\n | 'RATE_LIMITED'\n | 'BAD_REQUEST'\n | 'VERSION_MISMATCH'\n | 'IDENTITY_REQUIRED'\n | 'DUPLICATE_HORSE'\n | 'ORG_NAME_TAKEN'\n | 'ORG_NOT_FOUND'\n | 'NOT_ORG_MEMBER'\n | 'UNAUTHENTICATED'\n | 'STABLE_HORSE_NOT_FOUND'\n | 'STABLE_HORSE_NAME_TAKEN'\n | 'NETWORK_ERROR';\n\nexport class ApiError extends Error {\n constructor(\n readonly code: ApiErrorCode,\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ntype FetchFn = typeof fetch;\n\nlet identityCache: Promise<Identity | null> | null = null;\nfunction getIdentity(): Promise<Identity | null> {\n if (!identityCache) identityCache = loadIdentity();\n return identityCache;\n}\n\n// Tests can reset the cached identity.\nexport function _resetIdentityCacheForTests(): void {\n identityCache = null;\n}\n\nexport async function request<T>(\n method: string,\n path: string,\n body: unknown,\n horseAuthToken: string | undefined,\n fetchImpl: FetchFn = fetch,\n): Promise<T> {\n const url = path.startsWith('http') ? path : `${apiBase()}${path}`;\n const headers: Record<string, string> = {};\n headers[CLI_VERSION_HEADER] = CLI_VERSION;\n headers['user-agent'] = `token-derby/${CLI_VERSION}`;\n const identity = await getIdentity();\n if (identity) {\n headers[USER_ID_HEADER] = identity.user_id;\n headers[USER_TOKEN_HEADER] = identity.secret_token;\n }\n if (horseAuthToken) headers['authorization'] = `Bearer ${horseAuthToken}`;\n if (body !== undefined) headers['content-type'] = 'application/json';\n\n let res: Awaited<ReturnType<FetchFn>>;\n try {\n res = await fetchImpl(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n } catch (e: any) {\n throw new ApiError('NETWORK_ERROR', e?.message ?? 'fetch failed', 0);\n }\n\n const text = await res.text();\n const contentType = res.headers.get('content-type') ?? '';\n let parsed: any = null;\n if (contentType.includes('application/json') && text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = null;\n }\n }\n\n if (!res.ok) {\n if (parsed && typeof parsed.code === 'string') {\n throw new ApiError(parsed.code as ApiErrorCode, parsed.message ?? 'API error', res.status);\n }\n throw new ApiError('NETWORK_ERROR', `HTTP ${res.status}`, res.status);\n }\n\n return parsed as T;\n}\n","import type {\n CreateRaceRequest, CreateRaceResponse,\n GetRaceResponse, JoinRaceRequest, JoinRaceResponse,\n HeartbeatRequest, HeartbeatResponse, EndRaceResponse,\n CreateOrganisationRequest, CreateOrganisationResponse,\n JoinOrganisationRequest, JoinOrganisationResponse,\n ListOrganisationsResponse, GetOrganisationResponse,\n InitJockeyRequest, InitJockeyResponse,\n GetJockeyResponse, UpdateJockeyRequest, UpdateJockeyResponse,\n ListStableResponse, CreateStableHorseRequest, CreateStableHorseResponse,\n UpdateStableHorseRequest, UpdateStableHorseResponse, DeleteStableHorseResponse,\n SetOrgWebhookRequest, SetOrgWebhookResponse,\n GetOrgWebhookResponse, DeleteOrgWebhookResponse,\n} from '@token-derby/shared';\nimport { request } from './client.js';\n\nexport function createRace(body: CreateRaceRequest) {\n return request<CreateRaceResponse>('POST', '/races', body, undefined);\n}\n\nexport function getRace(joinCode: string) {\n return request<GetRaceResponse>('GET', `/races/${encodeURIComponent(joinCode)}`, undefined, undefined);\n}\n\nexport function joinRace(joinCode: string, body: JoinRaceRequest) {\n return request<JoinRaceResponse>('POST', `/races/${encodeURIComponent(joinCode)}/join`, body, undefined);\n}\n\nexport function heartbeat(joinCode: string, horseId: string, token: string, body: HeartbeatRequest) {\n return request<HeartbeatResponse>(\n 'POST',\n `/races/${encodeURIComponent(joinCode)}/horses/${encodeURIComponent(horseId)}/heartbeat`,\n body,\n token,\n );\n}\n\nexport function endRace(adminCode: string) {\n return request<EndRaceResponse>('DELETE', `/races/admin/${encodeURIComponent(adminCode)}`, undefined, undefined);\n}\n\nexport function createOrganisation(body: CreateOrganisationRequest) {\n return request<CreateOrganisationResponse>('POST', '/organisations', body, undefined);\n}\n\nexport function joinOrganisation(body: JoinOrganisationRequest) {\n return request<JoinOrganisationResponse>('POST', '/organisations/join', body, undefined);\n}\n\nexport function listOrganisations() {\n return request<ListOrganisationsResponse>('GET', '/organisations', undefined, undefined);\n}\n\nexport function getOrganisation(name: string) {\n return request<GetOrganisationResponse>('GET', `/organisations/${encodeURIComponent(name)}`, undefined, undefined);\n}\n\nexport function initJockey(body: InitJockeyRequest) {\n return request<InitJockeyResponse>('POST', '/jockey/init', body, undefined);\n}\n\nexport function getJockey() {\n return request<GetJockeyResponse>('GET', '/jockey/me', undefined, undefined);\n}\n\nexport function updateJockey(body: UpdateJockeyRequest) {\n return request<UpdateJockeyResponse>('PUT', '/jockey/me', body, undefined);\n}\n\nexport function listStable() {\n return request<ListStableResponse>('GET', '/jockey/me/horses', undefined, undefined);\n}\n\nexport function createStableHorse(body: CreateStableHorseRequest) {\n return request<CreateStableHorseResponse>('POST', '/jockey/me/horses', body, undefined);\n}\n\nexport function updateStableHorse(stableHorseId: string, body: UpdateStableHorseRequest) {\n return request<UpdateStableHorseResponse>(\n 'PUT',\n `/jockey/me/horses/${encodeURIComponent(stableHorseId)}`,\n body,\n undefined,\n );\n}\n\nexport function deleteStableHorse(stableHorseId: string) {\n return request<DeleteStableHorseResponse>(\n 'DELETE',\n `/jockey/me/horses/${encodeURIComponent(stableHorseId)}`,\n undefined,\n undefined,\n );\n}\n\nexport function setOrgWebhook(orgName: string, body: SetOrgWebhookRequest) {\n return request<SetOrgWebhookResponse>(\n 'PUT',\n `/organisations/${encodeURIComponent(orgName)}/webhook`,\n body,\n undefined,\n );\n}\n\nexport function getOrgWebhook(orgName: string) {\n return request<GetOrgWebhookResponse>(\n 'GET',\n `/organisations/${encodeURIComponent(orgName)}/webhook`,\n undefined,\n undefined,\n );\n}\n\nexport function deleteOrgWebhook(orgName: string) {\n return request<DeleteOrgWebhookResponse>(\n 'DELETE',\n `/organisations/${encodeURIComponent(orgName)}/webhook`,\n undefined,\n undefined,\n );\n}\n","import React from 'react';\nimport { render, Box, Text } from 'ink';\nimport type { StableHorse } from '@token-derby/shared';\nimport { levelFromXp } from '@token-derby/shared';\nimport { listStable } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\nimport { HorseSprite } from '../ui/HorseSprite.js';\nimport { MINI_SPRITE } from '../ui/sprite.js';\n\nexport async function stableListCommand(): Promise<number> {\n let horses: StableHorse[];\n try {\n const resp = await listStable();\n horses = resp.horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n\n if (horses.length === 0) {\n console.log('Your stable is empty. Run `token-derby stable create` to add a horse.');\n return 0;\n }\n const app = render(\n React.createElement(StableList, { horses }),\n );\n await app.waitUntilExit();\n return 0;\n}\n\nfunction StableList({ horses }: { horses: StableHorse[] }) {\n React.useEffect(() => {\n setImmediate(() => process.exit(0));\n }, []);\n return (\n <Box flexDirection=\"column\">\n <Text bold>Your stable ({horses.length}):</Text>\n {horses.map(h => (\n <Box key={h.stable_horse_id} flexDirection=\"row\" marginTop={1}>\n <HorseSprite sprite={MINI_SPRITE} colors={h.colors} />\n <Text> {h.name} <Text color=\"cyan\">[Lvl. {levelFromXp(h.xp)}]</Text></Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { listStable, deleteStableHorse } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function stableDeleteCommand(name: string | undefined): Promise<number> {\n if (!name) {\n console.error('Usage: token-derby stable delete <name>');\n return 2;\n }\n\n let horses;\n try {\n horses = (await listStable()).horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n\n const horse = horses.find(h => h.name === name);\n if (!horse) {\n console.error(`No horse named \"${name}\" in your stable.`);\n return 1;\n }\n\n const rl = readline.createInterface({ input: stdin, output: stdout });\n const answer = (await rl.question(`Delete \"${name}\" from your stable? [y/N] `)).trim().toLowerCase();\n rl.close();\n if (answer !== 'y' && answer !== 'yes') {\n console.log('Cancelled.');\n return 1;\n }\n\n try {\n await deleteStableHorse(horse.stable_horse_id);\n console.log(`✓ Deleted \"${name}\".`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport { levelFromXp } from '@token-derby/shared';\nimport { HorseCreator } from '../ui/HorseCreator.js';\nimport { listStable, updateStableHorse } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function stableEditCommand(name: string | undefined): Promise<number> {\n if (!name) {\n console.error('Usage: token-derby stable edit <name>');\n return 2;\n }\n\n const horses = await fetchStable();\n if (!horses) return 1;\n const existing = horses.find(h => h.name === name);\n if (!existing) {\n console.error(`No horse named \"${name}\" in your stable.`);\n return 1;\n }\n\n let exitCode = 0;\n const app = render(\n React.createElement(HorseCreator, {\n initialColors: existing.colors,\n initialName: existing.name,\n lockName: true,\n initialLevel: levelFromXp(existing.xp),\n onSubmit: async (_name, colors) => {\n try {\n await updateStableHorse(existing.stable_horse_id, { colors });\n app.unmount();\n console.log(`✓ Updated \"${existing.name}\".`);\n } catch (e) {\n app.unmount();\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n exitCode = 1;\n return;\n }\n throw e;\n }\n },\n onCancel: () => {\n app.unmount();\n console.log('Cancelled.');\n exitCode = 1;\n },\n }),\n );\n await app.waitUntilExit();\n return exitCode;\n}\n\nasync function fetchStable() {\n try {\n const resp = await listStable();\n return resp.horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return null;\n }\n throw e;\n }\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { ORG_NAME_PATTERN } from '@token-derby/shared';\nimport { createRace } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nconst DEFAULT_TZ = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n\nexport async function createRaceCommand(organisationName?: string): Promise<number> {\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n const name = (await rl.question('Race name: ')).trim();\n if (!name) { console.error('Name required.'); return 1; }\n\n const startRaw = (await rl.question('Start time (ISO 8601, blank = now): ')).trim();\n const start = startRaw ? startRaw : new Date().toISOString();\n if (!isIso(start)) { console.error('Invalid start time.'); return 1; }\n\n const durationRaw = (await rl.question('Race duration (hours): ')).trim();\n const durationHours = parseFloat(durationRaw);\n if (!Number.isFinite(durationHours) || durationHours <= 0) {\n console.error('Duration must be a positive number of hours.'); return 1;\n }\n const end = new Date(new Date(start).getTime() + durationHours * 3600_000).toISOString();\n\n const tz = (await rl.question(`Time zone [${DEFAULT_TZ}]: `)).trim() || DEFAULT_TZ;\n const maxRaw = (await rl.question('Max participants [30]: ')).trim();\n const max = maxRaw ? parseInt(maxRaw, 10) : undefined;\n if (max !== undefined && (!Number.isFinite(max) || max < 1)) {\n console.error('Max participants must be a positive number.'); return 1;\n }\n\n let org = organisationName;\n if (org === undefined) {\n const raw = (await rl.question('Organisation (blank for none): ')).trim();\n if (raw) org = raw;\n }\n if (org !== undefined && !ORG_NAME_PATTERN.test(org)) {\n console.error('Organisation name must be 1–12 alphanumeric characters.');\n return 1;\n }\n\n const countInputRaw = (await rl.question('Count input tokens (fresh input + cache creation) toward race totals? [y/N]: ')).trim().toLowerCase();\n const counts_input = countInputRaw === 'y' || countInputRaw === 'yes';\n\n const resp = await createRace({\n name, start_time: start, end_time: end, tz,\n ...(max !== undefined ? { max_participants: max } : {}),\n ...(org ? { organisation_name: org } : {}),\n ...(counts_input ? { counts_input: true } : {}),\n });\n\n console.log('');\n console.log(' ╔══════════════════════════════════════╗');\n console.log(` ║ JOIN CODE: ${resp.join_code.padEnd(23)}║`);\n console.log(' ╚══════════════════════════════════════╝');\n console.log('');\n console.log(` Admin code: ${resp.admin_code}`);\n console.log(' ⚠ Save the admin code — you need it to end the race early.');\n console.log('');\n if (org) {\n console.log(` Restricted to organisation: ${org}`);\n }\n if (counts_input) {\n console.log(' Counting input + output tokens (excluding cache reads).');\n }\n console.log(` Share with participants: token-derby join ${resp.join_code}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n } finally {\n rl.close();\n }\n}\n\nfunction isIso(s: string): boolean {\n if (!s) return false;\n const d = new Date(s);\n return !Number.isNaN(d.getTime());\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport type { HorseColors, StableHorse } from '@token-derby/shared';\nimport { HorsePicker } from '../ui/HorsePicker.js';\nimport { joinRace, getRace, listStable, listOrganisations } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\nimport { saveActiveRace, loadActiveRace, type ActiveRace } from '../stable/active-race.js';\nimport { RunRace, buildInitialState } from '../runtime/run-race.js';\nimport { loadIdentity } from '../identity/identity.js';\n\nexport async function joinCommand(joinCode: string | undefined): Promise<number> {\n if (!joinCode) {\n console.error('Usage: token-derby join <join-code>');\n return 2;\n }\n const code = joinCode.toUpperCase();\n\n const identity = await loadIdentity();\n if (!identity) {\n // Defensive — bin.ts already checks. Kept so this command is self-contained.\n console.error('Run `token-derby init` to set up your identity.');\n return 1;\n }\n\n // Pre-flight: fetch the race view to detect whether this user is already in it.\n let race;\n try {\n race = await getRace(code);\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'RACE_NOT_FOUND') console.error(`No race with join code ${code}.`);\n else console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n if (race.status === 'finished') {\n console.error('This race has already ended.');\n return 1;\n }\n\n const ownHorse = race.horses.find(h => h.user_id === identity.user_id) ?? null;\n\n let chosenStableHorseId: string;\n let chosenName: string;\n let chosenColors: HorseColors;\n let isResume: boolean;\n\n if (ownHorse) {\n // Auto-resume: use server's snapshot of the horse, no picker.\n chosenStableHorseId = ownHorse.stable_horse_id;\n chosenName = ownHorse.name;\n chosenColors = ownHorse.colors;\n isResume = true;\n } else {\n // For org-restricted races, surface NOT_ORG_MEMBER before walking the user\n // through stable/picker flows — otherwise the first thing they see is\n // \"Your stable is empty\" or a horse picker, hiding the real reason the\n // join will fail. The server still enforces this on POST /join.\n if (race.org_id) {\n try {\n const { organisations } = await listOrganisations();\n if (!organisations.some(o => o.org_id === race.org_id)) {\n const label = race.organisation_name ?? race.org_id;\n console.error(`This race is restricted to members of \"${label}\".`);\n return 1;\n }\n } catch {\n // If we can't reach the orgs endpoint, fall through and let the\n // join API enforce membership — server is source of truth.\n }\n }\n\n let horses: StableHorse[];\n try {\n horses = (await listStable()).horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n if (horses.length === 0) {\n console.error('Your stable is empty. Run `token-derby stable create` first.');\n return 1;\n }\n const picked = await pickHorse(horses);\n if (!picked) { console.log('Cancelled.'); return 1; }\n chosenStableHorseId = picked.stable_horse_id;\n chosenName = picked.name;\n chosenColors = picked.colors;\n isResume = false;\n }\n\n let joinResp;\n try {\n joinResp = await joinRace(code, { stable_horse_id: chosenStableHorseId });\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'RACE_FULL') console.error('This race is full.');\n else if (e.code === 'RACE_FINISHED') console.error('This race has ended.');\n else if (e.code === 'RACE_NOT_FOUND') console.error(`No race with join code ${code}.`);\n else if (e.code === 'VERSION_MISMATCH') console.error(e.message);\n else if (e.code === 'DUPLICATE_HORSE') console.error(e.message);\n else if (e.code === 'STABLE_HORSE_NOT_FOUND') {\n console.error('That horse no longer exists in your stable. Try again.');\n }\n else if (e.code === 'NOT_ORG_MEMBER') console.error(e.message);\n else console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n\n // For resume, try to carry forward our last token total from active-races state.\n const prior = await loadActiveRace(code);\n const lastTokens = isResume && prior?.horse_id === joinResp.horse_id ? prior.last_race_tokens : (ownHorse?.current_tokens ?? 0);\n\n const status: 'pending' | 'live' = race.status;\n const active: ActiveRace = {\n join_code: code,\n race_id: race.race_id,\n horse_id: joinResp.horse_id,\n heartbeat_token: joinResp.heartbeat_token,\n horse_name: chosenName,\n horse_colors: chosenColors,\n joined_at: ownHorse?.joined_at ?? new Date().toISOString(),\n last_race_tokens: lastTokens,\n last_heartbeat_at: new Date(0).toISOString(),\n ...(race.counts_input ? { counts_input: true } : {}),\n };\n await saveActiveRace(active);\n\n const initial = await buildInitialState({ active, raceStatus: status, rejoin: isResume });\n const app = render(React.createElement(RunRace, { active, ...initial, ownUserName: identity.display_name }));\n await app.waitUntilExit();\n return 0;\n}\n\nasync function pickHorse(horses: StableHorse[]): Promise<StableHorse | null> {\n return new Promise(resolve => {\n const app = render(\n React.createElement(HorsePicker, {\n horses,\n onPick: (h: StableHorse) => { app.unmount(); resolve(h); },\n onCancel: () => { app.unmount(); resolve(null); },\n }),\n );\n });\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MINI_SPRITE } from './sprite.js';\nimport type { StableHorse } from '@token-derby/shared';\nimport { levelFromXp } from '@token-derby/shared';\n\ntype Props = {\n horses: StableHorse[];\n onPick: (horse: StableHorse) => void;\n onCancel: () => void;\n};\n\nexport function HorsePicker({ horses, onPick, onCancel }: Props) {\n const [idx, setIdx] = useState(0);\n\n useInput((input, key) => {\n if (key.escape) { onCancel(); return; }\n if (horses.length === 0) return;\n if (key.upArrow) { setIdx((idx - 1 + horses.length) % horses.length); return; }\n if (key.downArrow) { setIdx((idx + 1) % horses.length); return; }\n if (key.return) { onPick(horses[idx]!); return; }\n });\n\n if (horses.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text>No horses in your stable.</Text>\n <Text dimColor>Run `token-derby stable create` to make one.</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text>Pick a horse to race:</Text>\n {horses.map((h, i) => (\n <Box key={h.stable_horse_id} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text>{i === idx ? '►' : ' '} {h.name} <Text color=\"cyan\">[Lvl. {levelFromXp(h.xp)}]</Text></Text>\n </Box>\n <Box flexDirection=\"row\">\n <Text> </Text>\n <HorseSprite sprite={MINI_SPRITE} colors={h.colors} />\n </Box>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text dimColor>↑/↓ choose · Enter pick · Esc cancel</Text>\n </Box>\n </Box>\n );\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { HorseColors } from '@token-derby/shared';\nimport { activeRaceFile, activeRacesDir } from '../paths.js';\n\nexport type ActiveRace = {\n join_code: string;\n race_id: string;\n horse_id: string;\n heartbeat_token: string;\n horse_name: string;\n horse_colors: HorseColors;\n joined_at: string;\n last_race_tokens: number;\n last_heartbeat_at: string;\n counts_input?: boolean;\n};\n\nexport async function loadActiveRace(joinCode: string): Promise<ActiveRace | null> {\n try {\n const raw = await fs.readFile(activeRaceFile(joinCode), 'utf8');\n return JSON.parse(raw) as ActiveRace;\n } catch (e: any) {\n if (e?.code === 'ENOENT') return null;\n throw e;\n }\n}\n\nexport async function saveActiveRace(active: ActiveRace): Promise<void> {\n await fs.mkdir(activeRacesDir(), { recursive: true });\n await fs.writeFile(\n activeRaceFile(active.join_code),\n JSON.stringify(active, null, 2) + '\\n',\n 'utf8',\n );\n}\n\nexport async function deleteActiveRace(joinCode: string): Promise<void> {\n try {\n await fs.unlink(activeRaceFile(joinCode));\n } catch (e: any) {\n if (e?.code !== 'ENOENT') throw e;\n }\n}\n\nexport async function listActiveRaces(): Promise<string[]> {\n try {\n const entries = await fs.readdir(activeRacesDir());\n return entries\n .filter(f => f.endsWith('.json'))\n .map(f => path.basename(f, '.json'));\n } catch (e: any) {\n if (e?.code === 'ENOENT') return [];\n throw e;\n }\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport type { GetRaceResponse, HeartbeatResponse } from '@token-derby/shared';\nimport { StatusScreen } from '../ui/StatusScreen.js';\nimport { describeAchievement, type RecentEvent } from '@token-derby/shared';\nimport { runHeartbeatLoop } from './heartbeat-loop.js';\nimport { sumTokensForRace } from '../tokens/transcripts.js';\nimport { initialBaseline } from '../tokens/baseline.js';\nimport * as endpoints from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\nimport { saveActiveRace, type ActiveRace } from '../stable/active-race.js';\nimport { HEARTBEAT_INTERVAL_MS, HEARTBEAT_RETRY_DELAYS_MS } from '../config.js';\n\nexport type RunRaceProps = {\n active: ActiveRace;\n startingBaseline: number;\n pendingMode: boolean;\n ownUserName: string;\n};\n\nexport function RunRace({ active, startingBaseline, pendingMode, ownUserName }: RunRaceProps) {\n const { exit } = useApp();\n const [race, setRace] = useState<GetRaceResponse | null>(null);\n const [lastHbAt, setLastHbAt] = useState<Date | null>(null);\n const [lastHbOk, setLastHbOk] = useState<boolean>(true);\n const [tickNow, setTickNow] = useState<Date>(new Date());\n const [fatalError, setFatalError] = useState<string | null>(null);\n const [achievements, setAchievements] = useState<Array<{ key: string; event: RecentEvent }>>([]);\n const shownAchievementAtRef = useRef<number>(0);\n\n const baselineRef = useRef(startingBaseline);\n const pendingRef = useRef(pendingMode);\n const lastTokenSampleRef = useRef<number>(startingBaseline);\n const ctrl = useRef(new AbortController());\n\n // Re-render every second so the \"Ns ago\" counter updates.\n useEffect(() => {\n const t = setInterval(() => setTickNow(new Date()), 1_000);\n return () => clearInterval(t);\n }, []);\n\n // Re-snapshot baseline when race transitions pending → live.\n useEffect(() => {\n if (pendingRef.current && race?.status === 'live') {\n sumTokensForRace(active).then(total => {\n baselineRef.current = total;\n pendingRef.current = false;\n });\n }\n }, [race?.status]);\n\n useEffect(() => {\n runHeartbeatLoop({\n sendHeartbeat: async (currentTokens) => {\n const resp = await endpoints.heartbeat(\n active.join_code, active.horse_id, active.heartbeat_token, { current_tokens: currentTokens },\n );\n const updated: ActiveRace = {\n ...active,\n last_race_tokens: currentTokens,\n last_heartbeat_at: new Date().toISOString(),\n };\n await saveActiveRace(updated);\n return resp;\n },\n getCurrentTokens: () => {\n if (pendingRef.current) return 0;\n return Math.max(0, lastTokenSampleRef.current - baselineRef.current);\n },\n intervalMs: HEARTBEAT_INTERVAL_MS,\n retryDelaysMs: HEARTBEAT_RETRY_DELAYS_MS,\n onSuccess: (resp: HeartbeatResponse) => {\n setLastHbAt(new Date());\n setLastHbOk(true);\n setRace(raceViewFrom(resp));\n const own = resp.horses.find(h => h.horse_id === active.horse_id);\n const candidates = (own?.recent_events ?? []).filter(e => e.at > shownAchievementAtRef.current);\n if (candidates.length > 0) {\n shownAchievementAtRef.current = Math.max(...candidates.map(e => e.at));\n const fresh = candidates.map(e => ({ key: `${e.at}-${e.name}`, event: e }));\n setAchievements(prev => [...prev, ...fresh]);\n }\n if (resp.race_status === 'finished') exit();\n },\n onError: (err) => {\n if (err instanceof ApiError && err.code === 'VERSION_MISMATCH') {\n setFatalError(err.message);\n ctrl.current.abort();\n exit();\n return;\n }\n setLastHbOk(false);\n },\n onFinished: () => exit(),\n abortSignal: ctrl.current.signal,\n });\n\n // Token sampler — refresh the running token total every 5s so the heartbeat sees fresh data.\n const sampler = setInterval(async () => {\n try {\n lastTokenSampleRef.current = await sumTokensForRace(active);\n } catch (e) {\n console.error('[token-derby] token sampler failed:', e);\n }\n }, 5_000);\n // Prime it once at startup.\n sumTokensForRace(active)\n .then(t => { lastTokenSampleRef.current = t; })\n .catch(e => console.error('[token-derby] token sampler prime failed:', e));\n\n const controller = ctrl.current;\n return () => {\n clearInterval(sampler);\n controller.abort();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const lastHeartbeatAgoSec = lastHbAt\n ? Math.max(0, Math.floor((tickNow.getTime() - lastHbAt.getTime()) / 1000))\n : null;\n\n if (fatalError) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\" bold>CLI version mismatch — disconnected</Text>\n <Text>{fatalError}</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <StatusScreen\n race={race}\n ownHorseId={active.horse_id}\n ownHorseName={active.horse_name}\n ownColors={active.horse_colors}\n ownUserName={ownUserName}\n lastHeartbeatAgoSec={lastHeartbeatAgoSec}\n lastHeartbeatOk={lastHbOk}\n />\n {achievements.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>Achievements</Text>\n {achievements.map(({ key, event }) => {\n const description = describeAchievement(event, active);\n return (\n <Box key={key} flexDirection=\"row\">\n <Text dimColor> {formatClockTime(event.at)} </Text>\n <Text color=\"yellow\" bold>+{event.xp} XP </Text>\n <Text>{event.name}</Text>\n <Text dimColor> — {description}</Text>\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n );\n}\n\nfunction formatClockTime(at: number): string {\n const d = new Date(at);\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n const s = String(d.getSeconds()).padStart(2, '0');\n return `${h}:${m}:${s}`;\n}\n\nfunction raceViewFrom(resp: HeartbeatResponse): GetRaceResponse {\n return {\n ...resp.race,\n status: resp.race_status,\n horses: resp.horses,\n server_time: resp.server_time,\n time_left_seconds: resp.time_left_seconds,\n };\n}\n\nexport async function buildInitialState(args: {\n active: ActiveRace;\n raceStatus: 'pending' | 'live';\n rejoin: boolean;\n}): Promise<{ startingBaseline: number; pendingMode: boolean }> {\n const runningTotal = await sumTokensForRace(args.active);\n if (args.rejoin) {\n return {\n startingBaseline: Math.max(0, runningTotal - args.active.last_race_tokens),\n pendingMode: args.raceStatus === 'pending',\n };\n }\n return {\n startingBaseline: initialBaseline({ runningTotal, status: args.raceStatus }),\n pendingMode: args.raceStatus === 'pending',\n };\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { GetRaceResponse, HorseColors, HorseView } from '@token-derby/shared';\nimport { levelInfo } from '@token-derby/shared';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MINI_SPRITE } from './sprite.js';\n\ntype Props = {\n race: GetRaceResponse | null;\n ownHorseId: string;\n ownHorseName: string;\n ownColors: HorseColors;\n ownUserName: string;\n lastHeartbeatAgoSec: number | null;\n lastHeartbeatOk: boolean;\n};\n\nexport function StatusScreen(props: Props) {\n const { race, ownHorseId, ownHorseName, ownColors, ownUserName, lastHeartbeatAgoSec, lastHeartbeatOk } = props;\n\n if (!race) {\n return (\n <Box flexDirection=\"column\">\n <Text>Joining race…</Text>\n </Box>\n );\n }\n\n const own: HorseView | undefined = race.horses.find(h => h.horse_id === ownHorseId);\n const leader: HorseView | undefined = race.horses[0];\n const elapsedPct = elapsed(race);\n const timeLeft = formatDuration(race.time_left_seconds);\n const lvl = levelInfo((own?.xp ?? 0) + (own?.live_xp ?? 0));\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1}>\n <Text>\n 🏇 TOKEN DERBY ─── <Text bold>{race.name}</Text> ─── status: <Text color={statusColor(race.status)}>{race.status}</Text>\n </Text>\n\n <Box marginTop={1} flexDirection=\"row\">\n <HorseSprite sprite={MINI_SPRITE} colors={ownColors} />\n <Box flexDirection=\"column\">\n <Text> {ownHorseName} <Text color=\"cyan\">[Lvl. {lvl.level}]</Text></Text>\n <Text> <Text dimColor>({ownUserName})</Text></Text>\n </Box>\n </Box>\n\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>Tokens (race): {own?.current_tokens ?? 0}</Text>\n <Text>Position: {own?.rank ?? '—'} of {race.horses.length}</Text>\n <Text>\n Leader: {leader ? `${leader.name}${leader.user_name ? ` (${leader.user_name})` : ''} — ${leader.current_tokens}` : '—'}\n </Text>\n <Text>Race elapsed: {(elapsedPct * 100).toFixed(0)}% {bar(elapsedPct, 20)}</Text>\n <Text>Time left: {timeLeft}</Text>\n <Text>\n XP: {lvl.next_level_xp === null\n ? `${lvl.xp} (max level) ${bar(1, 20)}`\n : `${lvl.xp_into_level}/${lvl.xp_for_level} → Lvl. ${lvl.level + 1} ${bar(lvl.progress, 20)}`}\n </Text>\n <Text>\n Last heartbeat: {lastHeartbeatAgoSec === null ? '—' : `${lastHeartbeatAgoSec}s ago`}\n {' '}\n <Text color={lastHeartbeatOk ? 'green' : 'yellow'}>\n {lastHeartbeatOk ? '✓' : '⚠'}\n </Text>\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>Press Ctrl+C to crash out of the race.</Text>\n </Box>\n </Box>\n );\n}\n\nfunction elapsed(race: GetRaceResponse): number {\n const start = new Date(race.start_time).getTime();\n const end = new Date(race.end_time).getTime();\n const now = new Date(race.server_time).getTime();\n if (end <= start) return 0;\n const v = (now - start) / (end - start);\n return Math.max(0, Math.min(1, v));\n}\n\nfunction bar(pct: number, width: number): string {\n const filled = Math.round(pct * width);\n return '▓'.repeat(filled) + '░'.repeat(width - filled);\n}\n\nfunction statusColor(status: GetRaceResponse['status']): string {\n if (status === 'live') return 'green';\n if (status === 'pending') return 'yellow';\n return 'gray';\n}\n\nfunction formatDuration(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const ss = s % 60;\n return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${ss.toString().padStart(2, '0')}`;\n}\n","import type { HeartbeatResponse } from '@token-derby/shared';\n\nexport type HeartbeatLoopOptions = {\n sendHeartbeat: (currentTokens: number) => Promise<HeartbeatResponse>;\n getCurrentTokens: () => number;\n intervalMs: number;\n retryDelaysMs: readonly number[];\n onSuccess: (resp: HeartbeatResponse) => void;\n onError: (err: unknown) => void;\n onFinished: () => void;\n abortSignal: AbortSignal;\n};\n\nexport function runHeartbeatLoop(opts: HeartbeatLoopOptions): void {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let retryIndex = 0;\n let stopped = false;\n\n const stop = () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n timer = null;\n };\n\n opts.abortSignal.addEventListener('abort', stop, { once: true });\n\n const schedule = (delay: number) => {\n if (stopped) return;\n timer = setTimeout(tick, delay);\n };\n\n const tick = async () => {\n if (stopped) return;\n try {\n const tokens = opts.getCurrentTokens();\n const resp = await opts.sendHeartbeat(tokens);\n retryIndex = 0;\n opts.onSuccess(resp);\n if (resp.race_status === 'finished') {\n opts.onFinished();\n stop();\n return;\n }\n schedule(opts.intervalMs);\n } catch (err) {\n opts.onError(err);\n const delay = opts.retryDelaysMs[Math.min(retryIndex, opts.retryDelaysMs.length - 1)] ?? 1_000;\n retryIndex += 1;\n schedule(delay);\n }\n };\n\n schedule(0);\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { claudeProjectsDir } from '../paths.js';\n\n// `input` here is \"fresh-input\" tokens only: input_tokens (this turn's new\n// content) + cache_creation_input_tokens (tokens written into the cache this\n// turn). cache_read_input_tokens is intentionally excluded — those are\n// passive context that don't represent work done in the race.\nexport type TokenTotals = { input: number; output: number };\n\nexport async function sumTokens(): Promise<TokenTotals> {\n const root = claudeProjectsDir();\n const files = await listJsonlFiles(root);\n let input = 0;\n let output = 0;\n for (const file of files) {\n const t = await sumFile(file);\n input += t.input;\n output += t.output;\n }\n return { input, output };\n}\n\n// Total tokens for a race in the race's chosen mode. When race.counts_input\n// is true, the race counts fresh-input + cache-creation + output; otherwise\n// it counts output only. cache_read is never included.\nexport async function sumTokensForRace(race: { counts_input?: boolean }): Promise<number> {\n const { input, output } = await sumTokens();\n return race.counts_input ? input + output : output;\n}\n\nasync function listJsonlFiles(root: string): Promise<string[]> {\n let projects: string[];\n try {\n projects = await fs.readdir(root);\n } catch (e: any) {\n if (e?.code === 'ENOENT') return [];\n throw e;\n }\n const out: string[] = [];\n for (const project of projects) {\n const projectDir = path.join(root, project);\n let stat;\n try {\n stat = await fs.stat(projectDir);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) continue;\n let entries: string[];\n try {\n entries = await fs.readdir(projectDir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.endsWith('.jsonl')) out.push(path.join(projectDir, entry));\n }\n }\n return out;\n}\n\nfunction addNum(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : 0;\n}\n\nasync function sumFile(file: string): Promise<TokenTotals> {\n let raw: string;\n try {\n raw = await fs.readFile(file, 'utf8');\n } catch {\n return { input: 0, output: 0 };\n }\n let input = 0;\n let output = 0;\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n let parsed: any;\n try {\n parsed = JSON.parse(line);\n } catch {\n continue;\n }\n const usage = parsed?.message?.usage;\n if (!usage) continue;\n input += addNum(usage.input_tokens) + addNum(usage.cache_creation_input_tokens);\n output += addNum(usage.output_tokens);\n }\n return { input, output };\n}\n","import type { RaceStatus } from '@token-derby/shared';\n\nexport function initialBaseline(args: { runningTotal: number; status: RaceStatus }): number {\n return args.runningTotal;\n}\n\nexport function rejoinBaseline(args: { runningTotal: number; lastRaceTokens: number }): number {\n return Math.max(0, args.runningTotal - args.lastRaceTokens);\n}\n\nexport function currentRaceTokens(runningTotal: number, baseline: number): number {\n return Math.max(0, runningTotal - baseline);\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { endRace } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function endCommand(adminCode: string | undefined): Promise<number> {\n if (!adminCode) {\n console.error('Usage: token-derby end <admin-code>');\n return 2;\n }\n const rl = readline.createInterface({ input: stdin, output: stdout });\n const answer = (await rl.question('End the race now and freeze final tokens? [y/N] ')).trim().toLowerCase();\n rl.close();\n if (answer !== 'y' && answer !== 'yes') {\n console.log('Cancelled.');\n return 1;\n }\n try {\n await endRace(adminCode);\n console.log('✓ Race ended.');\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'RACE_NOT_FOUND') console.error('No race with that admin code.');\n else console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport {\n loadIdentity,\n saveIdentity,\n deleteIdentity,\n validateDisplayName,\n type Identity,\n} from '../identity/identity.js';\nimport { initJockey, updateJockey } from '../api/endpoints.js';\nimport { ApiError, _resetIdentityCacheForTests } from '../api/client.js';\n\nexport async function initCommand(reset = false): Promise<number> {\n if (reset) {\n await deleteIdentity();\n _resetIdentityCacheForTests();\n console.log('Removed local identity. Creating a new one…');\n }\n\n const existing = await loadIdentity();\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n if (existing) {\n console.log(`Current jockey name: ${existing.display_name}`);\n const raw = (await rl.question('New jockey name (use your real name please) [keep]: ')).trim();\n if (!raw) {\n console.log('Kept existing name.');\n return 0;\n }\n const v = validateDisplayName(raw);\n if (!v.ok) { console.error(v.error); return 1; }\n try {\n const resp = await updateJockey({ display_name: v.name });\n const updated: Identity = { ...existing, display_name: resp.display_name };\n await saveIdentity(updated);\n console.log(`Updated jockey name to: ${updated.display_name}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'UNAUTHENTICATED') {\n console.error(\n 'Server does not recognise this identity. Your account may have been wiped. ' +\n 'Run `token-derby init --reset` to start fresh.',\n );\n } else {\n console.error(`Error: ${e.code} ${e.message}`);\n }\n return 1;\n }\n throw e;\n }\n }\n\n const raw = (await rl.question('Jockey Name (use your real name please): ')).trim();\n const v = validateDisplayName(raw);\n if (!v.ok) { console.error(v.error); return 1; }\n\n try {\n const resp = await initJockey({ display_name: v.name });\n const identity: Identity = {\n user_id: resp.user_id,\n display_name: resp.display_name,\n secret_token: resp.secret_token,\n created_at: new Date().toISOString(),\n };\n await saveIdentity(identity);\n _resetIdentityCacheForTests();\n console.log('');\n console.log(`Welcome, ${identity.display_name}!`);\n console.log('Your identity has been created on the server.');\n console.log('You can now create a stable and join races.');\n console.log('');\n console.log(' ⚠ Your secret token is stored locally in identity.json.');\n console.log(' If you lose it, you cannot recover this account — you would');\n console.log(' need to run `token-derby init --reset` and rebuild your stable.');\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n } finally {\n rl.close();\n }\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { spawn } from 'node:child_process';\nimport { gteSemver } from '@token-derby/shared';\nimport { CLI_VERSION } from '../version.js';\n\nconst REGISTRY_URL = 'https://registry.npmjs.org/@mauricode/token-derby/latest';\nconst UPGRADE_CMD = 'npm install -g @mauricode/token-derby@latest';\nconst FETCH_TIMEOUT_MS = 5_000;\n\ntype Deps = {\n fetchImpl?: typeof fetch;\n spawnImpl?: typeof spawn;\n promptYesNo?: (question: string) => Promise<boolean>;\n};\n\nexport async function updateCommand(deps: Deps = {}): Promise<number> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const spawnImpl = deps.spawnImpl ?? spawn;\n const promptYesNo = deps.promptYesNo ?? defaultPromptYesNo;\n\n let latest: string;\n try {\n latest = await fetchLatestVersion(fetchImpl);\n } catch (e: any) {\n console.error(`Could not reach the npm registry${e?.message ? ` (${e.message})` : ''}.`);\n console.error(`To upgrade manually: ${UPGRADE_CMD}`);\n return 1;\n }\n\n if (gteSemver(CLI_VERSION, latest)) {\n console.log(`You're on the latest version (${CLI_VERSION}).`);\n return 0;\n }\n\n console.log(`Current: ${CLI_VERSION} Latest: ${latest}`);\n const yes = await promptYesNo('Run upgrade now? [y/N]: ');\n if (!yes) {\n console.log(`To upgrade manually: ${UPGRADE_CMD}`);\n return 0;\n }\n\n return runNpmUpgrade(spawnImpl);\n}\n\nasync function fetchLatestVersion(fetchImpl: typeof fetch): Promise<string> {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetchImpl(REGISTRY_URL, { signal: controller.signal });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = await res.json() as { version?: unknown };\n if (typeof body.version !== 'string' || !/^\\d+\\.\\d+\\.\\d+/.test(body.version)) {\n throw new Error('unexpected registry response');\n }\n return body.version;\n } finally {\n clearTimeout(t);\n }\n}\n\nasync function defaultPromptYesNo(question: string): Promise<boolean> {\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n const answer = (await rl.question(question)).trim().toLowerCase();\n return answer === 'y' || answer === 'yes';\n } finally {\n rl.close();\n }\n}\n\nfunction runNpmUpgrade(spawnImpl: typeof spawn): Promise<number> {\n return new Promise(resolve => {\n const child = spawnImpl('npm', ['install', '-g', '@mauricode/token-derby@latest'], {\n stdio: 'inherit',\n });\n child.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'ENOENT') {\n console.error('Could not find `npm` on PATH.');\n console.error(`To upgrade manually: ${UPGRADE_CMD}`);\n } else {\n console.error(`npm failed to start: ${e.message}`);\n }\n resolve(1);\n });\n child.on('exit', code => resolve(code ?? 1));\n });\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { ORG_NAME_PATTERN, ORG_NAME_MAX_LENGTH } from '@token-derby/shared';\nimport { createOrganisation } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgCreateCommand(): Promise<number> {\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n const name = (await rl.question(`Organisation name (1–${ORG_NAME_MAX_LENGTH} alphanumeric chars): `)).trim();\n if (!ORG_NAME_PATTERN.test(name)) {\n console.error(`Name must be 1–${ORG_NAME_MAX_LENGTH} alphanumeric characters (no spaces or symbols).`);\n return 1;\n }\n const resp = await createOrganisation({ name });\n\n console.log('');\n console.log(` Organisation created: ${resp.org_name}`);\n console.log(' ╔══════════════════════════════════════════════════════════╗');\n console.log(` ║ JOIN TOKEN: ${resp.org_join_token.padEnd(43)}║`);\n console.log(' ╚══════════════════════════════════════════════════════════╝');\n console.log(' ⚠ Share this token to invite members. Treat it as a secret.');\n console.log('');\n console.log(` Members join with: token-derby organisation join ${resp.org_join_token}`);\n console.log(` Create org races: token-derby create --organisation ${resp.org_name}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n } finally {\n rl.close();\n }\n}\n","import { joinOrganisation } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgJoinCommand(token: string | undefined): Promise<number> {\n if (!token) {\n console.error('Usage: token-derby organisation join <join-token>');\n return 2;\n }\n try {\n const resp = await joinOrganisation({ join_token: token });\n console.log(`Joined organisation: ${resp.org_name}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { listOrganisations } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgListCommand(): Promise<number> {\n try {\n const resp = await listOrganisations();\n if (resp.organisations.length === 0) {\n console.log('You are not in any organisations.');\n console.log('Create one with: token-derby organisation create');\n console.log('Or join one with: token-derby organisation join <token>');\n return 0;\n }\n console.log(`Your organisations (${resp.organisations.length}):`);\n for (const o of resp.organisations) {\n console.log(` • ${o.org_name}`);\n }\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { ORG_NAME_PATTERN } from '@token-derby/shared';\nimport { getOrganisation } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgInfoCommand(name: string | undefined): Promise<number> {\n if (!name) {\n console.error('Usage: token-derby organisation info <name>');\n return 2;\n }\n if (!ORG_NAME_PATTERN.test(name)) {\n console.error('Organisation name must be 1–12 alphanumeric characters.');\n return 2;\n }\n try {\n const resp = await getOrganisation(name);\n console.log(`Organisation: ${resp.org_name}`);\n console.log(`Created: ${resp.created_at} by ${resp.creator_user_name}`);\n console.log('');\n console.log(' ╔══════════════════════════════════════════════════════════╗');\n console.log(` ║ JOIN TOKEN: ${resp.org_join_token.padEnd(43)}║`);\n console.log(' ╚══════════════════════════════════════════════════════════╝');\n console.log(' ⚠ Treat the token as a secret — anyone with it can join.');\n console.log('');\n console.log(` Members join with: token-derby organisation join ${resp.org_join_token}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { setOrgWebhook } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgWebhookSetCommand(orgName: string | undefined, url: string | undefined): Promise<number> {\n if (!orgName || !url) {\n console.error('Usage: token-derby organisation webhook set <org-name> <https-url>');\n return 2;\n }\n try {\n const resp = await setOrgWebhook(orgName, { url });\n console.log('');\n console.log(` Webhook set for ${orgName}: ${resp.webhook_url}`);\n console.log(' ╔══════════════════════════════════════════════════════════╗');\n console.log(` ║ SECRET: ${resp.webhook_secret.padEnd(47)}║`);\n console.log(' ╚══════════════════════════════════════════════════════════╝');\n console.log(' ⚠ Save this secret now — it will not be shown again.');\n console.log(' Your receiver verifies requests with: X-Token-Derby-Signature: sha256=<hmac(secret, raw body)>.');\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { getOrgWebhook } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgWebhookGetCommand(orgName: string | undefined): Promise<number> {\n if (!orgName) {\n console.error('Usage: token-derby organisation webhook get <org-name>');\n return 2;\n }\n try {\n const resp = await getOrgWebhook(orgName);\n if (resp.webhook_url) {\n console.log(`Webhook for ${orgName}: ${resp.webhook_url}`);\n } else {\n console.log(`No webhook configured for ${orgName}.`);\n }\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { deleteOrgWebhook } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgWebhookClearCommand(orgName: string | undefined): Promise<number> {\n if (!orgName) {\n console.error('Usage: token-derby organisation webhook clear <org-name>');\n return 2;\n }\n try {\n await deleteOrgWebhook(orgName);\n console.log(`Webhook removed for ${orgName}.`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { stableCreateCommand } from './commands/stable-create.js';\nimport { stableListCommand } from './commands/stable-list.js';\nimport { stableDeleteCommand } from './commands/stable-delete.js';\nimport { stableEditCommand } from './commands/stable-edit.js';\nimport { createRaceCommand } from './commands/create.js';\nimport { joinCommand } from './commands/join.js';\nimport { endCommand } from './commands/end.js';\nimport { initCommand } from './commands/init.js';\nimport { updateCommand } from './commands/update.js';\nimport { orgCreateCommand } from './commands/org-create.js';\nimport { orgJoinCommand } from './commands/org-join.js';\nimport { orgListCommand } from './commands/org-list.js';\nimport { orgInfoCommand } from './commands/org-info.js';\nimport { orgWebhookSetCommand } from './commands/org-webhook-set.js';\nimport { orgWebhookGetCommand } from './commands/org-webhook-get.js';\nimport { orgWebhookClearCommand } from './commands/org-webhook-clear.js';\nimport { CLI_VERSION } from './version.js';\nimport { loadIdentity } from './identity/identity.js';\n\nconst HELP = `token-derby v${CLI_VERSION}\n\nIdentity:\n token-derby init Set up your jockey identity (run this first)\n Re-running renames you on the server.\n token-derby init --reset Wipe local identity and create a fresh account.\n Your previous stable is abandoned on the server.\n\nMaintenance:\n token-derby update Check for and install the latest CLI version\n\nStable management:\n token-derby stable create Make a new horse (interactive)\n token-derby stable list Show your saved horses\n token-derby stable edit <name> Edit an existing horse's colors\n token-derby stable delete <name> Remove a horse from your stable\n\nOrganisations:\n token-derby organisation create Create a new organisation (interactive)\n token-derby organisation join <token> Join an organisation with a join token\n token-derby organisation info <name> Show an org's join token (members only)\n token-derby organisation list Show organisations you're a member of\n token-derby organisation webhook set <name> <url>\n Configure an https webhook for race events.\n Prints a secret used to sign each request.\n Only the org creator can run this.\n token-derby organisation webhook get <name>\n Show the org's configured webhook URL (or \"no webhook\").\n token-derby organisation webhook clear <name>\n Remove the webhook for this org.\n\nRaces:\n token-derby create [--organisation <name>]\n Create a new race (interactive). When\n --organisation is set, only members of\n that org can join.\n token-derby join <join-code> Join (or resume) a race\n token-derby end <admin-code> End a race early\n\nEnvironment:\n TOKEN_DERBY_API_BASE Override API base URL (default: production)\n TOKEN_DERBY_HOME Override identity/stable directory\n`;\n\nasync function main(): Promise<number> {\n const argv = process.argv.slice(2);\n const cmd = argv[0];\n\n if (!cmd || cmd === '--help' || cmd === '-h') { console.log(HELP); return 0; }\n if (cmd === '--version' || cmd === '-v') { console.log(CLI_VERSION); return 0; }\n\n if (cmd === 'init') {\n const reset = argv.slice(1).includes('--reset');\n return initCommand(reset);\n }\n // `update` runs before the identity gate so a broken or stale install can fix itself.\n if (cmd === 'update') return updateCommand();\n\n // Every other command requires an identity. `init` and `update` are the only escape hatches.\n const identity = await loadIdentity();\n if (!identity) {\n console.error('Run `token-derby init` to set up your identity before using any other command.');\n return 1;\n }\n\n if (cmd === 'stable') {\n const sub = argv[1];\n if (sub === 'create') return stableCreateCommand();\n if (sub === 'list') return stableListCommand();\n if (sub === 'edit') return stableEditCommand(argv[2]);\n if (sub === 'delete') return stableDeleteCommand(argv[2]);\n console.error(`Unknown stable subcommand: ${sub ?? '(none)'}`);\n console.error('Try: stable create | stable list | stable edit <name> | stable delete <name>');\n return 2;\n }\n\n if (cmd === 'organisation' || cmd === 'org') {\n const sub = argv[1];\n if (sub === 'create') return orgCreateCommand();\n if (sub === 'join') return orgJoinCommand(argv[2]);\n if (sub === 'info') return orgInfoCommand(argv[2]);\n if (sub === 'list') return orgListCommand();\n if (sub === 'webhook') {\n const action = argv[2];\n if (action === 'set') return orgWebhookSetCommand(argv[3], argv[4]);\n if (action === 'get') return orgWebhookGetCommand(argv[3]);\n if (action === 'clear') return orgWebhookClearCommand(argv[3]);\n console.error(`Unknown webhook action: ${action ?? '(none)'}`);\n console.error('Try: organisation webhook set <name> <url> | organisation webhook get <name> | organisation webhook clear <name>');\n return 2;\n }\n console.error(`Unknown organisation subcommand: ${sub ?? '(none)'}`);\n console.error('Try: organisation create | organisation join <token> | organisation info <name> | organisation list | organisation webhook <set|get|clear> ...');\n return 2;\n }\n\n if (cmd === 'create') {\n const orgName = parseFlag(argv.slice(1), '--organisation');\n return createRaceCommand(orgName);\n }\n if (cmd === 'join') return joinCommand(argv[1]);\n if (cmd === 'end') return endCommand(argv[1]);\n\n console.error(`Unknown command: ${cmd}`);\n console.error(HELP);\n return 2;\n}\n\nfunction parseFlag(args: string[], flag: string): string | undefined {\n for (let i = 0; i < args.length; i++) {\n if (args[i] === flag) return args[i + 1];\n const eq = `${flag}=`;\n if (args[i]?.startsWith(eq)) return args[i]!.slice(eq.length);\n }\n return undefined;\n}\n\nmain().then(\n code => process.exit(code),\n err => {\n console.error(err?.stack ?? err);\n process.exit(1);\n },\n);\n"],"mappings":"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","names":["React","Box","Text","jsx","Box","Text","path","path","React","React","render","Box","Text","jsx","jsxs","render","React","Box","Text","React","render","render","React","readline","stdin","stdout","stdin","stdout","React","render","useState","Box","Text","useInput","jsx","jsxs","useState","useInput","Box","Text","fs","path","useState","Box","Text","Box","Text","jsx","jsxs","Box","Text","fs","path","stat","jsx","jsxs","useState","Box","Text","render","React","readline","stdin","stdout","stdin","stdout","readline","stdin","stdout","stdin","stdout","raw","v","readline","stdin","stdout","stdin","stdout","readline","stdin","stdout","stdin","stdout"]}
1
+ {"version":3,"sources":["../src/commands/stable-create.ts","../src/ui/HorseCreator.tsx","../src/ui/HorseSprite.tsx","../src/ui/sprite.ts","../src/ui/sprite-render.ts","../src/hats/render.ts","../src/ui/half-blocks.ts","../src/ui/palette.ts","../src/config.ts","../src/version.ts","../../shared/src/constants.ts","../../shared/src/version-match.ts","../../shared/src/levels.ts","../../shared/src/midrace.ts","../../shared/src/hats.ts","../src/identity/identity.ts","../src/paths.ts","../src/api/client.ts","../src/api/endpoints.ts","../src/commands/stable-list.tsx","../src/commands/stable-delete.ts","../src/commands/stable-edit.ts","../src/ui/HatPicker.tsx","../src/ui/AnimatedHorseSprite.tsx","../src/commands/create.ts","../src/commands/join.ts","../src/ui/HorsePicker.tsx","../src/stable/active-race.ts","../src/runtime/run-race.tsx","../src/ui/StatusScreen.tsx","../src/runtime/heartbeat-loop.ts","../src/tokens/transcripts.ts","../src/tokens/baseline.ts","../src/commands/end.ts","../src/commands/init.ts","../src/commands/update.ts","../src/commands/roll.ts","../src/ui/RollReveal.tsx","../src/ui/HatSprite.tsx","../src/ui/RollHorsePicker.tsx","../src/commands/org-create.ts","../src/commands/org-join.ts","../src/commands/org-list.ts","../src/commands/org-info.ts","../src/commands/org-webhook-set.ts","../src/commands/org-webhook-get.ts","../src/commands/org-webhook-clear.ts","../src/bin.ts"],"sourcesContent":["import React from 'react';\nimport { render } from 'ink';\nimport { HorseCreator } from '../ui/HorseCreator.js';\nimport { createStableHorse } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function stableCreateCommand(): Promise<number> {\n let exitCode = 0;\n const app = render(\n React.createElement(HorseCreator, {\n onSubmit: async (name, colors) => {\n try {\n await createStableHorse({ name, colors });\n app.unmount();\n console.log(`✓ Saved \"${name}\" to your stable.`);\n } catch (e) {\n app.unmount();\n if (e instanceof ApiError) {\n if (e.code === 'STABLE_HORSE_NAME_TAKEN') {\n console.error(`A horse named \"${name}\" already exists. Pick a different name or use \\`token-derby stable edit ${name}\\` to modify it.`);\n } else {\n console.error(`Error: ${e.code} ${e.message}`);\n }\n exitCode = 1;\n return;\n }\n throw e;\n }\n },\n onCancel: () => {\n app.unmount();\n console.log('Cancelled.');\n exitCode = 1;\n },\n }),\n );\n await app.waitUntilExit();\n return exitCode;\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport TextInput from 'ink-text-input';\nimport type { HorseColors } from '@token-derby/shared';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MAIN_SPRITE } from './sprite.js';\nimport { SLOTS, PALETTES, nextColor, prevColor, defaultColors, type Slot } from './palette.js';\n\ntype Props = {\n onSubmit: (name: string, colors: HorseColors) => void;\n onCancel: () => void;\n initialColors?: HorseColors;\n initialName?: string;\n lockName?: boolean;\n initialLevel?: number;\n};\n\nexport function HorseCreator({ onSubmit, onCancel, initialColors, initialName, lockName, initialLevel }: Props) {\n const [colors, setColors] = useState<HorseColors>(initialColors ?? defaultColors());\n const [slotIdx, setSlotIdx] = useState(0);\n const [namingMode, setNamingMode] = useState(false);\n const [name, setName] = useState(initialName ?? '');\n const [error, setError] = useState<string | null>(null);\n\n const slot: Slot = SLOTS[slotIdx]!;\n\n useInput((input, key) => {\n if (namingMode) return;\n if (key.escape) { onCancel(); return; }\n if (key.upArrow) { setSlotIdx((slotIdx - 1 + SLOTS.length) % SLOTS.length); return; }\n if (key.downArrow) { setSlotIdx((slotIdx + 1) % SLOTS.length); return; }\n if (key.leftArrow) { setColors({ ...colors, [slot]: prevColor(slot, colors[slot]) }); return; }\n if (key.rightArrow) { setColors({ ...colors, [slot]: nextColor(slot, colors[slot]) }); return; }\n if (key.return) {\n if (lockName) { onSubmit(initialName ?? '', colors); return; }\n setNamingMode(true);\n return;\n }\n });\n\n const handleNameSubmit = (value: string) => {\n if (!value.trim()) {\n setError('Name required');\n return;\n }\n onSubmit(value.trim(), colors);\n };\n\n return (\n <Box flexDirection=\"column\">\n {lockName && initialName && (\n <Box marginBottom={1}>\n <Text bold>{initialName}</Text>\n {typeof initialLevel === 'number' && (\n <Text color=\"cyan\"> [Lvl. {initialLevel}]</Text>\n )}\n </Box>\n )}\n\n <Box marginBottom={1}>\n <HorseSprite sprite={MAIN_SPRITE} colors={colors} />\n </Box>\n\n <Box flexDirection=\"column\">\n {SLOTS.map((s, i) => (\n <Text key={s}>\n {i === slotIdx ? '►' : ' '} {s.padEnd(7)} <Text color={colors[s]}>██</Text> {colors[s]}\n </Text>\n ))}\n </Box>\n\n {!namingMode && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text dimColor>↑/↓ select slot · ←/→ cycle color · Enter accept · Esc cancel</Text>\n </Box>\n )}\n\n {namingMode && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text>Name your horse: </Text>\n <TextInput value={name} onChange={(v) => { setName(v); setError(null); }} onSubmit={handleNameSubmit} />\n {error && <Text color=\"red\">{error}</Text>}\n </Box>\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { HorseColors, Hat } from '@token-derby/shared';\nimport { renderSprite, type Cell } from './sprite-render.js';\nimport type { SlotTag } from './sprite.js';\nimport { composeHatGrid } from '../hats/render.js';\nimport { ansiFg, ansiBg, hexGridToHalfBlocks } from './half-blocks.js';\n\ntype Props = {\n sprite: readonly (readonly SlotTag[])[];\n colors: HorseColors;\n hat?: { hat: Hat; variant?: number };\n};\n\nexport function HorseSprite({ sprite, colors, hat }: Props) {\n if (!hat) {\n const grid = renderSprite(sprite, colors);\n return (\n <Box flexDirection=\"column\">\n {grid.map((row, y) => (\n <Text key={y}>{rowToAnsi(row)}</Text>\n ))}\n </Box>\n );\n }\n\n const { grid } = composeHatGrid(sprite, hat.hat, hat.variant ?? 0, colors);\n const lines = hexGridToHalfBlocks(grid);\n return (\n <Box flexDirection=\"column\">\n {lines.map((line, i) => (\n <Text key={i}>{line}</Text>\n ))}\n </Box>\n );\n}\n\nconst RESET = '\\x1b[0m';\n\nfunction rowToAnsi(row: Cell[]): string {\n let out = '';\n for (const cell of row) {\n if (cell.top === null && cell.bottom === null) {\n out += ' ';\n } else if (cell.top !== null && cell.bottom !== null) {\n out += ansiFg(cell.top) + ansiBg(cell.bottom) + '▀' + RESET;\n } else if (cell.top !== null) {\n out += ansiFg(cell.top) + '▀' + RESET;\n } else {\n out += ansiFg(cell.bottom!) + '▄' + RESET;\n }\n }\n return out;\n}\n","// Pixel slot tags. `null` = transparent.\n// B = body, M = mane, T = tail, S = saddle, E = eye (fixed black), H = hoof (fixed dark)\nexport type SlotTag = 'B' | 'M' | 'T' | 'S' | 'E' | 'H' | null;\n\nexport const FIXED_COLORS = {\n E: '#000000',\n H: '#1F1108',\n} as const;\n\n// Each pair of adjacent rows is intentionally identical so every half-block\n// cell renders as a solid color. The only intentional split is the last row\n// (legs/hooves transition).\nconst MAIN_ROWS: readonly string[] = [\n '................................',\n '................................',\n '..........................MMM...',\n '..........................MMM...',\n '.........................MBBEBB.',\n '.........................MBBEBB.',\n '........................MBBBBBBB',\n '........................MBBBBBBB',\n '..................MMMMMMMBBB....',\n '..................MMMMMMMBBB....',\n '....BBBBBBBBSSSSSSMMBBBBBB......',\n '...BBBBBBBBBSSSSSSMMBBBBBB......',\n '.TTBBBBBBBBBSSSSSSBBBBBBBB......',\n '.TTBBBBBBBBBSSSSSSBBBBBBBB......',\n 'TTTBBBBBBBBBBBBBBBBBBBBBBB......',\n 'TTTBBBBBBBBBBBBBBBBBBBBB........',\n '...BBB.BBB.....BBB.BBB..........',\n '...BBB.BBB.....BBB.BBB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '....BB..BB......BB..BB..........',\n '...HHH.HHH.....HHH.HHH..........',\n];\n\nconst MINI_ROWS: readonly string[] = [\n '.BBSSMBB',\n '.BBSSMBB',\n 'TBBBBBB.',\n 'THH..HH.',\n];\n\nexport const MAIN_SPRITE: readonly (readonly SlotTag[])[] = parse(MAIN_ROWS, 32, 24);\nexport const MINI_SPRITE: readonly (readonly SlotTag[])[] = parse(MINI_ROWS, 8, 4);\n\nfunction parse(rows: readonly string[], width: number, height: number): SlotTag[][] {\n if (rows.length !== height) {\n throw new Error(`sprite has ${rows.length} rows, expected ${height}`);\n }\n return rows.map((row, y) => {\n if (row.length !== width) {\n throw new Error(`sprite row ${y} has length ${row.length}, expected ${width}`);\n }\n return [...row].map(c => toTag(c));\n });\n}\n\nfunction toTag(c: string): SlotTag {\n switch (c) {\n case 'B': return 'B';\n case 'M': return 'M';\n case 'T': return 'T';\n case 'S': return 'S';\n case 'E': return 'E';\n case 'H': return 'H';\n case '.': return null;\n default: throw new Error(`unknown sprite char: ${c}`);\n }\n}\n","import type { HorseColors } from '@token-derby/shared';\nimport { FIXED_COLORS, type SlotTag } from './sprite.js';\n\nexport type Cell = {\n top: string | null;\n bottom: string | null;\n};\n\nexport function renderSprite(\n sprite: readonly (readonly SlotTag[])[],\n colors: HorseColors,\n): Cell[][] {\n const out: Cell[][] = [];\n for (let y = 0; y + 1 < sprite.length || y < sprite.length; y += 2) {\n const topRow = sprite[y];\n const bottomRow = sprite[y + 1];\n if (!topRow) break;\n const row: Cell[] = [];\n for (let x = 0; x < topRow.length; x++) {\n row.push({\n top: tagColor(topRow[x] ?? null, colors),\n bottom: tagColor(bottomRow?.[x] ?? null, colors),\n });\n }\n out.push(row);\n if (!bottomRow) break;\n }\n return out;\n}\n\nfunction tagColor(tag: SlotTag, colors: HorseColors): string | null {\n if (tag === null) return null;\n if (tag === 'E') return FIXED_COLORS.E;\n if (tag === 'H') return FIXED_COLORS.H;\n if (tag === 'B') return colors.body;\n if (tag === 'M') return colors.mane;\n if (tag === 'T') return colors.tail;\n if (tag === 'S') return colors.saddle;\n return null;\n}\n","import type { Hat, HorseColors } from '@token-derby/shared';\nimport { FIXED_COLORS, type SlotTag } from '../ui/sprite.js';\n\nexport type HatGrid = {\n /** 2D array of hex colours (or null for transparent). Width = canvas width, height = HORSE_H + extension */\n grid: (string | null)[][];\n /** Leftmost x-coordinate in horse-coords (≤ 0). The horse starts at grid column = -offsetX. */\n offsetX: number;\n};\n\n/**\n * Compose a horse + hat into a single coloured grid.\n *\n * Overlap rule: the hat's bottom 4 rows overlap horse rows 0..3, so the hat\n * sits flush on the flat head (y=4), covering the mane. The canvas grows\n * vertically by `max(0, hat.rows.length - 4)` and horizontally to fit any\n * hat overhang past the 32-wide horse sprite.\n *\n * Pure function — no side effects, deterministic given inputs.\n */\nexport function composeHatGrid(\n baseSprite: readonly (readonly SlotTag[])[],\n hat: Hat,\n variantIdx: number,\n horseColors: HorseColors,\n): HatGrid {\n const horseH = baseSprite.length;\n const horseW = baseSprite[0]?.length ?? 0;\n const hatH = hat.rows.length;\n const hatW = hat.width;\n const ext = Math.max(0, hatH - 4);\n\n // Canvas dimensions accommodate hat overhang.\n const canvasLeft = Math.min(0, hat.anchor_x);\n const canvasRight = Math.max(horseW, hat.anchor_x + hatW);\n const canvasW = canvasRight - canvasLeft;\n const horseOffsetX = -canvasLeft;\n\n const grid: (string | null)[][] = Array.from(\n { length: horseH + ext },\n () => Array(canvasW).fill(null),\n );\n\n // Paint horse first, hat second. The hat overlays the horse in the 4-row\n // overlap zone (grid rows ext..ext+3 = horse rows 0..3) — this is exactly\n // the point of the overlap rule: the hat covers the top of the mane and\n // sits visibly on the flat head. Above the horse (grid rows 0..ext-1) only\n // the hat is painted; below (the rest of the body) only the horse is.\n for (let y = 0; y < horseH; y++) {\n for (let x = 0; x < horseW; x++) {\n const tag = baseSprite[y]![x];\n if (tag === null) continue;\n grid[y + ext]![x + horseOffsetX] = tagToColor(tag, horseColors);\n }\n }\n\n const hatColors = hatColorsFor(hat, variantIdx);\n for (let y = 0; y < hatH; y++) {\n const row = hat.rows[y]!;\n for (let x = 0; x < hatW; x++) {\n const ch = row[x];\n if (ch === '.' || ch === undefined) continue;\n const gx = hat.anchor_x + x + horseOffsetX;\n if (gx < 0 || gx >= canvasW) continue;\n const color = ch === 'A' ? hatColors.A : (hatColors.Q ?? hatColors.A);\n grid[y]![gx] = color;\n }\n }\n\n return { grid, offsetX: canvasLeft };\n}\n\nfunction tagToColor(tag: Exclude<SlotTag, null>, c: HorseColors): string {\n switch (tag) {\n case 'B': return c.body;\n case 'M': return c.mane;\n case 'T': return c.tail;\n case 'S': return c.saddle;\n case 'E': return FIXED_COLORS.E;\n case 'H': return FIXED_COLORS.H;\n }\n}\n\nfunction hatColorsFor(hat: Hat, variantIdx: number): { A: string; Q?: string } {\n if (hat.rarity === 'legendary') return hat.colors;\n return hat.variants[variantIdx] ?? hat.variants[0]!;\n}\n","const RESET = '\\x1b[0m';\n\nfunction hexToRgb(hex: string): [number, number, number] {\n const h = hex.replace('#', '');\n return [\n parseInt(h.slice(0, 2), 16),\n parseInt(h.slice(2, 4), 16),\n parseInt(h.slice(4, 6), 16),\n ];\n}\n\nexport function ansiFg(hex: string): string {\n const [r, g, b] = hexToRgb(hex);\n return `\\x1b[38;2;${r};${g};${b}m`;\n}\n\nexport function ansiBg(hex: string): string {\n const [r, g, b] = hexToRgb(hex);\n return `\\x1b[48;2;${r};${g};${b}m`;\n}\n\n/**\n * Convert a hex-colored grid (null = transparent) into half-block ANSI lines.\n * Two adjacent grid rows become one terminal line via the ▀ character.\n */\nexport function hexGridToHalfBlocks(grid: (string | null)[][]): string[] {\n const W = grid[0]?.length ?? 0;\n const padded = grid.length % 2 === 0 ? grid : [...grid, Array<string | null>(W).fill(null)];\n const lines: string[] = [];\n for (let y = 0; y < padded.length; y += 2) {\n let line = '';\n for (let x = 0; x < W; x++) {\n const top = padded[y]![x] ?? null;\n const bot = padded[y + 1]![x] ?? null;\n if (top === null && bot === null) line += ' ';\n else if (top !== null && bot !== null) line += ansiFg(top) + ansiBg(bot) + '▀' + RESET;\n else if (top !== null) line += ansiFg(top) + '▀' + RESET;\n else line += ansiFg(bot!) + '▄' + RESET;\n }\n lines.push(line);\n }\n return lines;\n}\n","import type { HorseColors } from '@token-derby/shared';\n\nexport type Slot = keyof HorseColors;\n\nexport const SLOTS: readonly Slot[] = ['body', 'mane', 'tail', 'saddle'] as const;\n\nexport const PALETTES: Record<Slot, readonly string[]> = {\n body: [\n '#8B4513', '#A0522D', '#D2691E', '#CD853F', '#DEB887', '#F5DEB3',\n '#FFFFFF', '#000000', '#4A2C2A', '#5D3A1A', '#704214', '#9C5919',\n '#B87333', '#E5B783', '#F0E1C9', '#2F1B0C',\n ],\n mane: [\n '#000000', '#1C1C1C', '#2F1B0C', '#4A2C2A', '#5D3A1A', '#8B4513',\n '#FFFFFF', '#F5F5DC', '#DEB887', '#CD853F', '#FF4500', '#B22222',\n '#191970', '#4B0082', '#2E8B57', '#FFD700',\n ],\n tail: [\n '#000000', '#1C1C1C', '#2F1B0C', '#4A2C2A', '#5D3A1A', '#8B4513',\n '#FFFFFF', '#F5F5DC', '#DEB887', '#CD853F', '#FF4500', '#B22222',\n '#191970', '#4B0082', '#2E8B57', '#FFD700',\n ],\n saddle: [\n '#C0392B', '#922B21', '#7B241C', '#641E16', '#1F618D', '#21618C',\n '#1B4F72', '#0E6655', '#117A65', '#196F3D', '#7D6608', '#9A7D0A',\n '#6E2C00', '#4D5656', '#212F3D', '#000000',\n ],\n};\n\nexport function nextColor(slot: Slot, current: string): string {\n const palette = PALETTES[slot];\n const idx = palette.indexOf(current);\n return palette[(idx + 1 + palette.length) % palette.length] ?? palette[0]!;\n}\n\nexport function prevColor(slot: Slot, current: string): string {\n const palette = PALETTES[slot];\n const idx = palette.indexOf(current);\n if (idx < 0) return palette[0]!;\n return palette[(idx - 1 + palette.length) % palette.length]!;\n}\n\nexport function defaultColors(): HorseColors {\n return {\n body: PALETTES.body[0]!,\n mane: PALETTES.mane[0]!,\n tail: PALETTES.tail[0]!,\n saddle: PALETTES.saddle[0]!,\n };\n}\n","export const DEFAULT_API_BASE = 'https://token-derby.mauricode.co.uk/api';\n\nexport function apiBase(): string {\n return process.env.TOKEN_DERBY_API_BASE ?? DEFAULT_API_BASE;\n}\n\nexport const HEARTBEAT_INTERVAL_MS = 60_000;\nexport const HEARTBEAT_RETRY_DELAYS_MS = [1_000, 2_000, 4_000, 8_000, 15_000];\n","import { createRequire } from 'node:module';\n\ndeclare const __CLI_VERSION__: string | undefined;\n\nfunction readVersion(): string {\n if (typeof __CLI_VERSION__ === 'string' && __CLI_VERSION__.length > 0) {\n return __CLI_VERSION__;\n }\n try {\n const req = createRequire(import.meta.url);\n const pkg = req('../package.json') as { version?: string };\n if (typeof pkg.version === 'string') return pkg.version;\n } catch {\n // fall through\n }\n return '0.0.0-dev';\n}\n\nexport const CLI_VERSION: string = readVersion();\n","export const DEFAULT_MAX_PARTICIPANTS = 30;\nexport const JOIN_CODE_LENGTH = 6;\nexport const JOIN_CODE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';\nexport const CLI_VERSION_HEADER = 'x-cli-version';\nexport const USER_ID_HEADER = 'x-user-id';\nexport const USER_NAME_HEADER = 'x-user-name';\nexport const USER_TOKEN_HEADER = 'x-user-token';\nexport const USER_NAME_MAX_LENGTH = 40;\nexport const SECRET_TOKEN_BYTES = 32;\nexport const ORG_NAME_MAX_LENGTH = 12;\nexport const ORG_NAME_PATTERN = /^[A-Za-z0-9]{1,12}$/;\n","export type ParsedSemver = { major: number; minor: number; patch: number };\n\nconst SEMVER_RE = /^(\\d+)\\.(\\d+)\\.(\\d+)(?:[-+].*)?$/;\n\nexport function parseSemver(v: string | undefined | null): ParsedSemver | null {\n if (typeof v !== 'string') return null;\n const m = SEMVER_RE.exec(v.trim());\n if (!m) return null;\n return {\n major: Number(m[1]),\n minor: Number(m[2]),\n patch: Number(m[3]),\n };\n}\n\nexport function minorMatches(a: string | undefined | null, b: string | undefined | null): boolean {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return false;\n return pa.major === pb.major && pa.minor === pb.minor;\n}\n\n/**\n * Returns true when `a` is the same as or newer than `b` by semver MAJOR.MINOR.PATCH.\n * Returns false if either side is unparseable.\n */\nexport function gteSemver(a: string | undefined | null, b: string | undefined | null): boolean {\n const pa = parseSemver(a);\n const pb = parseSemver(b);\n if (!pa || !pb) return false;\n if (pa.major !== pb.major) return pa.major > pb.major;\n if (pa.minor !== pb.minor) return pa.minor > pb.minor;\n return pa.patch >= pb.patch;\n}\n","/**\n * Horse XP / level curve.\n *\n * The cost (in XP) to advance from level `n` to level `n+1` is given by:\n *\n * xpForLevel(n) = 1.8 n^3 + 18 n^2 + 50 n − 19.8\n *\n * So the cumulative XP at which a horse becomes each level is:\n *\n * Level 1 → 0 (every new horse starts here at 0 XP)\n * Level 2 → xpForLevel(1) = 50\n * Level 3 → xpForLevel(2) = 166.6\n * Level 4 → xpForLevel(3) = 340.8\n * ...\n * Level 30 → xpForLevel(29) = 60,468.4\n *\n * To redesign the curve, edit `xpForLevel` below or bump `MAX_LEVEL`.\n * Levels are derived from XP — they are not stored on the horse, so changing\n * this file re-levels every horse without needing a migration.\n */\n\nexport const MAX_LEVEL = 30;\n\nexport function xpForLevel(n: number): number {\n return 1.8 * n ** 3 + 18 * n ** 2 + 50 * n - 19.8;\n}\n\n/**\n * Cumulative XP at which a horse first becomes `level`. Level 1 is the\n * starting state, so its threshold is 0.\n */\nexport function thresholdForLevel(level: number): number {\n if (level <= 1) return 0;\n return Math.round(xpForLevel(level - 1));\n}\n\n/**\n * Convenience: total XP thresholds for each level, in order.\n * `XP_THRESHOLDS[i]` is the cumulative XP needed to be level `i+1`.\n */\nexport const XP_THRESHOLDS: readonly number[] = Array.from(\n { length: MAX_LEVEL },\n (_, i) => thresholdForLevel(i + 1),\n);\n\nexport type LevelInfo = {\n level: number;\n xp: number;\n level_start_xp: number;\n next_level_xp: number | null;\n xp_into_level: number;\n xp_for_level: number | null;\n progress: number;\n};\n\nexport function levelFromXp(xp: number): number {\n const v = Math.max(0, Math.floor(xp));\n let level = 1;\n while (level < MAX_LEVEL && v >= thresholdForLevel(level + 1)) {\n level++;\n }\n return level;\n}\n\nexport function levelInfo(xp: number): LevelInfo {\n const v = Math.max(0, Math.floor(xp));\n const level = levelFromXp(v);\n const level_start_xp = thresholdForLevel(level);\n const isMax = level >= MAX_LEVEL;\n const next_level_xp = isMax ? null : thresholdForLevel(level + 1);\n const xp_into_level = v - level_start_xp;\n const xp_for_level = isMax ? null : (next_level_xp! - level_start_xp);\n const progress = isMax ? 1 : Math.min(1, xp_into_level / Math.max(1, xp_for_level!));\n return { level, xp: v, level_start_xp, next_level_xp, xp_into_level, xp_for_level, progress };\n}\n\n/**\n * XP awarded for finishing a race. Components stack:\n * compete → every horse that joined gets this\n * podium → top 3 finishers\n * runner_up → 2nd place\n * winner → 1st place\n *\n * So a winner gets compete + podium + winner = 80 XP.\n * Edit these values to retune.\n */\nexport const XP_AWARDS = {\n compete: 25,\n podium: 25,\n runner_up: 15,\n winner: 30,\n token_bonus_max: 15,\n} as const;\n\nexport function xpForRaceResult(rank: number): number {\n let xp = XP_AWARDS.compete;\n if (rank <= 3) xp += XP_AWARDS.podium;\n if (rank === 2) xp += XP_AWARDS.runner_up;\n if (rank === 1) xp += XP_AWARDS.winner;\n return xp;\n}\n\n/**\n * Token-proportional XP bonus, layered on top of {@link xpForRaceResult}.\n * Winner always gets the full `token_bonus_max` (15).\n * Everyone else gets `round(tokens / winner_tokens * token_bonus_max)`.\n * Falls back to 0 if `winner_tokens` is non-positive (degenerate race).\n */\nexport function xpForTokenBonus(rank: number, tokens: number, winner_tokens: number): number {\n if (rank === 1) return XP_AWARDS.token_bonus_max;\n if (winner_tokens <= 0) return 0;\n const ratio = Math.max(0, tokens) / winner_tokens;\n return Math.round(Math.min(1, ratio) * XP_AWARDS.token_bonus_max);\n}\n\n// Total XP a horse earns from a finished race: rank bonus + token bonus + any\n// live XP it already banked during the race.\nexport function xpForRaceFinish(\n rank: number,\n tokens: number,\n winner_tokens: number,\n live_xp: number | undefined = 0,\n): number {\n return xpForRaceResult(rank) + xpForTokenBonus(rank, tokens, winner_tokens) + (live_xp ?? 0);\n}\n","export const ACHIEVEMENT_NAMES = [\n 'Racer!',\n 'Overtake!',\n 'Pacesetter!',\n 'Stampede!',\n 'Took the lead!',\n 'Comeback!',\n 'Pulled Away!',\n] as const;\n\nexport type AchievementName = typeof ACHIEVEMENT_NAMES[number];\n\nexport const ACHIEVEMENT_DESCRIPTIONS: Record<AchievementName, string> = {\n 'Racer!': 'Raced continuously for an hour',\n 'Overtake!': 'Overtook another horse',\n 'Pacesetter!': 'Led the race for an hour straight',\n 'Stampede!': 'Gained 7,000+ tokens in a single minute',\n 'Took the lead!': 'Charged into first place',\n 'Comeback!': 'Climbed from last place to the top half',\n 'Pulled Away!': 'Grew the lead by 5,000+ tokens in a minute',\n};\n\n// Describe an Overtake! event with multi-position climb.\nexport function overtakeDescription(positionsClimbed: number): string {\n if (positionsClimbed <= 1) return 'Overtook another horse';\n return `Overtook ${positionsClimbed} horses`;\n}\n\n// Multiplier applied to token thresholds (Stampede!, Pulled Away!, rate cap)\n// when a race counts input+output. Calibrated against real Claude Code\n// transcripts: with cache_read_input_tokens excluded (they're passive,\n// reflect context size rather than work), the aggregate ratio of\n// (fresh_input + cache_creation + output) / output is ~8x. Set to 10 so the\n// rate cap clears all but the busiest peak minutes (~p90).\nexport const TOKEN_INPUT_MULTIPLIER = 10;\n\nexport function tokenMultiplier(race: { counts_input?: boolean }): number {\n return race.counts_input ? TOKEN_INPUT_MULTIPLIER : 1;\n}\n\n// Race-aware description for an event. Stampede!/Pulled Away! report their\n// scaled thresholds for input+output races; everything else is static.\nexport function describeAchievement(\n event: { name: AchievementName; xp: number },\n race: { counts_input?: boolean },\n): string {\n if (event.name === 'Overtake!') {\n return overtakeDescription(Math.floor(event.xp / 3));\n }\n const m = tokenMultiplier(race);\n if (event.name === 'Stampede!') {\n return `Gained ${(MIDRACE_THRESHOLDS.stampede_tokens * m).toLocaleString('en-US')}+ tokens in a single minute`;\n }\n if (event.name === 'Pulled Away!') {\n return `Grew the lead by ${(MIDRACE_THRESHOLDS.pulled_away_gap * m).toLocaleString('en-US')}+ tokens in a minute`;\n }\n return ACHIEVEMENT_DESCRIPTIONS[event.name];\n}\n\nexport const MIDRACE_XP = {\n racer: 1,\n overtake: 3,\n pacesetter: 3,\n stampede: 2,\n took_lead: 5,\n comeback: 5,\n pulled_away: 3,\n} as const;\n\nexport const MIDRACE_CAPS = {\n racer_awards: 5,\n overtake_awards: 5,\n pacesetter_awards: 3,\n lead_take_awards: 3,\n // Stampede! and Pulled Away! are cooldown-based, not per-race-capped.\n // Comeback! is tracked as a boolean (comeback_awarded) — not a counter.\n} as const;\n\nexport const MIDRACE_THRESHOLDS = {\n warm_up_fraction: 0.08, // first 8% of race time\n streak_hour_ms: 3_600_000, // 1 hour for Racer!/Pacesetter!\n racer_dt_cap_ms: 90_000, // single-tick credit cap for Racer!\n stampede_tokens: 7_000, // tokens-in-a-minute threshold\n stampede_cooldown_ms: 7_200_000, // 2 hours\n pulled_away_gap: 5_000, // gap-growth threshold per minute\n pulled_away_cooldown_ms: 7_200_000, // 2 hours\n recent_events_retention_ms: 90_000, // sliding window for recent_events\n} as const;\n\nexport type RecentEvent = {\n at: number;\n name: AchievementName;\n xp: number;\n};\n","// Cosmetic hat catalog. Each hat ships with one or more colour variants\n// (legendary hats are exceptions — single design, animated). The roll\n// handler picks rarity tier → hat → variant uniformly. Catalog is edited\n// via `tools/hat-editor/index.html` and exported to this file by\n// pasting the result over the HATS array.\n\nimport type { Hat, HatId } from './types.js';\n\nexport function hatById(id: HatId): Hat | undefined {\n return HATS.find(h => h.id === id);\n}\n\nexport const HATS: Hat[] = [\n // ── COMMON (18) ────────────────────────────────────────────────────────\n { id: 'flat_cap', name: \"Flat Cap\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...........','....AAAA...','...AAAAAA..','..AAAAAAA..'], variants: [{ A: '#8B6914' }, { A: '#12301b' }, { A: '#aab5cb' }, { A: '#bdcbaa' }] },\n { id: 'bucket_hat', name: \"Bucket Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...QQQQQ...','...AAAAA...','...AAAAA...','.AAAAAAAAA.'], variants: [{ A: '#CC2200', Q: '#FFFFFF' }, { A: '#0007cc', Q: '#FFFFFF' }, { A: '#becc00', Q: '#4d3dc7' }, { A: '#cc00c5', Q: '#d6d6dc' }] },\n { id: 'beanie', name: \"Beanie\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','....AAA....','...AAAAA...','...AAAAA...','..AAAAAAA..'], variants: [{ A: '#4A7C59' }, { A: '#b21f35' }, { A: '#ec9418' }, { A: '#3a17e6' }] },\n { id: 'stetson', name: \"Stetson\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...AA.AA...','...AAAAA...','...AAAAA...','A..AAAAA..A','AAAAAAAAAAA','AAAAAAAAAAA'], variants: [{ A: '#C49A00' }, { A: '#272004' }, { A: '#040404' }, { A: '#373606' }] },\n { id: 'party_hat', name: \"Party Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','.....A.....','....AAA....','....AQA....','...AQAQA...','...AAAAA...'], variants: [{ A: '#FF69B4', Q: '#FFD700' }, { A: '#c46bff', Q: '#ff000d' }, { A: '#fdff6b', Q: '#0400ff' }, { A: '#6bff97', Q: '#05050a' }] },\n { id: 'fez', name: \"Fez\", rarity: 'common', width: 11, anchor_x: 22, rows: ['...........','...........','...........','...........','...........','...........','....Q......','....AAA....','....AAA....','....AAA....'], variants: [{ A: '#CC0000', Q: '#8B0000' }, { A: '#CC0000', Q: '#f5e5e5' }, { A: '#CC0000', Q: '#f1e209' }, { A: '#CC0000', Q: '#0956f1' }] },\n { id: 'sailor_hat', name: \"Sailor Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...QQQQQ...','..AAAAAAA..','..QQQQQQQ..','..AAAAAAA..'], variants: [{ A: '#FFFFFF', Q: '#000080' }, { A: '#FFFFFF', Q: '#c0c0ed' }, { A: '#FFFFFF', Q: '#00000a' }, { A: '#FFFFFF', Q: '#0505ef' }] },\n { id: 'newsboy_cap', name: \"Newsboy Cap\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...AAAAA...','..AAAQAAA..','..AAAAAAA..','..AAAAAA...'], variants: [{ A: '#5C4033', Q: '#3D2B1F' }, { A: '#e96020', Q: '#131211' }, { A: '#342c28', Q: '#131211' }, { A: '#0a0300', Q: '#ddab78' }] },\n { id: 'tam_o_shanter', name: \"Tam O'Shanter\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','.....Q.....','....AAA....','..AAAAAAA..','..AAAAAAA..','...AAAAA...'], variants: [{ A: '#006400', Q: '#FF0000' }, { A: '#ff0000', Q: '#016400' }] },\n { id: 'trucker_cap', name: \"Trucker Cap\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...AAQQ....','...AAQQ....','..AAQQQAA..','..AAQQQAA..'], variants: [{ A: '#2196F3', Q: '#FFFFFF' }, { A: '#f41fe3', Q: '#FFFFFF' }, { A: '#1ff45f', Q: '#FFFFFF' }] },\n { id: 'hard_hat', name: \"Hard Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','....AAA....','...AAAAA...','..AAAAAAA..','..AAAAAAAAA'], variants: [{ A: '#FFD600' }, { A: '#d74c1d' }] },\n { id: 'chef_toque', name: \"Chef's Toque\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...AAAAA...','..AAQAQAA..','...AQAQA...','...AQAQA...','...AQAQA...','...AAAAA...'], variants: [{ A: '#FFFFFF', Q: '#f9f9f9' }] },\n { id: 'bobble_hat', name: \"Bobble Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','.....Q.....','...AAAAA...','...AAAAA...','..AAAAAAA..'], variants: [{ A: '#C62828', Q: '#FFFFFF' }, { A: '#293bc7', Q: '#FFFFFF' }, { A: '#29c775', Q: '#231f1f' }, { A: '#a529c7', Q: '#d50707' }] },\n { id: 'cowboy_hat', name: \"Cowboy Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...AAAAA...','...AAAAA...','A.AAAAAAA.A','.AAAAAAAAA.'], variants: [{ A: '#8B4513' }, { A: '#0a0400' }, { A: '#956c50' }] },\n { id: 'baseball_cap', name: \"Baseball Cap\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','...AAAAA...','..AAAAAA...','..AAAAAAA..','..AAAAAAAAA'], variants: [{ A: '#1565C0' }, { A: '#8515c1' }, { A: '#15c157' }, { A: '#ef2d0b' }] },\n { id: 'tinfoil_hat', name: \"Tinfoil Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','.....A.....','....AAA....','...AAAAA...','..AAAAAAA..'], variants: [{ A: '#B0BEC5' }, { A: '#6a6c6c' }] },\n { id: 'dunce_cap', name: \"Dunce Cap\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','.....Q.....','....QAQ....','...QAAAQ...','...QAAAQ...','..QAAAAAQ..','..AAAAAAA..'], variants: [{ A: '#F8F8F8', Q: '#F44336' }] },\n { id: 'mini_top_hat', name: \"Mini Top Hat\", rarity: 'common', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...AAAAA...','...AAAAA...','...AAAAA...','..AAAAAAA..','..AAAAAAA..'], variants: [{ A: '#212121' }, { A: '#626060' }] },\n // ── RARE (10) ──────────────────────────────────────────────────────────\n { id: 'bicorne', name: \"Bicorne\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','..AAAQQQQ..','..AAAAAAA..','..AAAAAAA..','...QQQQQ...'], variants: [{ A: '#1A237E', Q: '#FFD700' }, { A: '#01052d', Q: '#544803' }] },\n { id: 'viking_helmet', name: \"Viking Helmet\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','..A.AAA.A..','..AAAAAAA..','..AAAAAAA..','..AQQQQQA..'], variants: [{ A: '#9E9E9E', Q: '#8D6E63' }, { A: '#dcdbdb', Q: '#bf3908' }] },\n { id: 'jesters_cap', name: \"Jester's Cap\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','..AQAQAQA..','..AQAQAQA..','...AAAAA...','...AAAAA...'], variants: [{ A: '#E53935', Q: '#FFD600' }, { A: '#e5a434', Q: '#0040ff' }, { A: '#34e537', Q: '#eeff00' }, { A: '#e234e5', Q: '#00ff40' }] },\n { id: 'plague_doctor', name: \"Plague Doctor Beak\", rarity: 'rare', width: 11, anchor_x: 24, rows: ['...........','...........','...........','...........','....QQQ....','...QAAAQQ..','...QQQQQQQ.','..QQQQQ.QQQ','..QQQQ....Q','..QQQQ.....'], variants: [{ A: '#F5F5F5', Q: '#795548' }, { A: '#e1dbdb', Q: '#080707' }] },\n { id: 'morion', name: \"Conquistador Morion\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','.....Q.....','...QQQQQ...','...QAAAQ...','.A..AAA..A.','..AAQQQAA..'], variants: [{ A: '#B0BEC5', Q: '#FFD600' }, { A: '#0a4768', Q: '#e6c10a' }] },\n { id: 'shako', name: \"Shako\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','........Q..','........Q..','........Q..','........Q..','..AAAAAAA..','..AAAAAAA..','..AAAAAAA..','..AQQQQQA..'], variants: [{ A: '#45464f', Q: '#00ff2a' }, { A: '#45464f', Q: '#ff4d00' }, { A: '#45464f', Q: '#ff0019' }, { A: '#45464f', Q: '#fff700' }] },\n { id: 'centurion_helm', name: \"Centurion Helm\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','....QQQ....','...QQQQQQ..','..QQQQQQQQ.','.QQ..A...Q.','.Q..AAA....','...AAAAA...','..AAAAAAA..','..AAAAAAA..'], variants: [{ A: '#B0BEC5', Q: '#C62828' }, { A: '#2f3131', Q: '#C62828' }] },\n { id: 'papal_mitre', name: \"Papal Mitre\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','....QQQ....','...QQQQQ...','...QAAAQ...','..AAAAAAA..'], variants: [{ A: '#FFFFFF', Q: '#FFD700' }] },\n { id: 'headdress', name: \"Headdress\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','...........','..AQAQAQA..','..AQAQAQA..','..AAAAAAA..','...QQQQQ...'], variants: [{ A: '#FF8F00', Q: '#1565C0' }] },\n { id: 'sombrero', name: \"Sombrero\", rarity: 'rare', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...........','.....A.....','....AAA....','...AAAAA...','...AQAQA...','AAAAAAAAAAA'], variants: [{ A: '#F57F17', Q: '#BF360C' }, { A: '#f8b377', Q: '#3e1204' }, { A: '#d6f877', Q: '#04133e' }, { A: '#d6f877', Q: '#04133e' }] },\n // ── EPIC (6) ───────────────────────────────────────────────────────────\n { id: 'papal_tiara', name: \"Papal Tiara\", rarity: 'epic', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','....QQ.....','...QQQQQ...','...QAAQQ...','...QQQQQ...','..AAAAAAA..','..AQQQQQA..'], variants: [{ A: '#FFFFFF', Q: '#FFD700' }, { A: '#b18e10', Q: '#f3f3f1' }] },\n { id: 'samurai_kabuto', name: \"Samurai Kabuto\", rarity: 'epic', width: 11, anchor_x: 23, rows: ['....Q...Q..','....QQ.QQ..','.....QQQ...','.......Q...','...AAAAQ...','..AAAAAQQ..','..AAAAAQQ..','.AAAAAAAQ..','AAAAAAAAQ..','AAAAAAAAQ..'], variants: [{ A: '#B0BEC5', Q: '#C62828' }, { A: '#050505', Q: '#C62828' }, { A: '#675f5f', Q: '#c4c729' }] },\n { id: 'gladiator_galea', name: \"Gladiator Galea\", rarity: 'epic', width: 11, anchor_x: 23, rows: ['...........','...........','...........','....QQQQQQ.','...QQQQQ...','...QQQQQ...','...QAAA....','..AAAAAAA..','..AAAAAAA..','..AQQQQQA..'], variants: [{ A: '#B0BEC5', Q: '#C62828' }, { A: '#ffe907', Q: '#C62828' }] },\n { id: 'pharaoh_nemes', name: \"Pharaoh Nemes\", rarity: 'epic', width: 11, anchor_x: 23, rows: ['...........','...........','...........','..AAAAAAA..','..AAQAQAA..','..QAQAQAQ..','..QAQAQAQ..','..QQAAAQQ..','..QQAAAAA..','...QAQA....'], variants: [{ A: '#FFD700', Q: '#1565C0' }, { A: '#8d342a', Q: '#63686e' }] },\n { id: 'spartan_helmet', name: \"Spartan Helmet\", rarity: 'epic', width: 11, anchor_x: 23, rows: ['...........','........Q..','.......QQ..','.....QQQQ..','....QQQQQ..','..QQQQQQ...','.QQQAA.....','QQAAAAAAA..','Q.AAAAAAA..','..AQQQQQA..'], variants: [{ A: '#B0BEC5', Q: '#B71C1C' }, { A: '#B0BEC5', Q: '#b2b51c' }, { A: '#B0BEC5', Q: '#b5611c' }] },\n { id: 'conquistador_full', name: \"Conquistador Helm\", rarity: 'epic', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','.....A.....','....AAA....','...AAAAA...','..AAAAAAA..','...AQQQA...','...AQQQA...'], variants: [{ A: '#B0BEC5', Q: '#FFD700' }, { A: '#B0BEC5', Q: '#0040ff' }, { A: '#B0BEC5', Q: '#36123b' }] },\n // ── LEGENDARY (5) ──────────────────────────────────────────────────────\n { id: 'rainbow_crown', name: \"Rainbow Crown\", rarity: 'legendary', width: 11, anchor_x: 23, rows: ['...........','...........','.....A.....','....AQA....','....AQA....','....AQA....','...AAQAA...','...AQQQA...','..AAQQQAA..','..AAAAAAA..'], colors: { A: '#FFD700', Q: '#553f3f' }, animation: { type: 'cycle', frames: ['#FF0000','#FF7F00','#FFFF00','#00FF00','#0000FF','#8B00FF'], fps: 8 } },\n { id: 'inferno_cap', name: \"Inferno Cap\", rarity: 'legendary', width: 11, anchor_x: 23, rows: ['...........','....AAA....','...AAAAA...','....AAA....','.....Q.....','A....Q....A','A...QQQ...A','.A..QQQ..A.','..AAAAAAA..','..AAAAAAA..'], colors: { A: '#FF4500', Q: '#FFD700' }, animation: { type: 'cycle', frames: ['#FF0000','#FF2200','#FF4500','#FF6600','#FF8C00','#FFA500'], fps: 12 } },\n { id: 'void_hood', name: \"Void Hood\", rarity: 'legendary', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...AAA.....','..AAAAAA...','.AAAAAAA...','.AAAAAAAA..','AAAAAAAAA..','AAAAQQQAA..','AAAAQQQAA..'], colors: { A: '#1A0033', Q: '#d9cfe3' }, animation: { type: 'cycle', frames: ['#0D0019','#1A0033','#2D004D','#3D0066','#2D004D','#1A0033'], fps: 3 } },\n { id: 'prismatic_jester', name: \"Prismatic Jester\", rarity: 'legendary', width: 11, anchor_x: 23, rows: ['...........','..Q.Q.Q.Q..','Q..A.A.A..Q','.Q.A.A.A.Q.','..AQAQAQA..','..AQAQAQA..','..AAAAAAA..','..AAAAAAA..','..AAAAAAA..','..AAAAAAA..'], colors: { A: '#FF0000', Q: '#0000FF' }, animation: { type: 'cycle', frames: ['#FF0000','#FF7F00','#FFFF00','#00FF00','#0000FF','#8B00FF','#FF00FF','#00FFFF'], fps: 15 } },\n { id: 'aurora_helm', name: \"Aurora Helm\", rarity: 'legendary', width: 11, anchor_x: 23, rows: ['...........','...........','...........','...........','...QQQQQ...','...QQQQQ...','..AAAAAAA..','..AAAAAAA..','..AQAAAQA..','..AQAAAQA..'], colors: { A: '#00CED1', Q: '#00FF7F' }, animation: { type: 'cycle', frames: ['#0000FF','#0066FF','#00BFFF','#00CED1','#00FF7F','#7CFC00','#00FF7F','#00CED1'], fps: 4 } },\n];\n","import { promises as fs } from 'node:fs';\nimport * as path from 'node:path';\nimport { USER_NAME_MAX_LENGTH } from '@token-derby/shared';\nimport { identityFile, homeDir } from '../paths.js';\n\nexport type Identity = {\n user_id: string;\n display_name: string;\n secret_token: string;\n created_at: string;\n};\n\nexport async function loadIdentity(): Promise<Identity | null> {\n try {\n const raw = await fs.readFile(identityFile(), 'utf8');\n const parsed = JSON.parse(raw) as Partial<Identity>;\n if (\n typeof parsed.user_id === 'string' &&\n typeof parsed.display_name === 'string' &&\n typeof parsed.secret_token === 'string' &&\n typeof parsed.created_at === 'string'\n ) {\n return parsed as Identity;\n }\n return null;\n } catch (e: any) {\n if (e?.code === 'ENOENT') return null;\n return null;\n }\n}\n\nexport async function saveIdentity(identity: Identity): Promise<void> {\n await fs.mkdir(homeDir(), { recursive: true });\n await fs.writeFile(identityFile(), JSON.stringify(identity, null, 2) + '\\n', 'utf8');\n}\n\nexport async function deleteIdentity(): Promise<void> {\n try {\n await fs.unlink(identityFile());\n } catch (e: any) {\n if (e?.code !== 'ENOENT') throw e;\n }\n}\n\nexport function validateDisplayName(name: string): { ok: true; name: string } | { ok: false; error: string } {\n const trimmed = name.trim();\n if (trimmed.length < 1) return { ok: false, error: 'Name cannot be empty.' };\n if (trimmed.length > USER_NAME_MAX_LENGTH) {\n return { ok: false, error: `Name must be ${USER_NAME_MAX_LENGTH} characters or fewer.` };\n }\n return { ok: true, name: trimmed };\n}\n\nexport function identityFilePath(): string {\n return identityFile();\n}\n\nexport function identityFileDir(): string {\n return path.dirname(identityFile());\n}\n","import * as os from 'node:os';\nimport * as path from 'node:path';\n\nexport function homeDir(): string {\n return process.env.TOKEN_DERBY_HOME ?? path.join(os.homedir(), '.token-derby');\n}\n\nexport function identityFile(): string {\n return path.join(homeDir(), 'identity.json');\n}\n\nexport function activeRaceFile(joinCode: string): string {\n return path.join(homeDir(), 'active-races', `${joinCode}.json`);\n}\n\nexport function activeRacesDir(): string {\n return path.join(homeDir(), 'active-races');\n}\n\nexport function claudeProjectsDir(): string {\n return process.env.TOKEN_DERBY_CLAUDE_DIR ?? path.join(os.homedir(), '.claude', 'projects');\n}\n","import { apiBase } from '../config.js';\nimport { CLI_VERSION } from '../version.js';\nimport { CLI_VERSION_HEADER, USER_ID_HEADER, USER_TOKEN_HEADER } from '@token-derby/shared';\nimport { loadIdentity, type Identity } from '../identity/identity.js';\n\nexport type ApiErrorCode =\n | 'RACE_NOT_FOUND'\n | 'RACE_FULL'\n | 'RACE_FINISHED'\n | 'INVALID_TOKEN'\n | 'RATE_LIMITED'\n | 'BAD_REQUEST'\n | 'VERSION_MISMATCH'\n | 'IDENTITY_REQUIRED'\n | 'DUPLICATE_HORSE'\n | 'ORG_NAME_TAKEN'\n | 'ORG_NOT_FOUND'\n | 'NOT_ORG_MEMBER'\n | 'UNAUTHENTICATED'\n | 'STABLE_HORSE_NOT_FOUND'\n | 'STABLE_HORSE_NAME_TAKEN'\n | 'NETWORK_ERROR';\n\nexport class ApiError extends Error {\n constructor(\n readonly code: ApiErrorCode,\n message: string,\n readonly status: number,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ntype FetchFn = typeof fetch;\n\nlet identityCache: Promise<Identity | null> | null = null;\nfunction getIdentity(): Promise<Identity | null> {\n if (!identityCache) identityCache = loadIdentity();\n return identityCache;\n}\n\n// Tests can reset the cached identity.\nexport function _resetIdentityCacheForTests(): void {\n identityCache = null;\n}\n\nexport async function request<T>(\n method: string,\n path: string,\n body: unknown,\n horseAuthToken: string | undefined,\n fetchImpl: FetchFn = fetch,\n): Promise<T> {\n const url = path.startsWith('http') ? path : `${apiBase()}${path}`;\n const headers: Record<string, string> = {};\n headers[CLI_VERSION_HEADER] = CLI_VERSION;\n headers['user-agent'] = `token-derby/${CLI_VERSION}`;\n const identity = await getIdentity();\n if (identity) {\n headers[USER_ID_HEADER] = identity.user_id;\n headers[USER_TOKEN_HEADER] = identity.secret_token;\n }\n if (horseAuthToken) headers['authorization'] = `Bearer ${horseAuthToken}`;\n if (body !== undefined) headers['content-type'] = 'application/json';\n\n let res: Awaited<ReturnType<FetchFn>>;\n try {\n res = await fetchImpl(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n });\n } catch (e: any) {\n throw new ApiError('NETWORK_ERROR', e?.message ?? 'fetch failed', 0);\n }\n\n const text = await res.text();\n const contentType = res.headers.get('content-type') ?? '';\n let parsed: any = null;\n if (contentType.includes('application/json') && text.length > 0) {\n try {\n parsed = JSON.parse(text);\n } catch {\n parsed = null;\n }\n }\n\n if (!res.ok) {\n if (parsed && typeof parsed.code === 'string') {\n throw new ApiError(parsed.code as ApiErrorCode, parsed.message ?? 'API error', res.status);\n }\n throw new ApiError('NETWORK_ERROR', `HTTP ${res.status}`, res.status);\n }\n\n return parsed as T;\n}\n","import type {\n CreateRaceRequest, CreateRaceResponse,\n GetRaceResponse, JoinRaceRequest, JoinRaceResponse,\n HeartbeatRequest, HeartbeatResponse, EndRaceResponse,\n CreateOrganisationRequest, CreateOrganisationResponse,\n JoinOrganisationRequest, JoinOrganisationResponse,\n ListOrganisationsResponse, GetOrganisationResponse,\n InitJockeyRequest, InitJockeyResponse,\n GetJockeyResponse, UpdateJockeyRequest, UpdateJockeyResponse,\n ListStableResponse, CreateStableHorseRequest, CreateStableHorseResponse,\n UpdateStableHorseRequest, UpdateStableHorseResponse, DeleteStableHorseResponse,\n SetOrgWebhookRequest, SetOrgWebhookResponse,\n GetOrgWebhookResponse, DeleteOrgWebhookResponse,\n RollHatResponse, EquipHatRequest, EquipHatResponse,\n} from '@token-derby/shared';\nimport { request } from './client.js';\n\nexport function createRace(body: CreateRaceRequest) {\n return request<CreateRaceResponse>('POST', '/races', body, undefined);\n}\n\nexport function getRace(joinCode: string) {\n return request<GetRaceResponse>('GET', `/races/${encodeURIComponent(joinCode)}`, undefined, undefined);\n}\n\nexport function joinRace(joinCode: string, body: JoinRaceRequest) {\n return request<JoinRaceResponse>('POST', `/races/${encodeURIComponent(joinCode)}/join`, body, undefined);\n}\n\nexport function heartbeat(joinCode: string, horseId: string, token: string, body: HeartbeatRequest) {\n return request<HeartbeatResponse>(\n 'POST',\n `/races/${encodeURIComponent(joinCode)}/horses/${encodeURIComponent(horseId)}/heartbeat`,\n body,\n token,\n );\n}\n\nexport function endRace(adminCode: string) {\n return request<EndRaceResponse>('DELETE', `/races/admin/${encodeURIComponent(adminCode)}`, undefined, undefined);\n}\n\nexport function createOrganisation(body: CreateOrganisationRequest) {\n return request<CreateOrganisationResponse>('POST', '/organisations', body, undefined);\n}\n\nexport function joinOrganisation(body: JoinOrganisationRequest) {\n return request<JoinOrganisationResponse>('POST', '/organisations/join', body, undefined);\n}\n\nexport function listOrganisations() {\n return request<ListOrganisationsResponse>('GET', '/organisations', undefined, undefined);\n}\n\nexport function getOrganisation(name: string) {\n return request<GetOrganisationResponse>('GET', `/organisations/${encodeURIComponent(name)}`, undefined, undefined);\n}\n\nexport function initJockey(body: InitJockeyRequest) {\n return request<InitJockeyResponse>('POST', '/jockey/init', body, undefined);\n}\n\nexport function getJockey() {\n return request<GetJockeyResponse>('GET', '/jockey/me', undefined, undefined);\n}\n\nexport function updateJockey(body: UpdateJockeyRequest) {\n return request<UpdateJockeyResponse>('PUT', '/jockey/me', body, undefined);\n}\n\nexport function listStable() {\n return request<ListStableResponse>('GET', '/jockey/me/horses', undefined, undefined);\n}\n\nexport function createStableHorse(body: CreateStableHorseRequest) {\n return request<CreateStableHorseResponse>('POST', '/jockey/me/horses', body, undefined);\n}\n\nexport function updateStableHorse(stableHorseId: string, body: UpdateStableHorseRequest) {\n return request<UpdateStableHorseResponse>(\n 'PUT',\n `/jockey/me/horses/${encodeURIComponent(stableHorseId)}`,\n body,\n undefined,\n );\n}\n\nexport function deleteStableHorse(stableHorseId: string) {\n return request<DeleteStableHorseResponse>(\n 'DELETE',\n `/jockey/me/horses/${encodeURIComponent(stableHorseId)}`,\n undefined,\n undefined,\n );\n}\n\nexport function setOrgWebhook(orgName: string, body: SetOrgWebhookRequest) {\n return request<SetOrgWebhookResponse>(\n 'PUT',\n `/organisations/${encodeURIComponent(orgName)}/webhook`,\n body,\n undefined,\n );\n}\n\nexport function getOrgWebhook(orgName: string) {\n return request<GetOrgWebhookResponse>(\n 'GET',\n `/organisations/${encodeURIComponent(orgName)}/webhook`,\n undefined,\n undefined,\n );\n}\n\nexport function deleteOrgWebhook(orgName: string) {\n return request<DeleteOrgWebhookResponse>(\n 'DELETE',\n `/organisations/${encodeURIComponent(orgName)}/webhook`,\n undefined,\n undefined,\n );\n}\n\nexport function rollHat(stableHorseId: string) {\n return request<RollHatResponse>('POST', `/jockey/me/horses/${encodeURIComponent(stableHorseId)}/roll`, undefined, undefined);\n}\n\nexport function equipHat(stableHorseId: string, body: EquipHatRequest) {\n return request<EquipHatResponse>('POST', `/jockey/me/horses/${encodeURIComponent(stableHorseId)}/equip`, body, undefined);\n}\n","import React from 'react';\nimport { render, Box, Text } from 'ink';\nimport type { StableHorse } from '@token-derby/shared';\nimport { levelFromXp } from '@token-derby/shared';\nimport { listStable } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\nimport { HorseSprite } from '../ui/HorseSprite.js';\nimport { MINI_SPRITE } from '../ui/sprite.js';\n\nexport async function stableListCommand(): Promise<number> {\n let horses: StableHorse[];\n try {\n const resp = await listStable();\n horses = resp.horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n\n if (horses.length === 0) {\n console.log('Your stable is empty. Run `token-derby stable create` to add a horse.');\n return 0;\n }\n const app = render(\n React.createElement(StableList, { horses }),\n );\n await app.waitUntilExit();\n return 0;\n}\n\nfunction StableList({ horses }: { horses: StableHorse[] }) {\n React.useEffect(() => {\n setImmediate(() => process.exit(0));\n }, []);\n return (\n <Box flexDirection=\"column\">\n <Text bold>Your stable ({horses.length}):</Text>\n {horses.map(h => (\n <Box key={h.stable_horse_id} flexDirection=\"row\" marginTop={1}>\n <HorseSprite sprite={MINI_SPRITE} colors={h.colors} />\n <Text> {h.name} <Text color=\"cyan\">[Lvl. {levelFromXp(h.xp)}]</Text></Text>\n </Box>\n ))}\n </Box>\n );\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { listStable, deleteStableHorse } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function stableDeleteCommand(name: string | undefined): Promise<number> {\n if (!name) {\n console.error('Usage: token-derby stable delete <name>');\n return 2;\n }\n\n let horses;\n try {\n horses = (await listStable()).horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n\n const horse = horses.find(h => h.name === name);\n if (!horse) {\n console.error(`No horse named \"${name}\" in your stable.`);\n return 1;\n }\n\n const rl = readline.createInterface({ input: stdin, output: stdout });\n const answer = (await rl.question(`Delete \"${name}\" from your stable? [y/N] `)).trim().toLowerCase();\n rl.close();\n if (answer !== 'y' && answer !== 'yes') {\n console.log('Cancelled.');\n return 1;\n }\n\n try {\n await deleteStableHorse(horse.stable_horse_id);\n console.log(`✓ Deleted \"${name}\".`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport { levelFromXp } from '@token-derby/shared';\nimport { HorseCreator } from '../ui/HorseCreator.js';\nimport { HatPicker } from '../ui/HatPicker.js';\nimport { listStable, updateStableHorse, equipHat } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function stableEditCommand(name: string | undefined): Promise<number> {\n if (!name) {\n console.error('Usage: token-derby stable edit <name>');\n return 2;\n }\n\n const horses = await fetchStable();\n if (!horses) return 1;\n const existing = horses.find(h => h.name === name);\n if (!existing) {\n console.error(`No horse named \"${name}\" in your stable.`);\n return 1;\n }\n\n let exitCode = 0;\n let liveColors = existing.colors;\n const app = render(\n React.createElement(HorseCreator, {\n initialColors: existing.colors,\n initialName: existing.name,\n lockName: true,\n initialLevel: levelFromXp(existing.xp),\n onSubmit: async (_name, colors) => {\n try {\n await updateStableHorse(existing.stable_horse_id, { colors });\n liveColors = colors;\n app.unmount();\n console.log(`✓ Updated \"${existing.name}\".`);\n } catch (e) {\n app.unmount();\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n exitCode = 1;\n return;\n }\n throw e;\n }\n },\n onCancel: () => {\n app.unmount();\n console.log('Cancelled.');\n exitCode = 1;\n },\n }),\n );\n await app.waitUntilExit();\n\n if (exitCode === 0 && existing.hats && existing.hats.length > 0) {\n const equipResult = await new Promise<{ done: boolean; idx: number | null }>(resolve => {\n const app2 = render(\n React.createElement(HatPicker, {\n hats: existing.hats!,\n equipped: existing.equipped_hat ?? null,\n colors: liveColors,\n onPick: (idx) => { app2.unmount(); resolve({ done: true, idx }); },\n onCancel: () => { app2.unmount(); resolve({ done: false, idx: null }); },\n }),\n );\n });\n if (equipResult.done) {\n try {\n await equipHat(existing.stable_horse_id, { hat_index: equipResult.idx });\n console.log(equipResult.idx === null ? 'Hat unequipped.' : 'Hat equipped.');\n } catch (e) {\n if (e instanceof ApiError) console.error(`Equip failed: ${e.code} ${e.message}`);\n else throw e;\n }\n }\n }\n\n return exitCode;\n}\n\nasync function fetchStable() {\n try {\n const resp = await listStable();\n return resp.horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return null;\n }\n throw e;\n }\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { CollectedHat, HorseColors } from '@token-derby/shared';\nimport { hatById } from '@token-derby/shared';\nimport { HorseSprite } from './HorseSprite.js';\nimport { AnimatedHorseSprite } from './AnimatedHorseSprite.js';\nimport { MAIN_SPRITE } from './sprite.js';\n\ntype Props = {\n hats: CollectedHat[];\n equipped: number | null | undefined;\n colors: HorseColors;\n onPick: (idx: number | null) => void;\n onCancel: () => void;\n};\n\n// Build a flat list with an \"Unequip\" virtual entry at position 0,\n// then the hats themselves (preserving their inventory indices).\ntype Entry =\n | { kind: 'unequip' }\n | { kind: 'hat'; idx: number; collected: CollectedHat };\n\nexport function HatPicker({ hats, equipped, colors, onPick, onCancel }: Props) {\n const entries: Entry[] = [\n { kind: 'unequip' },\n ...hats.map((c, idx) => ({ kind: 'hat' as const, idx, collected: c })),\n ];\n const [cursor, setCursor] = useState(0);\n useInput((input, key) => {\n if (key.escape) { onCancel(); return; }\n if (key.upArrow) { setCursor((cursor - 1 + entries.length) % entries.length); return; }\n if (key.downArrow) { setCursor((cursor + 1) % entries.length); return; }\n if (key.return) {\n const e = entries[cursor]!;\n onPick(e.kind === 'unequip' ? null : e.idx);\n return;\n }\n });\n\n const focused = entries[cursor]!;\n\n return (\n <Box flexDirection=\"column\">\n <Text>Pick a hat to equip:</Text>\n {entries.map((e, i) => {\n const isCursor = i === cursor;\n if (e.kind === 'unequip') {\n const isEquipped = equipped == null;\n return (\n <Box key=\"unequip\" flexDirection=\"row\">\n <Text>{isCursor ? '►' : ' '} <Text dimColor>Unequip</Text>{isEquipped ? ' ✓' : ''}</Text>\n </Box>\n );\n }\n const hat = hatById(e.collected.id);\n const name = hat?.name ?? e.collected.id;\n const variantSuffix = hat && hat.rarity !== 'legendary' && e.collected.variant !== undefined\n ? ` #${e.collected.variant + 1}`\n : '';\n const isEquipped = equipped === e.idx;\n const rarityColor = hat\n ? (hat.rarity === 'legendary' ? 'yellow' : hat.rarity === 'epic' ? 'magenta' : hat.rarity === 'rare' ? 'blue' : 'gray')\n : 'gray';\n return (\n <Box key={`hat-${e.idx}`} flexDirection=\"row\">\n <Text>\n {isCursor ? '►' : ' '} {name}{variantSuffix}{' '}\n <Text color={rarityColor}>[{hat?.rarity ?? '?'}]</Text>\n {isEquipped ? ' ✓' : ''}\n </Text>\n </Box>\n );\n })}\n\n <Box marginTop={1}>\n <Text dimColor>Preview:</Text>\n </Box>\n <PreviewArea focused={focused} colors={colors} />\n\n <Box marginTop={1}>\n <Text dimColor>↑/↓ choose · Enter pick · Esc cancel</Text>\n </Box>\n </Box>\n );\n}\n\nfunction PreviewArea({ focused, colors }: { focused: Entry; colors: HorseColors }) {\n if (focused.kind === 'unequip') {\n return <HorseSprite sprite={MAIN_SPRITE} colors={colors} />;\n }\n const hat = hatById(focused.collected.id);\n if (!hat) return <HorseSprite sprite={MAIN_SPRITE} colors={colors} />;\n if (hat.rarity === 'legendary') {\n return <AnimatedHorseSprite sprite={MAIN_SPRITE} colors={colors} hat={hat} />;\n }\n return <HorseSprite sprite={MAIN_SPRITE} colors={colors} hat={{ hat, variant: focused.collected.variant ?? 0 }} />;\n}\n","import React, { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport type { Hat, HorseColors } from '@token-derby/shared';\nimport type { SlotTag } from './sprite.js';\nimport { composeHatGrid } from '../hats/render.js';\nimport { hexGridToHalfBlocks } from './half-blocks.js';\n\ntype Props = {\n sprite: readonly (readonly SlotTag[])[];\n colors: HorseColors;\n /** A legendary hat. Non-legendaries should use HorseSprite. */\n hat: Hat;\n};\n\nexport function AnimatedHorseSprite({ sprite, colors, hat }: Props) {\n const isLegendary = hat.rarity === 'legendary';\n const frames = isLegendary ? hat.animation.frames : [];\n const fps = isLegendary ? hat.animation.fps : 1;\n\n const [idx, setIdx] = useState(0);\n useEffect(() => {\n if (!isLegendary || frames.length <= 1) return;\n const interval = setInterval(\n () => setIdx(i => (i + 1) % frames.length),\n Math.max(1, Math.round(1000 / fps)),\n );\n return () => clearInterval(interval);\n }, [isLegendary, frames.length, fps]);\n\n // For legendaries, override hat.colors.A with the current frame.\n const renderedHat: Hat = isLegendary && frames[idx]\n ? { ...hat, colors: { ...hat.colors, A: frames[idx]! } }\n : hat;\n\n const { grid } = composeHatGrid(sprite, renderedHat, 0, colors);\n const lines = hexGridToHalfBlocks(grid);\n return (\n <Box flexDirection=\"column\">\n {lines.map((line, i) => (\n <Text key={i}>{line}</Text>\n ))}\n </Box>\n );\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { ORG_NAME_PATTERN } from '@token-derby/shared';\nimport { createRace } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nconst DEFAULT_TZ = Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';\n\nexport async function createRaceCommand(organisationName?: string): Promise<number> {\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n const name = (await rl.question('Race name: ')).trim();\n if (!name) { console.error('Name required.'); return 1; }\n\n const startRaw = (await rl.question('Start time (ISO 8601, blank = now): ')).trim();\n const start = startRaw ? startRaw : new Date().toISOString();\n if (!isIso(start)) { console.error('Invalid start time.'); return 1; }\n\n const durationRaw = (await rl.question('Race duration (hours): ')).trim();\n const durationHours = parseFloat(durationRaw);\n if (!Number.isFinite(durationHours) || durationHours <= 0) {\n console.error('Duration must be a positive number of hours.'); return 1;\n }\n const end = new Date(new Date(start).getTime() + durationHours * 3600_000).toISOString();\n\n const tz = (await rl.question(`Time zone [${DEFAULT_TZ}]: `)).trim() || DEFAULT_TZ;\n const maxRaw = (await rl.question('Max participants [30]: ')).trim();\n const max = maxRaw ? parseInt(maxRaw, 10) : undefined;\n if (max !== undefined && (!Number.isFinite(max) || max < 1)) {\n console.error('Max participants must be a positive number.'); return 1;\n }\n\n let org = organisationName;\n if (org === undefined) {\n const raw = (await rl.question('Organisation (blank for none): ')).trim();\n if (raw) org = raw;\n }\n if (org !== undefined && !ORG_NAME_PATTERN.test(org)) {\n console.error('Organisation name must be 1–12 alphanumeric characters.');\n return 1;\n }\n\n const countInputRaw = (await rl.question('Count input tokens (fresh input + cache creation) toward race totals? [y/N]: ')).trim().toLowerCase();\n const counts_input = countInputRaw === 'y' || countInputRaw === 'yes';\n\n const resp = await createRace({\n name, start_time: start, end_time: end, tz,\n ...(max !== undefined ? { max_participants: max } : {}),\n ...(org ? { organisation_name: org } : {}),\n ...(counts_input ? { counts_input: true } : {}),\n });\n\n console.log('');\n console.log(' ╔══════════════════════════════════════╗');\n console.log(` ║ JOIN CODE: ${resp.join_code.padEnd(23)}║`);\n console.log(' ╚══════════════════════════════════════╝');\n console.log('');\n console.log(` Admin code: ${resp.admin_code}`);\n console.log(' ⚠ Save the admin code — you need it to end the race early.');\n console.log('');\n if (org) {\n console.log(` Restricted to organisation: ${org}`);\n }\n if (counts_input) {\n console.log(' Counting input + output tokens (excluding cache reads).');\n }\n console.log(` Share with participants: token-derby join ${resp.join_code}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n } finally {\n rl.close();\n }\n}\n\nfunction isIso(s: string): boolean {\n if (!s) return false;\n const d = new Date(s);\n return !Number.isNaN(d.getTime());\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport type { HorseColors, StableHorse } from '@token-derby/shared';\nimport { HorsePicker } from '../ui/HorsePicker.js';\nimport { joinRace, getRace, listStable, listOrganisations } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\nimport { saveActiveRace, loadActiveRace, type ActiveRace } from '../stable/active-race.js';\nimport { RunRace, buildInitialState } from '../runtime/run-race.js';\nimport { loadIdentity } from '../identity/identity.js';\n\nexport async function joinCommand(joinCode: string | undefined): Promise<number> {\n if (!joinCode) {\n console.error('Usage: token-derby join <join-code>');\n return 2;\n }\n const code = joinCode.toUpperCase();\n\n const identity = await loadIdentity();\n if (!identity) {\n // Defensive — bin.ts already checks. Kept so this command is self-contained.\n console.error('Run `token-derby init` to set up your identity.');\n return 1;\n }\n\n // Pre-flight: fetch the race view to detect whether this user is already in it.\n let race;\n try {\n race = await getRace(code);\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'RACE_NOT_FOUND') console.error(`No race with join code ${code}.`);\n else console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n if (race.status === 'finished') {\n console.error('This race has already ended.');\n return 1;\n }\n\n const ownHorse = race.horses.find(h => h.user_id === identity.user_id) ?? null;\n\n let chosenStableHorseId: string;\n let chosenName: string;\n let chosenColors: HorseColors;\n let isResume: boolean;\n\n if (ownHorse) {\n // Auto-resume: use server's snapshot of the horse, no picker.\n chosenStableHorseId = ownHorse.stable_horse_id;\n chosenName = ownHorse.name;\n chosenColors = ownHorse.colors;\n isResume = true;\n } else {\n // For org-restricted races, surface NOT_ORG_MEMBER before walking the user\n // through stable/picker flows — otherwise the first thing they see is\n // \"Your stable is empty\" or a horse picker, hiding the real reason the\n // join will fail. The server still enforces this on POST /join.\n if (race.org_id) {\n try {\n const { organisations } = await listOrganisations();\n if (!organisations.some(o => o.org_id === race.org_id)) {\n const label = race.organisation_name ?? race.org_id;\n console.error(`This race is restricted to members of \"${label}\".`);\n return 1;\n }\n } catch {\n // If we can't reach the orgs endpoint, fall through and let the\n // join API enforce membership — server is source of truth.\n }\n }\n\n let horses: StableHorse[];\n try {\n horses = (await listStable()).horses;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n if (horses.length === 0) {\n console.error('Your stable is empty. Run `token-derby stable create` first.');\n return 1;\n }\n const picked = await pickHorse(horses);\n if (!picked) { console.log('Cancelled.'); return 1; }\n chosenStableHorseId = picked.stable_horse_id;\n chosenName = picked.name;\n chosenColors = picked.colors;\n isResume = false;\n }\n\n let joinResp;\n try {\n joinResp = await joinRace(code, { stable_horse_id: chosenStableHorseId });\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'RACE_FULL') console.error('This race is full.');\n else if (e.code === 'RACE_FINISHED') console.error('This race has ended.');\n else if (e.code === 'RACE_NOT_FOUND') console.error(`No race with join code ${code}.`);\n else if (e.code === 'VERSION_MISMATCH') console.error(e.message);\n else if (e.code === 'DUPLICATE_HORSE') console.error(e.message);\n else if (e.code === 'STABLE_HORSE_NOT_FOUND') {\n console.error('That horse no longer exists in your stable. Try again.');\n }\n else if (e.code === 'NOT_ORG_MEMBER') console.error(e.message);\n else console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n\n // For resume, try to carry forward our last token total from active-races state.\n const prior = await loadActiveRace(code);\n const lastTokens = isResume && prior?.horse_id === joinResp.horse_id ? prior.last_race_tokens : (ownHorse?.current_tokens ?? 0);\n\n const status: 'pending' | 'live' = race.status;\n const active: ActiveRace = {\n join_code: code,\n race_id: race.race_id,\n horse_id: joinResp.horse_id,\n heartbeat_token: joinResp.heartbeat_token,\n horse_name: chosenName,\n horse_colors: chosenColors,\n joined_at: ownHorse?.joined_at ?? new Date().toISOString(),\n last_race_tokens: lastTokens,\n last_heartbeat_at: new Date(0).toISOString(),\n ...(race.counts_input ? { counts_input: true } : {}),\n };\n await saveActiveRace(active);\n\n const initial = await buildInitialState({ active, raceStatus: status, rejoin: isResume });\n const app = render(React.createElement(RunRace, { active, ...initial, ownUserName: identity.display_name }));\n await app.waitUntilExit();\n return 0;\n}\n\nasync function pickHorse(horses: StableHorse[]): Promise<StableHorse | null> {\n return new Promise(resolve => {\n const app = render(\n React.createElement(HorsePicker, {\n horses,\n onPick: (h: StableHorse) => { app.unmount(); resolve(h); },\n onCancel: () => { app.unmount(); resolve(null); },\n }),\n );\n });\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MINI_SPRITE } from './sprite.js';\nimport type { StableHorse } from '@token-derby/shared';\nimport { levelFromXp } from '@token-derby/shared';\n\ntype Props = {\n horses: StableHorse[];\n onPick: (horse: StableHorse) => void;\n onCancel: () => void;\n};\n\nexport function HorsePicker({ horses, onPick, onCancel }: Props) {\n const [idx, setIdx] = useState(0);\n\n useInput((input, key) => {\n if (key.escape) { onCancel(); return; }\n if (horses.length === 0) return;\n if (key.upArrow) { setIdx((idx - 1 + horses.length) % horses.length); return; }\n if (key.downArrow) { setIdx((idx + 1) % horses.length); return; }\n if (key.return) { onPick(horses[idx]!); return; }\n });\n\n if (horses.length === 0) {\n return (\n <Box flexDirection=\"column\">\n <Text>No horses in your stable.</Text>\n <Text dimColor>Run `token-derby stable create` to make one.</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text>Pick a horse to race:</Text>\n {horses.map((h, i) => (\n <Box key={h.stable_horse_id} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text>{i === idx ? '►' : ' '} {h.name} <Text color=\"cyan\">[Lvl. {levelFromXp(h.xp)}]</Text></Text>\n </Box>\n <Box flexDirection=\"row\">\n <Text> </Text>\n <HorseSprite sprite={MINI_SPRITE} colors={h.colors} />\n </Box>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text dimColor>↑/↓ choose · Enter pick · Esc cancel</Text>\n </Box>\n </Box>\n );\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type { HorseColors } from '@token-derby/shared';\nimport { activeRaceFile, activeRacesDir } from '../paths.js';\n\nexport type ActiveRace = {\n join_code: string;\n race_id: string;\n horse_id: string;\n heartbeat_token: string;\n horse_name: string;\n horse_colors: HorseColors;\n joined_at: string;\n last_race_tokens: number;\n last_heartbeat_at: string;\n counts_input?: boolean;\n};\n\nexport async function loadActiveRace(joinCode: string): Promise<ActiveRace | null> {\n try {\n const raw = await fs.readFile(activeRaceFile(joinCode), 'utf8');\n return JSON.parse(raw) as ActiveRace;\n } catch (e: any) {\n if (e?.code === 'ENOENT') return null;\n throw e;\n }\n}\n\nexport async function saveActiveRace(active: ActiveRace): Promise<void> {\n await fs.mkdir(activeRacesDir(), { recursive: true });\n await fs.writeFile(\n activeRaceFile(active.join_code),\n JSON.stringify(active, null, 2) + '\\n',\n 'utf8',\n );\n}\n\nexport async function deleteActiveRace(joinCode: string): Promise<void> {\n try {\n await fs.unlink(activeRaceFile(joinCode));\n } catch (e: any) {\n if (e?.code !== 'ENOENT') throw e;\n }\n}\n\nexport async function listActiveRaces(): Promise<string[]> {\n try {\n const entries = await fs.readdir(activeRacesDir());\n return entries\n .filter(f => f.endsWith('.json'))\n .map(f => path.basename(f, '.json'));\n } catch (e: any) {\n if (e?.code === 'ENOENT') return [];\n throw e;\n }\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { Box, Text, useApp } from 'ink';\nimport type { GetRaceResponse, HeartbeatResponse } from '@token-derby/shared';\nimport { StatusScreen } from '../ui/StatusScreen.js';\nimport { describeAchievement, type RecentEvent } from '@token-derby/shared';\nimport { runHeartbeatLoop } from './heartbeat-loop.js';\nimport { sumTokensForRace } from '../tokens/transcripts.js';\nimport { initialBaseline } from '../tokens/baseline.js';\nimport * as endpoints from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\nimport { saveActiveRace, type ActiveRace } from '../stable/active-race.js';\nimport { HEARTBEAT_INTERVAL_MS, HEARTBEAT_RETRY_DELAYS_MS } from '../config.js';\n\nexport type RunRaceProps = {\n active: ActiveRace;\n startingBaseline: number;\n pendingMode: boolean;\n ownUserName: string;\n};\n\nexport function RunRace({ active, startingBaseline, pendingMode, ownUserName }: RunRaceProps) {\n const { exit } = useApp();\n const [race, setRace] = useState<GetRaceResponse | null>(null);\n const [lastHbAt, setLastHbAt] = useState<Date | null>(null);\n const [lastHbOk, setLastHbOk] = useState<boolean>(true);\n const [tickNow, setTickNow] = useState<Date>(new Date());\n const [fatalError, setFatalError] = useState<string | null>(null);\n const [achievements, setAchievements] = useState<Array<{ key: string; event: RecentEvent }>>([]);\n const shownAchievementAtRef = useRef<number>(0);\n\n const baselineRef = useRef(startingBaseline);\n const pendingRef = useRef(pendingMode);\n const lastTokenSampleRef = useRef<number>(startingBaseline);\n const ctrl = useRef(new AbortController());\n\n // Re-render every second so the \"Ns ago\" counter updates.\n useEffect(() => {\n const t = setInterval(() => setTickNow(new Date()), 1_000);\n return () => clearInterval(t);\n }, []);\n\n // Re-snapshot baseline when race transitions pending → live.\n useEffect(() => {\n if (pendingRef.current && race?.status === 'live') {\n sumTokensForRace(active).then(total => {\n baselineRef.current = total;\n pendingRef.current = false;\n });\n }\n }, [race?.status]);\n\n useEffect(() => {\n runHeartbeatLoop({\n sendHeartbeat: async (currentTokens) => {\n const resp = await endpoints.heartbeat(\n active.join_code, active.horse_id, active.heartbeat_token, { current_tokens: currentTokens },\n );\n const updated: ActiveRace = {\n ...active,\n last_race_tokens: currentTokens,\n last_heartbeat_at: new Date().toISOString(),\n };\n await saveActiveRace(updated);\n return resp;\n },\n getCurrentTokens: () => {\n if (pendingRef.current) return 0;\n return Math.max(0, lastTokenSampleRef.current - baselineRef.current);\n },\n intervalMs: HEARTBEAT_INTERVAL_MS,\n retryDelaysMs: HEARTBEAT_RETRY_DELAYS_MS,\n onSuccess: (resp: HeartbeatResponse) => {\n setLastHbAt(new Date());\n setLastHbOk(true);\n setRace(raceViewFrom(resp));\n const own = resp.horses.find(h => h.horse_id === active.horse_id);\n const candidates = (own?.recent_events ?? []).filter(e => e.at > shownAchievementAtRef.current);\n if (candidates.length > 0) {\n shownAchievementAtRef.current = Math.max(...candidates.map(e => e.at));\n const fresh = candidates.map(e => ({ key: `${e.at}-${e.name}`, event: e }));\n setAchievements(prev => [...prev, ...fresh]);\n }\n if (resp.race_status === 'finished') exit();\n },\n onError: (err) => {\n if (err instanceof ApiError && err.code === 'VERSION_MISMATCH') {\n setFatalError(err.message);\n ctrl.current.abort();\n exit();\n return;\n }\n setLastHbOk(false);\n },\n onFinished: () => exit(),\n abortSignal: ctrl.current.signal,\n });\n\n // Token sampler — refresh the running token total every 5s so the heartbeat sees fresh data.\n const sampler = setInterval(async () => {\n try {\n lastTokenSampleRef.current = await sumTokensForRace(active);\n } catch (e) {\n console.error('[token-derby] token sampler failed:', e);\n }\n }, 5_000);\n // Prime it once at startup.\n sumTokensForRace(active)\n .then(t => { lastTokenSampleRef.current = t; })\n .catch(e => console.error('[token-derby] token sampler prime failed:', e));\n\n const controller = ctrl.current;\n return () => {\n clearInterval(sampler);\n controller.abort();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const lastHeartbeatAgoSec = lastHbAt\n ? Math.max(0, Math.floor((tickNow.getTime() - lastHbAt.getTime()) / 1000))\n : null;\n\n if (fatalError) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Text color=\"red\" bold>CLI version mismatch — disconnected</Text>\n <Text>{fatalError}</Text>\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <StatusScreen\n race={race}\n ownHorseId={active.horse_id}\n ownHorseName={active.horse_name}\n ownColors={active.horse_colors}\n ownUserName={ownUserName}\n lastHeartbeatAgoSec={lastHeartbeatAgoSec}\n lastHeartbeatOk={lastHbOk}\n />\n {achievements.length > 0 && (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>Achievements</Text>\n {achievements.map(({ key, event }) => {\n const description = describeAchievement(event, active);\n return (\n <Box key={key} flexDirection=\"row\">\n <Text dimColor> {formatClockTime(event.at)} </Text>\n <Text color=\"yellow\" bold>+{event.xp} XP </Text>\n <Text>{event.name}</Text>\n <Text dimColor> — {description}</Text>\n </Box>\n );\n })}\n </Box>\n )}\n </Box>\n );\n}\n\nfunction formatClockTime(at: number): string {\n const d = new Date(at);\n const h = String(d.getHours()).padStart(2, '0');\n const m = String(d.getMinutes()).padStart(2, '0');\n const s = String(d.getSeconds()).padStart(2, '0');\n return `${h}:${m}:${s}`;\n}\n\nfunction raceViewFrom(resp: HeartbeatResponse): GetRaceResponse {\n return {\n ...resp.race,\n status: resp.race_status,\n horses: resp.horses,\n server_time: resp.server_time,\n time_left_seconds: resp.time_left_seconds,\n };\n}\n\nexport async function buildInitialState(args: {\n active: ActiveRace;\n raceStatus: 'pending' | 'live';\n rejoin: boolean;\n}): Promise<{ startingBaseline: number; pendingMode: boolean }> {\n const runningTotal = await sumTokensForRace(args.active);\n if (args.rejoin) {\n return {\n startingBaseline: Math.max(0, runningTotal - args.active.last_race_tokens),\n pendingMode: args.raceStatus === 'pending',\n };\n }\n return {\n startingBaseline: initialBaseline({ runningTotal, status: args.raceStatus }),\n pendingMode: args.raceStatus === 'pending',\n };\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { GetRaceResponse, HorseColors, HorseView } from '@token-derby/shared';\nimport { levelInfo } from '@token-derby/shared';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MINI_SPRITE } from './sprite.js';\n\ntype Props = {\n race: GetRaceResponse | null;\n ownHorseId: string;\n ownHorseName: string;\n ownColors: HorseColors;\n ownUserName: string;\n lastHeartbeatAgoSec: number | null;\n lastHeartbeatOk: boolean;\n};\n\nexport function StatusScreen(props: Props) {\n const { race, ownHorseId, ownHorseName, ownColors, ownUserName, lastHeartbeatAgoSec, lastHeartbeatOk } = props;\n\n if (!race) {\n return (\n <Box flexDirection=\"column\">\n <Text>Joining race…</Text>\n </Box>\n );\n }\n\n const own: HorseView | undefined = race.horses.find(h => h.horse_id === ownHorseId);\n const leader: HorseView | undefined = race.horses[0];\n const elapsedPct = elapsed(race);\n const timeLeft = formatDuration(race.time_left_seconds);\n const lvl = levelInfo((own?.xp ?? 0) + (own?.live_xp ?? 0));\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" paddingX={1}>\n <Text>\n 🏇 TOKEN DERBY ─── <Text bold>{race.name}</Text> ─── status: <Text color={statusColor(race.status)}>{race.status}</Text>\n </Text>\n\n <Box marginTop={1} flexDirection=\"row\">\n <HorseSprite sprite={MINI_SPRITE} colors={ownColors} />\n <Box flexDirection=\"column\">\n <Text> {ownHorseName} <Text color=\"cyan\">[Lvl. {lvl.level}]</Text></Text>\n <Text> <Text dimColor>({ownUserName})</Text></Text>\n </Box>\n </Box>\n\n <Box flexDirection=\"column\" marginTop={1}>\n <Text>Tokens (race): {own?.current_tokens ?? 0}</Text>\n <Text>Position: {own?.rank ?? '—'} of {race.horses.length}</Text>\n <Text>\n Leader: {leader ? `${leader.name}${leader.user_name ? ` (${leader.user_name})` : ''} — ${leader.current_tokens}` : '—'}\n </Text>\n <Text>Race elapsed: {(elapsedPct * 100).toFixed(0)}% {bar(elapsedPct, 20)}</Text>\n <Text>Time left: {timeLeft}</Text>\n <Text>\n XP: {lvl.next_level_xp === null\n ? `${lvl.xp} (max level) ${bar(1, 20)}`\n : `${lvl.xp_into_level}/${lvl.xp_for_level} → Lvl. ${lvl.level + 1} ${bar(lvl.progress, 20)}`}\n </Text>\n <Text>\n Last heartbeat: {lastHeartbeatAgoSec === null ? '—' : `${lastHeartbeatAgoSec}s ago`}\n {' '}\n <Text color={lastHeartbeatOk ? 'green' : 'yellow'}>\n {lastHeartbeatOk ? '✓' : '⚠'}\n </Text>\n </Text>\n </Box>\n\n <Box marginTop={1}>\n <Text dimColor>Press Ctrl+C to crash out of the race.</Text>\n </Box>\n </Box>\n );\n}\n\nfunction elapsed(race: GetRaceResponse): number {\n const start = new Date(race.start_time).getTime();\n const end = new Date(race.end_time).getTime();\n const now = new Date(race.server_time).getTime();\n if (end <= start) return 0;\n const v = (now - start) / (end - start);\n return Math.max(0, Math.min(1, v));\n}\n\nfunction bar(pct: number, width: number): string {\n const filled = Math.round(pct * width);\n return '▓'.repeat(filled) + '░'.repeat(width - filled);\n}\n\nfunction statusColor(status: GetRaceResponse['status']): string {\n if (status === 'live') return 'green';\n if (status === 'pending') return 'yellow';\n return 'gray';\n}\n\nfunction formatDuration(seconds: number): string {\n const s = Math.max(0, Math.floor(seconds));\n const h = Math.floor(s / 3600);\n const m = Math.floor((s % 3600) / 60);\n const ss = s % 60;\n return `${h.toString().padStart(2, '0')}:${m.toString().padStart(2, '0')}:${ss.toString().padStart(2, '0')}`;\n}\n","import type { HeartbeatResponse } from '@token-derby/shared';\n\nexport type HeartbeatLoopOptions = {\n sendHeartbeat: (currentTokens: number) => Promise<HeartbeatResponse>;\n getCurrentTokens: () => number;\n intervalMs: number;\n retryDelaysMs: readonly number[];\n onSuccess: (resp: HeartbeatResponse) => void;\n onError: (err: unknown) => void;\n onFinished: () => void;\n abortSignal: AbortSignal;\n};\n\nexport function runHeartbeatLoop(opts: HeartbeatLoopOptions): void {\n let timer: ReturnType<typeof setTimeout> | null = null;\n let retryIndex = 0;\n let stopped = false;\n\n const stop = () => {\n stopped = true;\n if (timer) clearTimeout(timer);\n timer = null;\n };\n\n opts.abortSignal.addEventListener('abort', stop, { once: true });\n\n const schedule = (delay: number) => {\n if (stopped) return;\n timer = setTimeout(tick, delay);\n };\n\n const tick = async () => {\n if (stopped) return;\n try {\n const tokens = opts.getCurrentTokens();\n const resp = await opts.sendHeartbeat(tokens);\n retryIndex = 0;\n opts.onSuccess(resp);\n if (resp.race_status === 'finished') {\n opts.onFinished();\n stop();\n return;\n }\n schedule(opts.intervalMs);\n } catch (err) {\n opts.onError(err);\n const delay = opts.retryDelaysMs[Math.min(retryIndex, opts.retryDelaysMs.length - 1)] ?? 1_000;\n retryIndex += 1;\n schedule(delay);\n }\n };\n\n schedule(0);\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { claudeProjectsDir } from '../paths.js';\n\n// `input` here is \"fresh-input\" tokens only: input_tokens (this turn's new\n// content) + cache_creation_input_tokens (tokens written into the cache this\n// turn). cache_read_input_tokens is intentionally excluded — those are\n// passive context that don't represent work done in the race.\nexport type TokenTotals = { input: number; output: number };\n\nexport async function sumTokens(): Promise<TokenTotals> {\n const root = claudeProjectsDir();\n const files = await listJsonlFiles(root);\n let input = 0;\n let output = 0;\n for (const file of files) {\n const t = await sumFile(file);\n input += t.input;\n output += t.output;\n }\n return { input, output };\n}\n\n// Total tokens for a race in the race's chosen mode. When race.counts_input\n// is true, the race counts fresh-input + cache-creation + output; otherwise\n// it counts output only. cache_read is never included.\nexport async function sumTokensForRace(race: { counts_input?: boolean }): Promise<number> {\n const { input, output } = await sumTokens();\n return race.counts_input ? input + output : output;\n}\n\nasync function listJsonlFiles(root: string): Promise<string[]> {\n let projects: string[];\n try {\n projects = await fs.readdir(root);\n } catch (e: any) {\n if (e?.code === 'ENOENT') return [];\n throw e;\n }\n const out: string[] = [];\n for (const project of projects) {\n const projectDir = path.join(root, project);\n let stat;\n try {\n stat = await fs.stat(projectDir);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) continue;\n let entries: string[];\n try {\n entries = await fs.readdir(projectDir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n if (entry.endsWith('.jsonl')) out.push(path.join(projectDir, entry));\n }\n }\n return out;\n}\n\nfunction addNum(value: unknown): number {\n return typeof value === 'number' && Number.isFinite(value) ? value : 0;\n}\n\nasync function sumFile(file: string): Promise<TokenTotals> {\n let raw: string;\n try {\n raw = await fs.readFile(file, 'utf8');\n } catch {\n return { input: 0, output: 0 };\n }\n let input = 0;\n let output = 0;\n for (const line of raw.split('\\n')) {\n if (!line.trim()) continue;\n let parsed: any;\n try {\n parsed = JSON.parse(line);\n } catch {\n continue;\n }\n const usage = parsed?.message?.usage;\n if (!usage) continue;\n input += addNum(usage.input_tokens) + addNum(usage.cache_creation_input_tokens);\n output += addNum(usage.output_tokens);\n }\n return { input, output };\n}\n","import type { RaceStatus } from '@token-derby/shared';\n\nexport function initialBaseline(args: { runningTotal: number; status: RaceStatus }): number {\n return args.runningTotal;\n}\n\nexport function rejoinBaseline(args: { runningTotal: number; lastRaceTokens: number }): number {\n return Math.max(0, args.runningTotal - args.lastRaceTokens);\n}\n\nexport function currentRaceTokens(runningTotal: number, baseline: number): number {\n return Math.max(0, runningTotal - baseline);\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { endRace } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function endCommand(adminCode: string | undefined): Promise<number> {\n if (!adminCode) {\n console.error('Usage: token-derby end <admin-code>');\n return 2;\n }\n const rl = readline.createInterface({ input: stdin, output: stdout });\n const answer = (await rl.question('End the race now and freeze final tokens? [y/N] ')).trim().toLowerCase();\n rl.close();\n if (answer !== 'y' && answer !== 'yes') {\n console.log('Cancelled.');\n return 1;\n }\n try {\n await endRace(adminCode);\n console.log('✓ Race ended.');\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'RACE_NOT_FOUND') console.error('No race with that admin code.');\n else console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport {\n loadIdentity,\n saveIdentity,\n deleteIdentity,\n validateDisplayName,\n type Identity,\n} from '../identity/identity.js';\nimport { initJockey, updateJockey } from '../api/endpoints.js';\nimport { ApiError, _resetIdentityCacheForTests } from '../api/client.js';\n\nexport async function initCommand(reset = false): Promise<number> {\n if (reset) {\n await deleteIdentity();\n _resetIdentityCacheForTests();\n console.log('Removed local identity. Creating a new one…');\n }\n\n const existing = await loadIdentity();\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n if (existing) {\n console.log(`Current jockey name: ${existing.display_name}`);\n const raw = (await rl.question('New jockey name (use your real name please) [keep]: ')).trim();\n if (!raw) {\n console.log('Kept existing name.');\n return 0;\n }\n const v = validateDisplayName(raw);\n if (!v.ok) { console.error(v.error); return 1; }\n try {\n const resp = await updateJockey({ display_name: v.name });\n const updated: Identity = { ...existing, display_name: resp.display_name };\n await saveIdentity(updated);\n console.log(`Updated jockey name to: ${updated.display_name}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'UNAUTHENTICATED') {\n console.error(\n 'Server does not recognise this identity. Your account may have been wiped. ' +\n 'Run `token-derby init --reset` to start fresh.',\n );\n } else {\n console.error(`Error: ${e.code} ${e.message}`);\n }\n return 1;\n }\n throw e;\n }\n }\n\n const raw = (await rl.question('Jockey Name (use your real name please): ')).trim();\n const v = validateDisplayName(raw);\n if (!v.ok) { console.error(v.error); return 1; }\n\n try {\n const resp = await initJockey({ display_name: v.name });\n const identity: Identity = {\n user_id: resp.user_id,\n display_name: resp.display_name,\n secret_token: resp.secret_token,\n created_at: new Date().toISOString(),\n };\n await saveIdentity(identity);\n _resetIdentityCacheForTests();\n console.log('');\n console.log(`Welcome, ${identity.display_name}!`);\n console.log('Your identity has been created on the server.');\n console.log('You can now create a stable and join races.');\n console.log('');\n console.log(' ⚠ Your secret token is stored locally in identity.json.');\n console.log(' If you lose it, you cannot recover this account — you would');\n console.log(' need to run `token-derby init --reset` and rebuild your stable.');\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n } finally {\n rl.close();\n }\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { spawn } from 'node:child_process';\nimport { gteSemver } from '@token-derby/shared';\nimport { CLI_VERSION } from '../version.js';\n\nconst REGISTRY_URL = 'https://registry.npmjs.org/@mauricode/token-derby/latest';\nconst UPGRADE_CMD = 'npm install -g @mauricode/token-derby@latest';\nconst FETCH_TIMEOUT_MS = 5_000;\n\ntype Deps = {\n fetchImpl?: typeof fetch;\n spawnImpl?: typeof spawn;\n promptYesNo?: (question: string) => Promise<boolean>;\n};\n\nexport async function updateCommand(deps: Deps = {}): Promise<number> {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const spawnImpl = deps.spawnImpl ?? spawn;\n const promptYesNo = deps.promptYesNo ?? defaultPromptYesNo;\n\n let latest: string;\n try {\n latest = await fetchLatestVersion(fetchImpl);\n } catch (e: any) {\n console.error(`Could not reach the npm registry${e?.message ? ` (${e.message})` : ''}.`);\n console.error(`To upgrade manually: ${UPGRADE_CMD}`);\n return 1;\n }\n\n if (gteSemver(CLI_VERSION, latest)) {\n console.log(`You're on the latest version (${CLI_VERSION}).`);\n return 0;\n }\n\n console.log(`Current: ${CLI_VERSION} Latest: ${latest}`);\n const yes = await promptYesNo('Run upgrade now? [y/N]: ');\n if (!yes) {\n console.log(`To upgrade manually: ${UPGRADE_CMD}`);\n return 0;\n }\n\n return runNpmUpgrade(spawnImpl);\n}\n\nasync function fetchLatestVersion(fetchImpl: typeof fetch): Promise<string> {\n const controller = new AbortController();\n const t = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);\n try {\n const res = await fetchImpl(REGISTRY_URL, { signal: controller.signal });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const body = await res.json() as { version?: unknown };\n if (typeof body.version !== 'string' || !/^\\d+\\.\\d+\\.\\d+/.test(body.version)) {\n throw new Error('unexpected registry response');\n }\n return body.version;\n } finally {\n clearTimeout(t);\n }\n}\n\nasync function defaultPromptYesNo(question: string): Promise<boolean> {\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n const answer = (await rl.question(question)).trim().toLowerCase();\n return answer === 'y' || answer === 'yes';\n } finally {\n rl.close();\n }\n}\n\nfunction runNpmUpgrade(spawnImpl: typeof spawn): Promise<number> {\n return new Promise(resolve => {\n const child = spawnImpl('npm', ['install', '-g', '@mauricode/token-derby@latest'], {\n stdio: 'inherit',\n });\n child.on('error', (e: NodeJS.ErrnoException) => {\n if (e.code === 'ENOENT') {\n console.error('Could not find `npm` on PATH.');\n console.error(`To upgrade manually: ${UPGRADE_CMD}`);\n } else {\n console.error(`npm failed to start: ${e.message}`);\n }\n resolve(1);\n });\n child.on('exit', code => resolve(code ?? 1));\n });\n}\n","import React from 'react';\nimport { render } from 'ink';\nimport { levelFromXp, hatById } from '@token-derby/shared';\nimport type { StableHorse } from '@token-derby/shared';\nimport { ApiError } from '../api/client.js';\nimport { listStable, rollHat, equipHat } from '../api/endpoints.js';\nimport { RollReveal, printClosedBox, type RollOutcome } from '../ui/RollReveal.js';\nimport { RollHorsePicker } from '../ui/RollHorsePicker.js';\n\nfunction pendingFor(horse: StableHorse): number {\n const level = levelFromXp(horse.xp);\n const lastRolled = horse.last_rolled_level ?? Math.max(0, level - 1);\n return level - lastRolled;\n}\n\nasync function promptYesNo(question: string): Promise<boolean> {\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n const a = (await rl.question(question)).trim().toLowerCase();\n rl.close();\n return a === '' || a === 'y' || a === 'yes';\n}\n\n/** Show the closed box, wait for Enter, then play the open/reveal animation. */\nasync function runReveal(outcome: RollOutcome): Promise<void> {\n // Stage 1: print closed box to stdout (no Ink) so readline can prompt\n // for Enter without fighting Ink for stdin.\n printClosedBox();\n const readline = await import('node:readline/promises');\n const rl = readline.createInterface({ input: process.stdin, output: process.stdout });\n await rl.question('Press Enter to open the box… ');\n rl.close();\n\n // Stage 2: open → burst → reveal (or open → empty → done for no_hat).\n await new Promise<void>(resolve => {\n const app = render(React.createElement(RollReveal, {\n outcome,\n onDone: () => { app.unmount(); resolve(); },\n }));\n });\n}\n\nexport async function rollCommand(): Promise<number> {\n let stable;\n try {\n stable = await listStable();\n } catch (e) {\n if (e instanceof ApiError) { console.error(`Error: ${e.code} ${e.message}`); return 1; }\n throw e;\n }\n\n const eligible = stable.horses\n .map(h => ({ ...h, pending: pendingFor(h) }))\n .filter(h => h.pending > 0);\n\n if (eligible.length === 0) {\n console.log('No rolls available. Level up a horse to earn a roll!');\n return 0;\n }\n\n let chosen: StableHorse = eligible[0]!;\n if (eligible.length > 1) {\n const picked = await new Promise<StableHorse | null>(resolve => {\n const app = render(React.createElement(RollHorsePicker, {\n horses: eligible,\n onPick: (h) => { app.unmount(); resolve(h); },\n onCancel: () => { app.unmount(); resolve(null); },\n }));\n });\n if (!picked) { console.log('Cancelled.'); return 0; }\n chosen = picked;\n }\n\n while (true) {\n let result;\n try {\n result = await rollHat(chosen.stable_horse_id);\n } catch (e) {\n if (e instanceof ApiError) {\n if (e.code === 'INSUFFICIENT_ROLLS') { console.log('No more rolls available.'); return 0; }\n console.error(`Error: ${e.code} ${e.message}`); return 1;\n }\n throw e;\n }\n\n // Build a tier-agnostic outcome shape for RollReveal. The closed box is\n // the same colour for every outcome — rarity only reveals during the\n // confetti burst (and is absent entirely for no_hat).\n const outcome: RollOutcome | null = (() => {\n if (result.result === 'hat') {\n const hat = hatById(result.collected.id);\n if (!hat) return null;\n return { kind: 'hat', hat, variant: result.collected.variant };\n }\n if (result.result === 'duplicate') {\n const hat = hatById(result.hat_id);\n if (!hat) return null;\n return { kind: 'duplicate', hat, variant: result.variant };\n }\n return { kind: 'no_hat' };\n })();\n if (!outcome) {\n console.error('Server returned an unknown hat id — catalog mismatch.');\n return 1;\n }\n\n // Closed box + Enter prompt, then the open/burst/reveal animation.\n await runReveal(outcome);\n\n if (result.result === 'hat') {\n const hat = hatById(result.collected.id)!;\n const variantSuffix = hat.rarity !== 'legendary' && result.collected.variant !== undefined\n ? ` #${result.collected.variant + 1}`\n : '';\n console.log(`\\n✨ ${hat.name}${variantSuffix} [${hat.rarity.toUpperCase()}]\\n`);\n if (await promptYesNo('Equip now? [Y/n] ')) {\n try {\n await equipHat(chosen.stable_horse_id, { hat_index: result.hat_index });\n console.log(`Equipped on ${chosen.name}.`);\n } catch (e) {\n if (e instanceof ApiError) { console.error(`Equip failed: ${e.code} ${e.message}`); }\n else throw e;\n }\n }\n } else if (result.result === 'duplicate') {\n const hat = hatById(result.hat_id);\n const variantSuffix = result.variant !== undefined ? ` #${result.variant + 1}` : '';\n console.log(`\\nYou already have ${hat?.name ?? result.hat_id}${variantSuffix}. +${result.xp_awarded} XP.\\n`);\n } else {\n console.log(`\\nNo hat this time. +${result.xp_awarded} XP toward your next level.\\n`);\n }\n\n if (result.remaining_rolls <= 0) return 0;\n if (!(await promptYesNo(`${result.remaining_rolls} more roll${result.remaining_rolls === 1 ? '' : 's'} available. Roll again? [Y/n] `))) return 0;\n }\n}\n","import React, { useState, useEffect, useMemo } from 'react';\nimport { Box, Text } from 'ink';\nimport type { Hat } from '@token-derby/shared';\nimport { HatSprite, AnimatedHatSprite } from './HatSprite.js';\nimport { ansiFg } from './half-blocks.js';\n\nconst RESET = '\\x1b[0m';\n\n// The box itself is always the same warm-gold colour — it gives away no\n// rarity. The rarity is revealed by the confetti burst once the box opens.\nconst BOX_COLOR = '#E5C76B';\n\n// Palettes per rarity tier. Confetti picks uniformly from these.\nconst TIER_PALETTE: Record<Hat['rarity'], string[]> = {\n common: ['#FFFFFF', '#DDDDDD', '#AAAAAA', '#9E9E9E'],\n rare: ['#42A5F5', '#1E88E5', '#90CAF9', '#0277BD'],\n epic: ['#AB47BC', '#8E24AA', '#CE93D8', '#6A1B9A'],\n legendary: ['#FFD700', '#FF7F00', '#FF0000', '#FF00FF', '#00BFFF', '#7CFC00', '#8B00FF'],\n};\n\nconst CONFETTI_CHARS = ['✦', '✧', '⋆', '★', '☆', '✨', '*', '•', '◆', '◇'];\n\nconst SCENE_W = 32;\nconst SCENE_H = 10;\n\n// ─── Box frames ──────────────────────────────────────────────────────\n\nfunction pad(line: string): string {\n const visible = stripAnsi(line).length;\n const lead = Math.max(0, Math.floor((SCENE_W - visible) / 2));\n return ' '.repeat(lead) + line + ' '.repeat(Math.max(0, SCENE_W - lead - visible));\n}\n\nfunction stripAnsi(s: string): string {\n return s.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\nconst BOX_CLOSED: string[] = [\n '',\n '',\n '╔═════════════╗',\n '║ ░░░░░ ║',\n '║░░░░░░░░░░░░░║',\n '║ ░░░░░░░░░ ║',\n '║░░░░░░░░░░░░░║',\n '╚═════════════╝',\n '',\n '',\n].map(pad);\n\nconst BOX_OPENING_1: string[] = [\n '',\n '╔═════════════╗',\n '╚═════════════╝',\n '',\n '╔═════════════╗',\n '║ ✦ ║',\n '║░░░░░░░░░░░░░║',\n '╚═════════════╝',\n '',\n '',\n].map(pad);\n\nconst BOX_OPENING_2: string[] = [\n ' ╔═════════════╗',\n ' ║ ║',\n ' ╚═════════════╝',\n '',\n ' ✨ ★ ✦',\n '',\n '╔═════════════╗',\n '║ ║',\n '╚═════════════╝',\n '',\n].map(pad);\n\nconst BOX_EMPTY: string[] = [\n '',\n '',\n '',\n '',\n '',\n '',\n '╔═════════════╗',\n '║ ║',\n '╚═════════════╝',\n '',\n].map(pad);\n\n// ─── Gift box component ──────────────────────────────────────────────\n\nfunction GiftBox({ frame, color }: { frame: string[]; color: string }) {\n return (\n <Box flexDirection=\"column\">\n {frame.map((line, i) => (\n <Text key={i}>{line ? ansiFg(color) + line + RESET : line}</Text>\n ))}\n </Box>\n );\n}\n\n// ─── Closed-box-to-stdout ────────────────────────────────────────────\n\n/**\n * Print the closed box directly to stdout — bypasses Ink so we can use\n * readline for the Enter-to-open prompt without fighting Ink for stdin.\n * Box colour is identical across all rarities; rarity reveals later via\n * the confetti burst.\n */\nexport function printClosedBox(): void {\n for (const line of BOX_CLOSED) {\n const colored = line.trim().length > 0\n ? `${ansiFg(BOX_COLOR)}${line}${RESET}`\n : line;\n process.stdout.write(colored + '\\n');\n }\n}\n\n// ─── Confetti burst ──────────────────────────────────────────────────\n\ntype Particle = {\n x: number; y: number;\n vx: number; vy: number;\n char: string;\n color: string;\n};\n\nfunction spawnParticles(tier: Hat['rarity'], count: number, cx: number, cy: number): Particle[] {\n const palette = TIER_PALETTE[tier];\n const out: Particle[] = [];\n for (let i = 0; i < count; i++) {\n const angle = (i / count) * Math.PI * 2 + (Math.random() - 0.5) * 0.6;\n const speed = 0.8 + Math.random() * 1.6;\n out.push({\n x: cx,\n y: cy,\n vx: Math.cos(angle) * speed,\n vy: Math.sin(angle) * speed * 0.5,\n char: CONFETTI_CHARS[Math.floor(Math.random() * CONFETTI_CHARS.length)]!,\n color: palette[Math.floor(Math.random() * palette.length)]!,\n });\n }\n return out;\n}\n\nfunction ConfettiBurst({ tier }: { tier: Hat['rarity'] }) {\n const cx = Math.floor(SCENE_W / 2);\n const cy = Math.floor(SCENE_H / 2);\n const particles = useMemo(() => spawnParticles(tier, 36, cx, cy), [tier, cx, cy]);\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n const i = setInterval(() => setTick(t => t + 1), 70);\n return () => clearInterval(i);\n }, []);\n\n const grid: string[][] = Array.from({ length: SCENE_H }, () => Array(SCENE_W).fill(' '));\n for (const p of particles) {\n const x = Math.round(p.x + p.vx * tick);\n const y = Math.round(p.y + p.vy * tick);\n if (x >= 0 && x < SCENE_W && y >= 0 && y < SCENE_H) {\n grid[y]![x] = ansiFg(p.color) + p.char + RESET;\n }\n }\n\n return (\n <Box flexDirection=\"column\">\n {grid.map((row, y) => (\n <Text key={y}>{row.join('')}</Text>\n ))}\n </Box>\n );\n}\n\n// ─── Outcome-aware reveal ────────────────────────────────────────────\n\nexport type RollOutcome =\n | { kind: 'hat'; hat: Hat; variant?: number }\n | { kind: 'duplicate'; hat: Hat; variant?: number }\n | { kind: 'no_hat' };\n\ntype RevealProps = {\n outcome: RollOutcome;\n onDone: () => void;\n};\n\n/**\n * Plays the reveal animation starting from \"lid lifting\" (the closed box\n * + Enter prompt is a separate component). Sequence depends on outcome:\n * - hat / duplicate: open → tier-coloured burst → hat shown alone\n * - no_hat: open → empty box pause → done (no confetti)\n */\nexport function RollReveal({ outcome, onDone }: RevealProps) {\n const isNoHat = outcome.kind === 'no_hat';\n const isLegendary = outcome.kind !== 'no_hat' && outcome.hat.rarity === 'legendary';\n\n const [phase, setPhase] = useState<'open1' | 'open2' | 'burst' | 'empty' | 'reveal'>('open1');\n\n useEffect(() => {\n const timers: ReturnType<typeof setTimeout>[] = [];\n timers.push(setTimeout(() => setPhase('open2'), 350));\n if (isNoHat) {\n timers.push(setTimeout(() => setPhase('empty'), 700));\n timers.push(setTimeout(onDone, 1500));\n } else {\n timers.push(setTimeout(() => setPhase('burst'), 700));\n timers.push(setTimeout(() => setPhase('reveal'), 1650));\n timers.push(setTimeout(onDone, isLegendary ? 4650 : 2650));\n }\n return () => timers.forEach(clearTimeout);\n }, [isNoHat, isLegendary, onDone]);\n\n if (phase === 'open1') return <GiftBox frame={BOX_OPENING_1} color={BOX_COLOR} />;\n if (phase === 'open2') return <GiftBox frame={BOX_OPENING_2} color={BOX_COLOR} />;\n if (phase === 'empty') return <GiftBox frame={BOX_EMPTY} color={BOX_COLOR} />;\n if (phase === 'burst' && outcome.kind !== 'no_hat') {\n return <ConfettiBurst tier={outcome.hat.rarity} />;\n }\n // phase === 'reveal' — only reachable for hat/duplicate outcomes\n if (outcome.kind === 'no_hat') return <GiftBox frame={BOX_EMPTY} color={BOX_COLOR} />;\n return outcome.hat.rarity === 'legendary'\n ? <AnimatedHatSprite hat={outcome.hat} centerIn={{ w: SCENE_W, h: SCENE_H }} />\n : <HatSprite hat={outcome.hat} variant={outcome.variant} centerIn={{ w: SCENE_W, h: SCENE_H }} />;\n}\n","import React, { useEffect, useState } from 'react';\nimport { Box, Text } from 'ink';\nimport type { Hat } from '@token-derby/shared';\nimport { hexGridToHalfBlocks } from './half-blocks.js';\n\ntype Props = {\n hat: Hat;\n variant?: number;\n /** When set, the hat is centered within an N×M scene (in pixels, pre-half-block). */\n centerIn?: { w: number; h: number };\n};\n\n/**\n * Render just the hat pixels — no horse. Used for roll reveals where we want\n * to show the prize on its own before equipping it. For legendary hats with\n * an animation block, see AnimatedHatSprite below.\n */\nexport function HatSprite({ hat, variant, centerIn }: Props) {\n const colors = hatColorsFor(hat, variant ?? 0);\n const grid = makeHatGrid(hat, colors, centerIn);\n const lines = hexGridToHalfBlocks(grid);\n return (\n <Box flexDirection=\"column\">\n {lines.map((line, i) => (\n <Text key={i}>{line}</Text>\n ))}\n </Box>\n );\n}\n\n/**\n * Same as HatSprite but cycles the legendary animation frames over the A\n * color in place. Non-legendary hats fall through to a single static render.\n */\nexport function AnimatedHatSprite({ hat, variant, centerIn }: Props) {\n if (hat.rarity !== 'legendary') {\n return <HatSprite hat={hat} variant={variant} centerIn={centerIn} />;\n }\n const frames = hat.animation.frames;\n const fps = hat.animation.fps;\n const [idx, setIdx] = useState(0);\n useEffect(() => {\n if (frames.length <= 1) return;\n const interval = setInterval(\n () => setIdx(i => (i + 1) % frames.length),\n Math.max(1, Math.round(1000 / fps)),\n );\n return () => clearInterval(interval);\n }, [frames.length, fps]);\n const framed: Hat = { ...hat, colors: { ...hat.colors, A: frames[idx]! } };\n return <HatSprite hat={framed} variant={variant} centerIn={centerIn} />;\n}\n\nfunction hatColorsFor(hat: Hat, variantIdx: number): { A: string; Q?: string } {\n if (hat.rarity === 'legendary') return hat.colors;\n return hat.variants[variantIdx] ?? hat.variants[0]!;\n}\n\nfunction makeHatGrid(\n hat: Hat,\n colors: { A: string; Q?: string },\n centerIn: { w: number; h: number } | undefined,\n): (string | null)[][] {\n const w = centerIn?.w ?? hat.width;\n const h = centerIn?.h ?? hat.rows.length;\n // Center the hat within the requested canvas. If no centerIn, the grid is\n // hat-sized and the hat starts at (0, 0).\n const offX = Math.floor((w - hat.width) / 2);\n const offY = Math.floor((h - hat.rows.length) / 2);\n const grid: (string | null)[][] = Array.from({ length: h }, () => Array(w).fill(null));\n for (let y = 0; y < hat.rows.length; y++) {\n const row = hat.rows[y]!;\n for (let x = 0; x < hat.width; x++) {\n const ch = row[x];\n if (ch === '.' || ch === undefined) continue;\n const gx = x + offX;\n const gy = y + offY;\n if (gx < 0 || gx >= w || gy < 0 || gy >= h) continue;\n grid[gy]![gx] = ch === 'A' ? colors.A : (colors.Q ?? colors.A);\n }\n }\n return grid;\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport { HorseSprite } from './HorseSprite.js';\nimport { MINI_SPRITE } from './sprite.js';\nimport type { StableHorse } from '@token-derby/shared';\nimport { levelFromXp } from '@token-derby/shared';\n\ntype Pending = StableHorse & { pending: number };\n\ntype Props = {\n horses: Pending[];\n onPick: (horse: StableHorse) => void;\n onCancel: () => void;\n};\n\nexport function RollHorsePicker({ horses, onPick, onCancel }: Props) {\n const [idx, setIdx] = useState(0);\n useInput((input, key) => {\n if (key.escape) { onCancel(); return; }\n if (horses.length === 0) return;\n if (key.upArrow) { setIdx((idx - 1 + horses.length) % horses.length); return; }\n if (key.downArrow) { setIdx((idx + 1) % horses.length); return; }\n if (key.return) { onPick(horses[idx]!); return; }\n });\n\n return (\n <Box flexDirection=\"column\">\n <Text>Pick a horse to roll for:</Text>\n {horses.map((h, i) => (\n <Box key={h.stable_horse_id} flexDirection=\"column\">\n <Box flexDirection=\"row\">\n <Text>\n {i === idx ? '►' : ' '} {h.name}{' '}\n <Text color=\"cyan\">[Lvl. {levelFromXp(h.xp)}]</Text>{' '}\n <Text color=\"yellow\">— {h.pending} roll{h.pending === 1 ? '' : 's'}</Text>\n </Text>\n </Box>\n <Box flexDirection=\"row\">\n <Text> </Text>\n <HorseSprite sprite={MINI_SPRITE} colors={h.colors} />\n </Box>\n </Box>\n ))}\n <Box marginTop={1}>\n <Text dimColor>↑/↓ choose · Enter pick · Esc cancel</Text>\n </Box>\n </Box>\n );\n}\n","import * as readline from 'node:readline/promises';\nimport { stdin, stdout } from 'node:process';\nimport { ORG_NAME_PATTERN, ORG_NAME_MAX_LENGTH } from '@token-derby/shared';\nimport { createOrganisation } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgCreateCommand(): Promise<number> {\n const rl = readline.createInterface({ input: stdin, output: stdout });\n try {\n const name = (await rl.question(`Organisation name (1–${ORG_NAME_MAX_LENGTH} alphanumeric chars): `)).trim();\n if (!ORG_NAME_PATTERN.test(name)) {\n console.error(`Name must be 1–${ORG_NAME_MAX_LENGTH} alphanumeric characters (no spaces or symbols).`);\n return 1;\n }\n const resp = await createOrganisation({ name });\n\n console.log('');\n console.log(` Organisation created: ${resp.org_name}`);\n console.log(' ╔══════════════════════════════════════════════════════════╗');\n console.log(` ║ JOIN TOKEN: ${resp.org_join_token.padEnd(43)}║`);\n console.log(' ╚══════════════════════════════════════════════════════════╝');\n console.log(' ⚠ Share this token to invite members. Treat it as a secret.');\n console.log('');\n console.log(` Members join with: token-derby organisation join ${resp.org_join_token}`);\n console.log(` Create org races: token-derby create --organisation ${resp.org_name}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n } finally {\n rl.close();\n }\n}\n","import { joinOrganisation } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgJoinCommand(token: string | undefined): Promise<number> {\n if (!token) {\n console.error('Usage: token-derby organisation join <join-token>');\n return 2;\n }\n try {\n const resp = await joinOrganisation({ join_token: token });\n console.log(`Joined organisation: ${resp.org_name}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { listOrganisations } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgListCommand(): Promise<number> {\n try {\n const resp = await listOrganisations();\n if (resp.organisations.length === 0) {\n console.log('You are not in any organisations.');\n console.log('Create one with: token-derby organisation create');\n console.log('Or join one with: token-derby organisation join <token>');\n return 0;\n }\n console.log(`Your organisations (${resp.organisations.length}):`);\n for (const o of resp.organisations) {\n console.log(` • ${o.org_name}`);\n }\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { ORG_NAME_PATTERN } from '@token-derby/shared';\nimport { getOrganisation } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgInfoCommand(name: string | undefined): Promise<number> {\n if (!name) {\n console.error('Usage: token-derby organisation info <name>');\n return 2;\n }\n if (!ORG_NAME_PATTERN.test(name)) {\n console.error('Organisation name must be 1–12 alphanumeric characters.');\n return 2;\n }\n try {\n const resp = await getOrganisation(name);\n console.log(`Organisation: ${resp.org_name}`);\n console.log(`Created: ${resp.created_at} by ${resp.creator_user_name}`);\n console.log('');\n console.log(' ╔══════════════════════════════════════════════════════════╗');\n console.log(` ║ JOIN TOKEN: ${resp.org_join_token.padEnd(43)}║`);\n console.log(' ╚══════════════════════════════════════════════════════════╝');\n console.log(' ⚠ Treat the token as a secret — anyone with it can join.');\n console.log('');\n console.log(` Members join with: token-derby organisation join ${resp.org_join_token}`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { setOrgWebhook } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgWebhookSetCommand(orgName: string | undefined, url: string | undefined): Promise<number> {\n if (!orgName || !url) {\n console.error('Usage: token-derby organisation webhook set <org-name> <https-url>');\n return 2;\n }\n try {\n const resp = await setOrgWebhook(orgName, { url });\n console.log('');\n console.log(` Webhook set for ${orgName}: ${resp.webhook_url}`);\n console.log(' ╔══════════════════════════════════════════════════════════╗');\n console.log(` ║ SECRET: ${resp.webhook_secret.padEnd(47)}║`);\n console.log(' ╚══════════════════════════════════════════════════════════╝');\n console.log(' ⚠ Save this secret now — it will not be shown again.');\n console.log(' Your receiver verifies requests with: X-Token-Derby-Signature: sha256=<hmac(secret, raw body)>.');\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { getOrgWebhook } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgWebhookGetCommand(orgName: string | undefined): Promise<number> {\n if (!orgName) {\n console.error('Usage: token-derby organisation webhook get <org-name>');\n return 2;\n }\n try {\n const resp = await getOrgWebhook(orgName);\n if (resp.webhook_url) {\n console.log(`Webhook for ${orgName}: ${resp.webhook_url}`);\n } else {\n console.log(`No webhook configured for ${orgName}.`);\n }\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { deleteOrgWebhook } from '../api/endpoints.js';\nimport { ApiError } from '../api/client.js';\n\nexport async function orgWebhookClearCommand(orgName: string | undefined): Promise<number> {\n if (!orgName) {\n console.error('Usage: token-derby organisation webhook clear <org-name>');\n return 2;\n }\n try {\n await deleteOrgWebhook(orgName);\n console.log(`Webhook removed for ${orgName}.`);\n return 0;\n } catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.code} ${e.message}`);\n return 1;\n }\n throw e;\n }\n}\n","import { stableCreateCommand } from './commands/stable-create.js';\nimport { stableListCommand } from './commands/stable-list.js';\nimport { stableDeleteCommand } from './commands/stable-delete.js';\nimport { stableEditCommand } from './commands/stable-edit.js';\nimport { createRaceCommand } from './commands/create.js';\nimport { joinCommand } from './commands/join.js';\nimport { endCommand } from './commands/end.js';\nimport { initCommand } from './commands/init.js';\nimport { updateCommand } from './commands/update.js';\nimport { rollCommand } from './commands/roll.js';\nimport { orgCreateCommand } from './commands/org-create.js';\nimport { orgJoinCommand } from './commands/org-join.js';\nimport { orgListCommand } from './commands/org-list.js';\nimport { orgInfoCommand } from './commands/org-info.js';\nimport { orgWebhookSetCommand } from './commands/org-webhook-set.js';\nimport { orgWebhookGetCommand } from './commands/org-webhook-get.js';\nimport { orgWebhookClearCommand } from './commands/org-webhook-clear.js';\nimport { CLI_VERSION } from './version.js';\nimport { loadIdentity } from './identity/identity.js';\n\nconst HELP = `token-derby v${CLI_VERSION}\n\nIdentity:\n token-derby init Set up your jockey identity (run this first)\n Re-running renames you on the server.\n token-derby init --reset Wipe local identity and create a fresh account.\n Your previous stable is abandoned on the server.\n\nMaintenance:\n token-derby update Check for and install the latest CLI version\n\nStable management:\n token-derby stable create Make a new horse (interactive)\n token-derby stable list Show your saved horses\n token-derby stable edit <name> Edit an existing horse's colors\n token-derby stable delete <name> Remove a horse from your stable\n\nOrganisations:\n token-derby organisation create Create a new organisation (interactive)\n token-derby organisation join <token> Join an organisation with a join token\n token-derby organisation info <name> Show an org's join token (members only)\n token-derby organisation list Show organisations you're a member of\n token-derby organisation webhook set <name> <url>\n Configure an https webhook for race events.\n Prints a secret used to sign each request.\n Only the org creator can run this.\n token-derby organisation webhook get <name>\n Show the org's configured webhook URL (or \"no webhook\").\n token-derby organisation webhook clear <name>\n Remove the webhook for this org.\n\nRaces:\n token-derby create [--organisation <name>]\n Create a new race (interactive). When\n --organisation is set, only members of\n that org can join.\n token-derby join <join-code> Join (or resume) a race\n token-derby end <admin-code> End a race early\n\nCosmetics:\n token-derby roll Spend a pending roll to try for a hat.\n Earn rolls by leveling up horses.\n\nEnvironment:\n TOKEN_DERBY_API_BASE Override API base URL (default: production)\n TOKEN_DERBY_HOME Override identity/stable directory\n`;\n\nasync function main(): Promise<number> {\n const argv = process.argv.slice(2);\n const cmd = argv[0];\n\n if (!cmd || cmd === '--help' || cmd === '-h') { console.log(HELP); return 0; }\n if (cmd === '--version' || cmd === '-v') { console.log(CLI_VERSION); return 0; }\n\n if (cmd === 'init') {\n const reset = argv.slice(1).includes('--reset');\n return initCommand(reset);\n }\n // `update` runs before the identity gate so a broken or stale install can fix itself.\n if (cmd === 'update') return updateCommand();\n\n // Every other command requires an identity. `init` and `update` are the only escape hatches.\n const identity = await loadIdentity();\n if (!identity) {\n console.error('Run `token-derby init` to set up your identity before using any other command.');\n return 1;\n }\n\n if (cmd === 'stable') {\n const sub = argv[1];\n if (sub === 'create') return stableCreateCommand();\n if (sub === 'list') return stableListCommand();\n if (sub === 'edit') return stableEditCommand(argv[2]);\n if (sub === 'delete') return stableDeleteCommand(argv[2]);\n console.error(`Unknown stable subcommand: ${sub ?? '(none)'}`);\n console.error('Try: stable create | stable list | stable edit <name> | stable delete <name>');\n return 2;\n }\n\n if (cmd === 'organisation' || cmd === 'org') {\n const sub = argv[1];\n if (sub === 'create') return orgCreateCommand();\n if (sub === 'join') return orgJoinCommand(argv[2]);\n if (sub === 'info') return orgInfoCommand(argv[2]);\n if (sub === 'list') return orgListCommand();\n if (sub === 'webhook') {\n const action = argv[2];\n if (action === 'set') return orgWebhookSetCommand(argv[3], argv[4]);\n if (action === 'get') return orgWebhookGetCommand(argv[3]);\n if (action === 'clear') return orgWebhookClearCommand(argv[3]);\n console.error(`Unknown webhook action: ${action ?? '(none)'}`);\n console.error('Try: organisation webhook set <name> <url> | organisation webhook get <name> | organisation webhook clear <name>');\n return 2;\n }\n console.error(`Unknown organisation subcommand: ${sub ?? '(none)'}`);\n console.error('Try: organisation create | organisation join <token> | organisation info <name> | organisation list | organisation webhook <set|get|clear> ...');\n return 2;\n }\n\n if (cmd === 'create') {\n const orgName = parseFlag(argv.slice(1), '--organisation');\n return createRaceCommand(orgName);\n }\n if (cmd === 'join') return joinCommand(argv[1]);\n if (cmd === 'end') return endCommand(argv[1]);\n if (cmd === 'roll') return rollCommand();\n\n console.error(`Unknown command: ${cmd}`);\n console.error(HELP);\n return 2;\n}\n\nfunction parseFlag(args: string[], flag: string): string | undefined {\n for (let i = 0; i < args.length; i++) {\n if (args[i] === flag) return args[i + 1];\n const eq = `${flag}=`;\n if (args[i]?.startsWith(eq)) return args[i]!.slice(eq.length);\n }\n return undefined;\n}\n\nmain().then(\n code => process.exit(code),\n err => {\n console.error(err?.stack ?? err);\n process.exit(1);\n },\n);\n"],"mappings":"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","names":["React","Box","Text","grid","RESET","jsx","Box","Text","path","path","React","React","render","Box","Text","jsx","jsxs","render","React","Box","Text","React","render","useState","Box","Text","useInput","useState","Box","Text","jsx","useState","Box","Text","jsx","jsxs","useState","useInput","Box","Text","isEquipped","render","React","readline","stdin","stdout","stdin","stdout","React","render","useState","Box","Text","useInput","jsx","jsxs","useState","useInput","Box","Text","fs","path","useEffect","useState","Box","Text","Box","Text","jsx","jsxs","Box","Text","fs","path","stat","jsx","jsxs","useState","useEffect","Box","Text","render","React","readline","stdin","stdout","stdin","stdout","readline","stdin","stdout","stdin","stdout","raw","v","readline","stdin","stdout","promptYesNo","stdin","stdout","React","render","useState","useEffect","Box","Text","useEffect","useState","Box","Text","jsx","hatColorsFor","Box","Text","useState","useEffect","jsx","RESET","Box","Text","useState","useEffect","useState","Box","Text","useInput","jsx","jsxs","useState","useInput","Box","Text","readline","render","React","readline","stdin","stdout","stdin","stdout"]}