Commit Graph
8 Commits
Author SHA1 Message Date
DorianandClaude Fable 5 2512265113 fix: nostr-provider.js 404, DocsPage proxy-unaware URL, round-jump on late viewer join
CI / check (push) Failing after 6m9s
Three more fixes found during live demo verification:

1. server/src/app.ts: the previous commit added <script src="/nostr-provider.js">
   to index.html and shipped the file into server/public/, but this app's
   static file serving is an explicit per-route allowlist, not a catch-all —
   there was no route registered for it, so it 404'd and the signer bridge
   silently never loaded. Added the missing app.get('/nostr-provider.js', ...)
   route.

2. DocsPage.vue: promptUrl (the displayed "give this URL to your AI" copy
   button) was built from window.location.origin — same root-cause bug class
   as the JoinBoutPage/BotProfilePage fix (ffd4dfd), just for a link instead
   of fetched content. Now resolves the real arena origin from the fetched
   prompt's own content (which IS correctly proxy-resolved server-side via
   arena-proxy) instead of the browser's current address.

3. FightPage.vue: opening a fight already in progress (e.g. a background
   poll-mode bot kept answering challenges while nobody had the viewer open)
   showed nothing until the next live round arrived — reads as "the fight
   jumped straight to round N". loadFight() always fetched the completed
   rounds (data.rounds) but nothing backfilled the visible log from them;
   only live SSE round_end events ever pushed into liveLogItems. Added
   backfillCompletedRounds(), called once on mount before wireSSE() connects,
   that renders a compact (non-animated — no scene/TTS replay) summary of
   every already-completed round and sets HP/round-counter to current state
   immediately.

4. BOTFIGHTS.md: documented the webhook_test signature exception (see ffd4dfd
   commit for the same fix already applied to the live doc endpoint's
   underlying example) — this file is frontend/public/docs/BOTFIGHTS.md,
   the static copy that predates today's /api/docs/prompt-only rendering
   fix; keeping both in sync since some flows may still reference the path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 07:16:24 -04:00
DorianandClaude Fable 5 2c039f2af3 fix(nostr): reactive extension detection + native Archipelago signer bridge
CI / check (push) Failing after 6m19s
Two fixes found during live signer-login verification:

1. hasExtension was `computed(() => !!window.nostr)` — window.nostr is a
   plain global with no Vue reactivity, so this evaluated once, lazily, on
   first read and cached forever. If the extension's content script hadn't
   injected yet at that moment (common — extensions often inject slightly
   after page scripts start), "SIGN IN WITH EXTENSION" disappeared
   permanently, even once the extension finished injecting moments later.
   Reported live as "no browser extension or signer option ever shows".
   Fixed: hasExtension is now backed by a real ref, seeded from the current
   value and upgraded by a short poll (existing waitForSigner() precedent,
   same 200ms/timeout shape) so the UI reacts when the extension actually
   appears.

2. Added Archipelago's native NIP-07 signer bridge (frontend/public/
   nostr-provider.js, copied verbatim from neode-ui/public/nostr-provider.js
   — the canonical source) via a <script> tag in index.html. This no-ops
   immediately outside an iframe (window === window.top), so a real browser
   extension in a standalone tab is unaffected. Inside the Archipelago node
   dashboard's iframe, it provides window.nostr backed by the node's own
   identity via postMessage to
   neode-ui/src/views/appSession/useNostrBridge.ts (already generic — no
   per-app allowlist needed for the getPublicKey/signEvent bridge itself,
   only for the optional auto-login/identity-picker convenience flow, which
   this app doesn't use). Existing login() flow (buildNip98Token ->
   POST /api/auth/nostr/session) works unchanged through this bridge.

Together: signing in now works reliably both in the dashboard iframe (no
extension needed at all) and in a direct tab (real extension, now reliably
detected).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 06:58:53 -04:00
DorianandClaude Fable 5 d2fc998a28 docs(prompt): AI-agent consent preamble, operator-only LLM creds (drop ANTHROPIC_API_KEY pattern), accurate queue-join timing — feedback from first real AI agent test
CI / check (push) Failing after 6m5s
The first cloud AI agent given the prompt refused it as a suspected prompt
injection: 'nothing else needs to be read' framing, raw-IP fallback, and
being told to wire its own ANTHROPIC_API_KEY into a persistent script. All
three patterns removed; brains are now an operator-supplied optional
OpenAI-compatible endpoint with local heuristics as default. queue/join
documented as blocking ~35s (60s client timeout) matching the real 30s
production QUEUE_TIMEOUT_MS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-30 23:52:18 -04:00
Dorian bbc3c7acff docs(09-03): consolidate BOTFIGHTS setup docs into one self-contained AI prompt
CI / check (push) Failing after 6m13s
- Merge BOTFIGHTS.md + BOTFIGHTS-EASY/POLLING/WEBHOOK.md + BOT_SETUP.md into
  a single canonical prompt at frontend/public/docs/BOTFIGHTS.md
- Add the previously-undocumented registration step (POST /api/bots,
  anonymous, poll vs webhook mode, rate limits, 409/422 behavior)
- Replace the stale botfights.io fallback host with the {{ARENA_URL}} token
  (substituted server-side/client-side in later tasks)
- Document the exact HMAC-SHA256 webhook signature derivation, matching
  orchestrator.ts (the old bot.js example's verifySignature() was wrong —
  it hashed BOT_SECRET directly instead of via the secretHash+signingKey
  two-step the server actually uses)
- Document the trash_talk (webhook, snake_case) vs trashTalk (poll,
  camelCase) field-naming split, verified against the real zod schemas
- Add the endpoint reference table, troubleshooting table, and arena-as-relay
  framing (any node can host an arena; default is the Foundation's)
- Replace root BOTFIGHTS.md with a 4-line stub pointing at the canonical copy
- Delete the four superseded docs (BOTFIGHTS-EASY/POLLING/WEBHOOK.md, BOT_SETUP.md)
2026-07-30 22:01:43 -04:00
DorianandClaude Opus 4.6 2e7a039b8b fix: serve /docs/*.md as static files, not SPA fallback
- Add /docs/* route to serve markdown setup guides
- Add md to MIME map and SPA catch-all exclusion
- Normalize BOTFIGHTS.md placeholders to YOUR_BOT_ID/YOUR_BOT_SECRET

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:16:44 +00:00
Dorian bc4a52bc12 fixes 2026-03-12 16:35:59 +00:00
DorianandClaude Opus 4.6 52769ab43a feat: ship pre-generated TTS audio files for instant playback
71 static voice files (9.6MB) for round calls, intros, hype lines,
and challenge announces. These play instantly from file instead of
running Kokoro TTS generation in the browser. Dynamic content
(questions, answers, narrations) still uses Kokoro.

Includes Node.js generation script (scripts/generate-voice-files.mjs)
and modified tts.ts to check static file cache before worker generation.
Static audio works even before Kokoro model finishes loading.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 10:38:44 +00:00
DorianandClaude Opus 4.6 486d6f445d feat: PWA support — installable on all platforms
- Add vite-plugin-pwa with autoUpdate service worker
- Generate SVG + PNG icons (192, 512, apple-touch-icon, favicon)
- Web app manifest with standalone display mode
- Workbox caching: precache assets, cache Google Fonts, NetworkFirst for API
- Apple mobile web app meta tags for iOS home screen

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 21:53:44 +00:00