diff --git a/docs/index.html b/docs/index.html
index 37ef507e..7d19cf39 100755
--- a/docs/index.html
+++ b/docs/index.html
@@ -11290,29 +11290,6 @@
${m.name}
// Shared safe LLM call — resolves the backend, then routes the call. Keyless backends
// (connected agent / server LLM) run single-shot through the server; key backends
// (OpenRouter / Venice) call the provider directly and keep the model-fallback chain.
- async function safeLLMCall(prompt, options = {}) {
- const backend = resolveLLMBackend();
- if (backend.kind === 'none') throw new Error(LLM_BACKEND_HINT);
-
- if (backend.kind === 'agent' || backend.kind === 'server') {
- if (typeof trackApiCall === 'function') trackApiCall();
- const label = backend.kind === 'agent' ? ('agent:' + backend.agentId) : 'server-llm';
- addIntel('API', `→ ${label}`, 'info');
- const content = await _backendCall(backend, prompt, options);
- if (!content || content.trim().length < 10) throw new Error(`${label} returned empty response`);
- currentModelInUse = label;
- return content;
- }
-
- const primaryModel = options.model || state.settings?.selectedModel || 'anthropic/claude-opus-4.6';
- const fallbackModel = state.settings?.fallbackModel || 'nousresearch/hermes-3-llama-3.1-405b';
- let models;
- if (backend.kind === 'venice') {
- models = [veniceModel(options.model || state.settings?.selectedModel)];
- } else {
- models = options._noFallback ? [primaryModel]
- : (primaryModel === fallbackModel ? [primaryModel] : [primaryModel, fallbackModel]);
- }
// Same-origin proxy the browser "AI" features POST to when local mode is on.
// The server (npm run server) serves this page, so /api/llm/chat is same-origin
// (no CORS) and reuses LLMBackbone -> LocalAdapter to reach llama.cpp/Ollama.
@@ -11507,6 +11484,21 @@ ${m.name}
// Shared safe LLM call — handles response.ok, JSON parsing, timeouts, model fallback
async function safeLLMCall(prompt, options = {}) {
+ const backend = resolveLLMBackend();
+ if (backend.kind === 'none') throw new Error(LLM_BACKEND_HINT);
+
+ // Keyless routing: a connected local agent (Claude Code/Codex/Hermes) or the
+ // server's own configured LLM answers through the same-origin server, not the browser.
+ if (backend.kind === 'agent' || backend.kind === 'server') {
+ if (typeof trackApiCall === 'function') trackApiCall();
+ const label = backend.kind === 'agent' ? ('agent:' + backend.agentId) : 'server-llm';
+ addIntel('API', `→ ${label}`, 'info');
+ const content = await _backendCall(backend, prompt, options);
+ if (!content || content.trim().length < 10) throw new Error(`${label} returned empty response`);
+ currentModelInUse = label;
+ return content;
+ }
+
const localMode = !!state.settings?.useLocal;
const apiKey = localMode ? 'local' : getApiKey();
if (!localMode && !apiKey) throw new Error('No API key configured');
@@ -11589,19 +11581,6 @@ ${m.name}
: 'https://openrouter.ai/api/v1/chat/completions';
const headers = { 'Authorization': `Bearer ${backend.key}`, 'Content-Type': 'application/json' };
if (backend.kind === 'openrouter') { headers['HTTP-Referer'] = window.location.href; headers['X-Title'] = options.title || 'T3MP3ST'; }
- const response = await fetch(endpoint, {
- method: 'POST',
- headers,
- body: JSON.stringify({
- model,
- messages: Array.isArray(prompt)
- ? prompt
- : [{ role: 'user', content: prompt }],
- max_tokens: options.maxTokens || 4096,
- temperature: options.temperature ?? 0.3
- }),
- signal: AbortSignal.timeout(options.timeout || 120000)
- });
// LOCAL MODE: route through the same-origin server proxy (reuses
// LLMBackbone -> LocalAdapter; avoids browser CORS against llama.cpp/localhost).
@@ -11655,14 +11634,9 @@ ${m.name}
const cloudTimer = setTimeout(() => cloudController.abort(), cloudTimeoutMs);
let response;
try {
- response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
+ response = await fetch(endpoint, {
method: 'POST',
- headers: {
- 'Authorization': `Bearer ${apiKey}`,
- 'Content-Type': 'application/json',
- 'HTTP-Referer': window.location.href,
- 'X-Title': options.title || 'T3MP3ST'
- },
+ headers,
body: JSON.stringify({
model,
messages: Array.isArray(prompt)
@@ -11707,11 +11681,6 @@ ${m.name}
if (mode === 'live') {
if (resolveLLMBackend().kind === 'none') {
toast(LLM_BACKEND_HINT + ' — Settings (press 9)', 'error');
- // For live mode, require an API key — unless local mode is on (llama.cpp/Ollama needs none)
- if (mode === 'live' && !state.settings?.useLocal) {
- const apiKey = getApiKey();
- if (!apiKey || apiKey.length < 10) {
- toast('OpenRouter API key required for benchmarks — go to Settings (press 9) to configure, or enable the Local Model', 'error');
return;
}
}
@@ -12418,9 +12387,6 @@ ${m.name}
* LLM-as-Judge - Semantic correctness evaluation
* Uses a second LLM call to evaluate response quality
*/
- async function runLLMJudge(test, response, apiKey) {
- if (!EVALUATION_CONFIG.llmJudge.enabled || resolveLLMBackend().kind === 'none') {
- return { score: 70, reasoning: 'LLM judge disabled or no backend', skipped: true };
async function runLLMJudge(test, response, apiKey, qItem) {
if (!EVALUATION_CONFIG.llmJudge.enabled || (!apiKey && !state.settings?.useLocal)) {
return { score: 70, reasoning: 'LLM judge disabled or no API key', skipped: true };
@@ -12627,11 +12593,6 @@ ${m.name}
{ role: 'system', content: systemPrompt },
{ role: 'user', content: test.challenge }
],
- { model: selectedModel, systemPrompt, maxTokens: 1000, temperature: opConfig?.params?.temperature || 0.3, timeout: 30000, title: 'T3MP3ST Benchmark' }
- );
- } catch (err) {
- addIntel('API', `Error: ${String(err.message).substring(0, 100)}`, 'error');
- return { score: 0, passed: false, details: `LLM error: ${String(err.message).substring(0, 120)}`, response: String(err.message) };
{
model: selectedModel,
maxTokens: 1000,
@@ -12887,11 +12848,6 @@ ${cs.category} ${cs.category} ${cs.category} ${cs.category} ${cs.category} ${cs.category}