feat: v3 — fight loop, expanded challenges, FightPage ownership guard

- Add fight-loop CLI for automated mock fights with elo-based matchmaking
- Expand challenge types, scoring narrations, arenas, and mock bot pool
- FightPage "Fight again" buttons now only show for your own bot
- FightViewer async scene init, live fight polling with round counter
- Extract mock answers into separate answers module

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-03-06 23:44:40 +00:00
co-authored by Claude Opus 4.6
parent 47d20fbe66
commit 2c0323d5fb
14 changed files with 2669 additions and 996 deletions
+9 -2
View File
@@ -80,7 +80,14 @@ async function callWebhook(
return { answer: null, timeMs: elapsed, timedOut: false, error: true }
}
const data = await res.json() as { answer?: string; trash_talk?: string }
const text = await res.text()
let data: { answer?: string; trash_talk?: string }
try {
data = JSON.parse(text)
} catch {
console.log(`[webhook] ${url} returned non-JSON in ${elapsed}ms: ${text.slice(0, 200)}`)
return { answer: null, timeMs: elapsed, timedOut: false, error: true }
}
console.log(`[webhook] ${url} OK in ${elapsed}ms answer=${(data.answer || '').slice(0, 80)}`)
return {
answer: data.answer || null,
@@ -115,7 +122,7 @@ async function getBotResponse(
): Promise<WebhookResponse> {
if (isMockBot(bot.webhookUrl)) {
console.log(`[fight] ${bot.name} is mock bot, generating response`)
const mock = generateMockBotResponse(challenge.type, bot.name)
const mock = generateMockBotResponse(challenge, bot.name)
return {
answer: mock.answer || null,
trashTalk: mock.trashTalk,