← back to Model Arena
liveness: fix OpenAI max_completion_tokens (gpt-5.1 generates), repoint 4th local slot off wedged Mac1 → Mac2 qwen2.5, replace status-based double-fire guard with in-flight Set (create path no longer blocked)
a7941bbce89d6e354e86937a945bf93b5ac7fa8e · 2026-07-22 23:07:57 -0700 · Steve
Files touched
A data/artifacts/8dd797019e83/gpt.htmlA data/artifacts/8dd797019e83/grok.htmlA data/artifacts/8dd797019e83/kimi.htmlA data/artifacts/8dd797019e83/qwen25-7b.htmlM data/challenges.jsonM data/costlog.jsonlM data/votes.jsonlM server.js
Diff
commit a7941bbce89d6e354e86937a945bf93b5ac7fa8e
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jul 22 23:07:57 2026 -0700
liveness: fix OpenAI max_completion_tokens (gpt-5.1 generates), repoint 4th local slot off wedged Mac1 → Mac2 qwen2.5, replace status-based double-fire guard with in-flight Set (create path no longer blocked)
---
data/artifacts/8dd797019e83/gpt.html | 10 +
data/artifacts/8dd797019e83/grok.html | 5 +
data/artifacts/8dd797019e83/kimi.html | 8 +
data/artifacts/8dd797019e83/qwen25-7b.html | 15 ++
data/challenges.json | 329 ++++++++++++++++++++++++++++-
data/costlog.jsonl | 3 +
data/votes.jsonl | 3 +
server.js | 28 ++-
8 files changed, 384 insertions(+), 17 deletions(-)
diff --git a/data/artifacts/8dd797019e83/gpt.html b/data/artifacts/8dd797019e83/gpt.html
new file mode 100644
index 0000000..c308471
--- /dev/null
+++ b/data/artifacts/8dd797019e83/gpt.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>OK</title>
+</head>
+<body>
+<h1>OK</h1>
+</body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/8dd797019e83/grok.html b/data/artifacts/8dd797019e83/grok.html
new file mode 100644
index 0000000..aefcb4f
--- /dev/null
+++ b/data/artifacts/8dd797019e83/grok.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<html>
+<head><meta charset="UTF-8"></head>
+<body><h1>OK</h1></body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/8dd797019e83/kimi.html b/data/artifacts/8dd797019e83/kimi.html
new file mode 100644
index 0000000..b3fd228
--- /dev/null
+++ b/data/artifacts/8dd797019e83/kimi.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<title>OK</title>
+</head>
+<body><h1>OK</h1></body>
+</html>
\ No newline at end of file
diff --git a/data/artifacts/8dd797019e83/qwen25-7b.html b/data/artifacts/8dd797019e83/qwen25-7b.html
new file mode 100644
index 0000000..45a4c17
--- /dev/null
+++ b/data/artifacts/8dd797019e83/qwen25-7b.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<title>OK</title>
+<style>
+body { margin: 0; display: flex; align-items: center; justify-content: center; height: 100vh; }
+h1 { text-align: center; }
+</style>
+<script>
+document.write('<h1>OK</h1>');
+</script>
+</head>
+<body></body>
+</html>
\ No newline at end of file
diff --git a/data/challenges.json b/data/challenges.json
index 3e9fc93..539ee7c 100644
--- a/data/challenges.json
+++ b/data/challenges.json
@@ -4,7 +4,7 @@
"title": "Smoke Test: Particle Fireworks",
"prompt": "Build an interactive fireworks simulator in a single HTML file: click anywhere to launch a rocket that explodes into physics-based particles with trails, gravity, and glow. Include an auto-show mode. Keep it under 200 lines.",
"created_at": "2026-07-23T05:02:46.618Z",
- "winner": "gemma3-12b",
+ "winner": "kimi",
"runs": [
{
"model": "hermes3-8b",
@@ -56,14 +56,14 @@
"finished_at": "2026-07-23T05:36:35.854Z"
}
],
- "voted_at": "2026-07-23T05:15:22.408Z"
+ "voted_at": "2026-07-23T05:51:00.009Z"
},
{
"id": "966d54f224fd",
"title": "neon city",
"prompt": "playable html game like tron",
"created_at": "2026-07-23T05:29:23.102Z",
- "winner": null,
+ "winner": "grok",
"runs": [
{
"model": "qwen3-14b",
@@ -140,14 +140,15 @@
"bytes": 7691,
"finished_at": "2026-07-23T05:29:58.821Z"
}
- ]
+ ],
+ "voted_at": "2026-07-23T05:51:21.751Z"
},
{
"id": "74df3b61e7ca",
"title": "Synthwave Visualizer",
"prompt": "Build a synthwave music visualizer using WebAudio oscillators (no external audio files): a retro sun over an animated perspective grid that pulses to generated music, with play/stop controls.",
"created_at": "2026-07-23T05:36:38.158Z",
- "winner": null,
+ "winner": "grok",
"runs": [
{
"model": "qwen3-14b",
@@ -180,12 +181,12 @@
},
{
"model": "qwen25-7b",
- "status": "running",
- "error": null,
- "seconds": 0,
+ "status": "error",
+ "error": "timeout after 600s",
+ "seconds": 600,
"cost": null,
"started_at": "2026-07-23T05:39:54.409Z",
- "finished_at": null
+ "finished_at": "2026-07-23T05:49:54.388Z"
},
{
"model": "claude",
@@ -225,6 +226,316 @@
"bytes": 17543,
"finished_at": "2026-07-23T05:37:35.718Z"
}
+ ],
+ "voted_at": "2026-07-23T05:51:45.195Z"
+ },
+ {
+ "id": "93946ee6d736",
+ "title": "Interior Design Quality WP",
+ "prompt": "You are an expert architectural visualization and interior designer.\n\nVisit the New Arrivals collection on Designer Wallcoverings – New Arrivals and select one wallpaper design that you believe is the strongest choice for a luxury residential space. Use only a design from the current New Arrivals collection. \nD\nDesigner Wallcoverings and Fabrics\n\nTask\nCreate a photorealistic rendering of the provided room by applying the same selected wallpaper design continuously across every wall in the room.\n\nRequirements\nSelect only one wallpaper pattern.\nApply that identical pattern to all visible walls.\nDo not mix patterns or colors.\nPreserve the room's:\narchitecture\nfurniture\nflooring\nceiling\nwindows\nlighting\ntrim and moldings\nMaintain accurate wallpaper scale and repeat.\nEnsure pattern alignment across adjacent walls and around corners.\nRespect perspective, lighting, shadows, and wall geometry.\nDo not alter furniture placement or add decorative elements.\nKeep the rendering highly photorealistic with natural materials and realistic texture.\nOutput\nProvide:\n\nThe rendered image.\nWallpaper name.\nBrand/manufacturer.\nLink to the selected wallpaper product.\nA brief explanation (2–3 sentences) of why this wallpaper was chosen for the space.\nEvaluation Criteria\nScore each model from 1–10 on:\n\nCriterion\tDescription\nWallpaper Selection\tAppropriate choice from New Arrivals\nPattern Accuracy\tCorrect reproduction of wallpaper\nFull-Wall Coverage\tEvery wall covered consistently\nPattern Alignment\tProper matching across corners and walls\nScale Accuracy\tRealistic wallpaper repeat size\nPhotorealism\tRendering quality\nLighting Consistency\tWallpaper reacts naturally to lighting\nGeometry Preservation\tRoom proportions unchanged\nInstruction Following\tNo extra modifications\nOverall Interior Design Quality\tProfessional aesthetic\n\nImportant: The wallpaper must come from the current Designer Wallcoverings New Arrivals collection, and the same design must be used uniformly on every wall without",
+ "created_at": "2026-07-23T05:53:30.025Z",
+ "winner": null,
+ "runs": [
+ {
+ "model": "qwen3-14b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gemma3-12b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "hermes3-8b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "qwen25-7b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "claude",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "kimi",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gpt",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "grok",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ }
+ ]
+ },
+ {
+ "id": "acebf42d306a",
+ "title": "data collection ability",
+ "prompt": "If your goal is to compare 6 AI models on data collection ability, research quality, reasoning, and response speed, use a prompt that forces them to gather, organize, verify, and summarize information in a measurable way.\n\nBenchmark Prompt\nYou are being evaluated against other AI models.\n\nTask:\nResearch the current state of the AI coding assistant market.\n\nRequirements:\n1. Identify the top 10 AI coding assistants available today.\n2. For each assistant provide:\n - Company\n - Release year\n - Primary strengths\n - Weaknesses\n - Pricing\n - Supported IDEs\n - Supported models\n - Context window (if available)\n - Official website\n3. Compare all 10 in a markdown table.\n4. Rank the top 5 for:\n - Coding\n - Speed\n - Accuracy\n - Cost\n5. Include citations or sources for every factual claim.\n6. State any uncertainties rather than guessing.\n7. End with a concise executive summary (under 200 words).\n\nEvaluation criteria:\n- Accuracy\n- Completeness\n- Organization\n- Citation quality\n- Hallucination rate\n- Time to first token\n- Total completion time\n\nOutput only markdown.\n\nWhat to Measure\nMetric\tHow to Score\nTime to first token\tSeconds\nTotal response time\tSeconds\nAccuracy\t1–10\nCompleteness\t1–10\nCitation quality\t1–10\nHallucinations\tCount incorrect facts\nFormatting\t1–10\nOverall usefulness\t1–10\n\nIf you want to really stress-test them\nResearch the latest developments in quantum computing during the last 12 months.\n\nRequirements:\n- Use at least 15 sources.\n- Include academic papers, company announcements, and news.\n- Distinguish confirmed facts from speculation.\n- Build a timeline.\n- Compare IBM, Google, Microsoft, Quantinuum, PsiQuantum, and IonQ.\n- Provide citations for every section.\n- Mention conflicting reports.\n- Produce a 1,500-word report with a comparison table and executive summary.\n\nThis benchmark exercises:\n\nLive web research (if available)\nData collection\nSource verification\nInformation synthesis\nReasoning\nLong-context handling\nSpeed\nIt works well for comparing models such as GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Qwen, and others.",
+ "created_at": "2026-07-23T05:55:46.342Z",
+ "winner": null,
+ "runs": [
+ {
+ "model": "qwen3-14b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gemma3-12b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "hermes3-8b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "qwen25-7b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "claude",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "kimi",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gpt",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "grok",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ }
+ ]
+ },
+ {
+ "id": "35303b0ef3b8",
+ "title": "Propagation check",
+ "prompt": "Reply with exactly one short sentence: name a color.",
+ "created_at": "2026-07-23T06:00:00.593Z",
+ "winner": null,
+ "runs": [
+ {
+ "model": "qwen3-14b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gemma3-12b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "hermes3-8b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "qwen25-7b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "claude",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "kimi",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gpt",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "grok",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ }
+ ]
+ },
+ {
+ "id": "8dd797019e83",
+ "title": "Liveness Probe",
+ "prompt": "Return a single-file HTML page whose body contains exactly the text OK in an <h1>. Nothing else.",
+ "created_at": "2026-07-23T06:01:37.215Z",
+ "winner": null,
+ "runs": [
+ {
+ "model": "qwen25-7b",
+ "status": "done",
+ "error": null,
+ "seconds": 2,
+ "cost": 0,
+ "started_at": "2026-07-23T06:06:16.958Z",
+ "finished_at": "2026-07-23T06:06:19.195Z",
+ "bytes": 300
+ },
+ {
+ "model": "gpt",
+ "status": "done",
+ "error": null,
+ "seconds": 2,
+ "cost": 0.0009,
+ "started_at": "2026-07-23T06:06:16.976Z",
+ "finished_at": "2026-07-23T06:06:18.888Z",
+ "bytes": 113
+ },
+ {
+ "model": "grok",
+ "status": "done",
+ "error": null,
+ "seconds": 3,
+ "cost": 0.0014,
+ "started_at": "2026-07-23T06:06:16.994Z",
+ "finished_at": "2026-07-23T06:06:19.832Z",
+ "bytes": 91
+ },
+ {
+ "model": "kimi",
+ "status": "done",
+ "error": null,
+ "seconds": 30,
+ "cost": 0.0031,
+ "started_at": "2026-07-23T06:06:17.005Z",
+ "finished_at": "2026-07-23T06:06:46.532Z",
+ "bytes": 121
+ }
+ ]
+ },
+ {
+ "id": "e4acfac81892",
+ "title": "Propagation check 2",
+ "prompt": "Reply with exactly one short sentence: name a color.",
+ "created_at": "2026-07-23T06:02:20.024Z",
+ "winner": null,
+ "runs": [
+ {
+ "model": "qwen3-14b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gemma3-12b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "hermes3-8b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "qwen25-7b",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "claude",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "kimi",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "gpt",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ },
+ {
+ "model": "grok",
+ "status": "error",
+ "error": "server restarted mid-run",
+ "seconds": 0,
+ "cost": null
+ }
]
}
]
\ No newline at end of file
diff --git a/data/costlog.jsonl b/data/costlog.jsonl
index 8411679..ed466ee 100644
--- a/data/costlog.jsonl
+++ b/data/costlog.jsonl
@@ -3,3 +3,6 @@
{"ts":"2026-07-23T05:36:35.853Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena","input_tokens":127,"output_tokens":2649,"cost_usd":0.006699}
{"ts":"2026-07-23T05:37:35.716Z","provider":"xai","model":"grok-4.5","task":"model-arena","input_tokens":322,"output_tokens":6581,"cost_usd":0.099681}
{"ts":"2026-07-23T05:42:06.899Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena","input_tokens":120,"output_tokens":5902,"cost_usd":0.014827}
+{"ts":"2026-07-23T06:06:18.884Z","provider":"openai","model":"gpt-5.1","task":"model-arena","input_tokens":103,"output_tokens":49,"cost_usd":0.000866}
+{"ts":"2026-07-23T06:06:19.831Z","provider":"xai","model":"grok-4.5","task":"model-arena","input_tokens":308,"output_tokens":33,"cost_usd":0.001419}
+{"ts":"2026-07-23T06:06:46.529Z","provider":"moonshot","model":"kimi-k2.5","task":"model-arena","input_tokens":104,"output_tokens":1221,"cost_usd":0.003115}
diff --git a/data/votes.jsonl b/data/votes.jsonl
index 536246e..6081896 100644
--- a/data/votes.jsonl
+++ b/data/votes.jsonl
@@ -1 +1,4 @@
{"ts":"2026-07-23T05:15:22.408Z","challenge":"0ac1af2eaed4","title":"Smoke Test: Particle Fireworks","winner":"gemma3-12b","field":["hermes3-8b","gemma3-12b"]}
+{"ts":"2026-07-23T05:51:00.009Z","challenge":"0ac1af2eaed4","title":"Smoke Test: Particle Fireworks","winner":"kimi","field":["hermes3-8b","gemma3-12b","qwen3-14b","kimi"]}
+{"ts":"2026-07-23T05:51:21.751Z","challenge":"966d54f224fd","title":"neon city","winner":"grok","field":["gemma3-12b","hermes3-8b","kimi","grok"]}
+{"ts":"2026-07-23T05:51:45.195Z","challenge":"74df3b61e7ca","title":"Synthwave Visualizer","winner":"grok","field":["gemma3-12b","hermes3-8b","kimi","grok"]}
diff --git a/server.js b/server.js
index 1b6e3e0..2314881 100644
--- a/server.js
+++ b/server.js
@@ -32,7 +32,9 @@ const MODELS = [
{ id: 'qwen3-14b', label: 'Qwen3 14B', kind: 'local', host: 'http://localhost:11434', model: 'qwen3:14b', estCost: 0 },
{ id: 'gemma3-12b', label: 'Gemma3 12B', kind: 'local', host: 'http://localhost:11434', model: 'gemma3:12b', estCost: 0 },
{ id: 'hermes3-8b', label: 'Hermes3 8B', kind: 'local', host: 'http://localhost:11434', model: 'hermes3:8b', estCost: 0 },
- { id: 'qwen25-7b', label: 'Qwen2.5 7B (Mac1)', kind: 'local', host: 'http://192.168.1.133:11434', model: 'qwen2.5:7b', estCost: 0 },
+ // was Mac1 (192.168.1.133) — that Ollama host wedges (model pinned in VRAM, generations hang);
+ // repointed to Mac2-local qwen2.5 for reliable liveness. Set OLLAMA_MAC1=1 to use Mac1 again.
+ { id: 'qwen25-7b', label: 'Qwen2.5 (local)', kind: 'local', host: process.env.OLLAMA_MAC1 ? 'http://192.168.1.133:11434' : 'http://localhost:11434', model: process.env.OLLAMA_MAC1 ? 'qwen2.5:7b' : 'qwen2.5:latest', estCost: 0 },
{ id: 'claude', label: 'Claude Fable 5', kind: 'metered', provider: 'anthropic', model: 'claude-fable-5', envKey: 'ANTHROPIC_API_KEY', estCost: 0.15 },
{ id: 'kimi', label: 'Kimi K2.5', kind: 'metered', provider: 'moonshot', model: 'kimi-k2.5', envKey: 'MOONSHOT_API_KEY', estCost: 0.03 },
{ id: 'gpt', label: 'GPT-5.1', kind: 'metered', provider: 'openai', model: process.env.OPENAI_MODEL || 'gpt-5.1', envKey: 'OPENAI_API_KEY', estCost: 0.10 },
@@ -108,6 +110,9 @@ function onKey(key, fn) {
queues[key] = next.catch(() => {});
return next;
}
+// (challenge,model) pairs currently enqueued-or-running — prevents a second
+// runModel() call from double-enqueuing the same run (the metered double-spend race)
+const inFlight = new Set();
async function generateLocal(m, prompt) {
const r = await httpJson(m.host + '/api/chat', {}, {
@@ -142,8 +147,12 @@ async function generateMetered(m, prompt) {
inTok = (r.json.usage && r.json.usage.input_tokens) || 0; outTok = (r.json.usage && r.json.usage.output_tokens) || 0;
} else {
const base = { moonshot: 'https://api.moonshot.ai/v1', openai: 'https://api.openai.com/v1', xai: 'https://api.x.ai/v1' }[m.provider];
- const r = await httpJson(base + '/chat/completions', { headers: { Authorization: 'Bearer ' + key } },
- { model: m.model, temperature: m.provider === 'moonshot' ? 1 : 0.7, max_tokens: 16000, messages: [{ role: 'user', content: prompt }] }, 300000);
+ // gpt-5 family only accepts max_completion_tokens (not max_tokens) and only
+ // the default temperature; moonshot/xai take the classic max_tokens+temperature.
+ const body = m.provider === 'openai'
+ ? { model: m.model, max_completion_tokens: 16000, messages: [{ role: 'user', content: prompt }] }
+ : { model: m.model, temperature: m.provider === 'moonshot' ? 1 : 0.7, max_tokens: 16000, messages: [{ role: 'user', content: prompt }] };
+ const r = await httpJson(base + '/chat/completions', { headers: { Authorization: 'Bearer ' + key } }, body, 300000);
const ch = r.json && r.json.choices && r.json.choices[0];
if (!ch) throw new Error(m.provider + ' error: ' + JSON.stringify(r.json && r.json.error || r.raw).slice(0, 200));
text = ch.message.content || ch.message.reasoning_content || '';
@@ -160,9 +169,11 @@ function runModel(challenge, modelId) {
const m = MODELS.find(x => x.id === modelId);
const run = challenge.runs.find(r => r.model === modelId);
if (!m || !run) return;
- // double-fire guard: never start a model that's already in flight (blocks the
- // metered double-spend race from two rapid retries on the same run)
- if (run.status === 'running' || run.status === 'queued') return;
+ // double-fire guard: never enqueue a (challenge,model) that's already queued or
+ // running — blocks the metered double-spend race from two rapid retries
+ const fkey = challenge.id + ':' + modelId;
+ if (inFlight.has(fkey)) return;
+ inFlight.add(fkey);
run.status = 'queued'; run.error = null; run.started_at = null; run.finished_at = null; saveChallenges(challenges);
const prompt = ARENA_PROMPT(challenge.prompt);
const exec = async () => {
@@ -182,6 +193,7 @@ function runModel(challenge, modelId) {
run.seconds = Math.round((Date.now() - t0) / 1000);
}
run.finished_at = new Date().toISOString();
+ inFlight.delete(fkey);
saveChallenges(challenges);
};
if (m.kind === 'local') onKey(m.host, exec); else onKey('metered:' + m.id, exec);
@@ -198,11 +210,11 @@ setInterval(() => {
let dirty = false;
for (const c of challenges) for (const r of c.runs) {
if (r.status === 'running' && r.started_at && now - Date.parse(r.started_at) > STUCK_RUNNING_MS) {
- r.status = 'error'; r.error = 'timed out (watchdog) — model host unresponsive'; r.finished_at = new Date().toISOString(); dirty = true;
+ r.status = 'error'; r.error = 'timed out (watchdog) — model host unresponsive'; r.finished_at = new Date().toISOString(); inFlight.delete(c.id + ':' + r.model); dirty = true;
} else if (r.status === 'queued' && r.started_at == null) {
// stamp a queue-entry time so we can age it out; reuse challenge age as the floor
const floor = Date.parse(c.created_at || new Date().toISOString());
- if (now - floor > STUCK_QUEUED_MS) { r.status = 'error'; r.error = 'never started — model host busy/down'; r.seconds = 0; r.finished_at = new Date().toISOString(); dirty = true; }
+ if (now - floor > STUCK_QUEUED_MS) { r.status = 'error'; r.error = 'never started — model host busy/down'; r.seconds = 0; r.finished_at = new Date().toISOString(); inFlight.delete(c.id + ':' + r.model); dirty = true; }
}
}
if (dirty) saveChallenges(challenges);
← 45826ed auto-save: 2026-07-22T22:47:10 (5 files) — data/challenges.j
·
back to Model Arena
·
auto-save: 2026-07-22T23:17:18 (4 files) — data/challenges.j 39b20bd →