* fix(ui): route OBSIDIVM benchmarks through any backend, not OpenRouter-only
The OBSIDIVM benchmark/self-improvement UI ran its own client-side,
OpenRouter-only LLM path: getApiKey() read only the OpenRouter key, every
call hardcoded openrouter.ai, and the gate hard-blocked with "Configure
OpenRouter API key first" — so a configured Venice key was ignored and a
connected local agent was never used.
Add a client-side backend resolver (OpenRouter key -> Venice key -> connected
agent -> server LLM) and route all benchmark executors, judges, and gates
through it:
- resolveLLMBackend() + LLM_BACKEND_HINT; safeLLMCall()/_safeLLMCallOnce()
become backend-aware (Venice uses api.venice.ai with a Venice-valid model;
OpenRouter unchanged). _backendCall() routes keyless backends through the
existing server endpoints: /api/agents/local/dispatch (drives the connected
Claude Code/Codex/Hermes agent) and /api/llm/chat (server LLM).
- runLiveBenchmark, ctfCallLLM, the self-improvement analyzer, and the config
optimizer now call safeLLMCall instead of a hardcoded openrouter.ai fetch.
- Live-Test / improvement-loop gates and runLLMJudge accept any backend.
Client-side only; no server changes (endpoints already existed). The
recon-only SPECTRA helper is intentionally left OpenRouter-only (out of scope).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(ui): keyless routing must use the API base URL (cross-origin) + model consistency
Addresses review feedback on the OBSIDIVM backend-routing PR.
1. Relative keyless URLs broke the primary cross-origin deployment. _backendCall
fetched '/api/agents/local/dispatch' and '/api/llm/chat' as RELATIVE URLs, but
when the static War Room (GitHub Pages docs/) talks to a separate backend the
app sets T3MP3ST_API.baseUrl = http://<host>:3333. There the relative fetches
hit the Pages origin → 404/CORS, so the headline local-agent / server-LLM
routing silently failed (worked only same-origin). Fix: prefix
`${T3MP3ST_API.baseUrl}` on both; empty base stays relative for same-origin.
Verified: with baseUrl set, both now resolve to http://<host>:3333/api/...
2. Model default consistency. Four benchmark fallbacks read
'anthropic/claude-opus-4.8', out of step with the state default, the <option>,
renderModels and saveApiKey (all 'claude-opus-4.6'). Reverted to 4.6 to match.
(The /api/agents/local/dispatch server route exists — src/server.ts.)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* fix(ui): backend-aware gates on the last OpenRouter-only benchmark paths
Addresses the re-review on this PR: two flows this PR claims support Venice /
connected local agent / server LLM still hard-gated on an OpenRouter key.
1. runSingleBenchTest() (single benchmark click): replaced the getApiKey()
length check with `resolveLLMBackend().kind === 'none'` (+ LLM_BACKEND_HINT),
matching runBenchmarks('live'). A Venice-only / agent / server backend can now
click-run a single test instead of being blocked before safeLLMCall().
2. Self-improvement auto-apply:
- autoApplyForLoop() now falls back to applyFallbackImprovements() only when
NO backend exists (resolveLLMBackend().kind === 'none'), not merely when the
OpenRouter key is empty — so the optimizer step uses Venice/agent/server.
- autoApplyRecommendations() entry gate uses the backend check.
- The Auto-Apply button show/hide (displayAnalysis) uses `hasBackend =
resolveLLMBackend().kind !== 'none'` instead of an OpenRouter-only key test.
Verified: gates pass for venice/agent/server, block only when kind==='none';
node --check clean on the inline scripts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The Settings agent card's render() set window.__t3mpLiveAgents from CLIENT-side
pings only (Object.keys(pingStatus).filter(ok)). Agents connected server-side —
via autoReconnect (ping:false) or a status?check=1 re-ping — are live on the
server even though this client never pinged them, so every re-render reset the
count to 0. Since upstream's t3mpHasBackend() is now `llmAvailable || live > 0`,
that clobber made the War Room show "No LLM backbone — connect an agent before
hunting" on localhost even with a genuinely-live local agent (repro: 3 agents
connected, hermes lastPing.ok on the server, yet hasBackend=false after any
detect/render).
Fix: live = max(client-pinged-ok, server-reported-live), reading the server's
own agent state (window.__t3mpServerAgents, refreshed via status?check=1). The
summary and the global now both reflect reality and re-renders no longer break
the gate. Verified: hasBackend stays true across detect/connect re-renders.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>