Spaces:
Sleeping
Sleeping
Commit History
-
chore: switch ENDPOINT to dedicated pod (zopt7f90d1ydgy)
The shared pod (qry6crb96ko8ep) was being saturated by ~2-5 req/sec of external traffic, leading to ~50% HTTP 500 rate even with cache_prompt:false. Build update from b9038 → b9049 didn't fix this; the failure mode is GPU saturation across 4 shared slots, not a slot-bookkeeping bug. New pod zopt7f90d1ydgy is dedicated to mini-world: - LLAMA_ARG_N_PARALLEL=1 (single slot, no multi-tenant slot pollution) - Same image (ghcr.io/ggml-org/llama.cpp:server-cuda) - Same model (unsloth/Qwen3.6-27B-GGUF / Qwen3.6-27B-UD-Q4_K_XL.gguf) - Same RTX 3090, ctx_size 8192 - Costs $0.46/hr — same as old pod Verified: 20/20 successful chat completions on the fresh pod (vs 10/20 on the shared pod immediately after restart). Updated default ENDPOINT in: - server.ts (Space inference loop) - eval.ts (long-horizon eval harness) - eval-scenarios.ts (controlled-scenario eval) - README.md (doc reference) Old pod can be deleted once Space rebuild confirms the new endpoint works.a0a680b -
chore: un-pause Space — other runpod clients dominate, our pause has no effect
b0ef027 -
chore: temporarily pause Space to isolate other runpod clients
36cb9e9 -
feat: enable thinking for the summarizer (only)
Live observation: agent gets stuck in directional loops (e.g. 5 consecutive move:up's all failing with "Cannot move into obstacle"). The error feedback reaches the model on the very next turn but doesn't break the lock. After compaction, the bland bullet summary preserves the loop but doesn't surface it as a problem the agent should correct, so the model resumes the same direction. Hypothesis: a smarter summarizer that actually reasons about what happened can flag the failure pattern explicitly ("direction up is blocked, try another") in the summary the agent reads next turn. Changes: - callSummarizer: chat_template_kwargs.enable_thinking → true. Bumped max_tokens 400 → 2048 to leave room for the thinking chain plus the bullet output. Thinking adds ~5-10s to compaction calls but those happen ~once per ~30 turns, so the per-turn loop stays fast (cache off, ~6-8s/turn). - SUMMARY_SYS: explicitly call out repeated-failure detection as a required signal in the summary — gives t…b5023c0 -
fix: retry connect() forever instead of crashing the Space when pod is restarting
870fbcf -
fix: disable cache_prompt by default — slot poisoning is unfixable on this build
Empirical pattern observed across many runs: ~5-12 turns succeed with cache_prompt:true, then every subsequent request 500s with "Context size has been exceeded", and the retry-without-cache also fails because the upstream slot itself is saturated. Container rebuild fixes it briefly, then the cycle repeats. The clean fix is to stop opting into the broken default. cache_prompt:false on every request gives stable ~6-8s/turn forever, vs ~1.4s/turn with cache that catastrophically fails after a few turns. USE_CACHE env var lets us opt back in once the upstream build (b9038-2ca1161bd) is updated to a version without the regression, without another code change.ac90842 -
chore: trigger Space rebuild after pod restart
82ff8b1 -
chore: drop START_PAUSED — Space runs the agent loop on boot again
e756f4d -
docs: AGENTS.md — document the eval protocol
Future agents working on this repo should default to eval-scenarios.ts (fixed-scenario, score-based) and treat eval.ts as a secondary drift check. Spell out the pre-eval checklist (pause Space, stop local server, verify /slots idle) so the noisy-conclusion mistake from 9f22305 doesn't recur.fa83041 -
revert: noisy-eval conclusion; restore 9×9 viewport + START_PAUSED, add controlled scenarios
Commit 9f22305 ("ship experiment winner — 5×5 viewport + cache") was based on long-horizon eval runs whose signal was dominated by HTTP-500 fallbacks from a contended 4-slot runpod. With the live HF Space and 3 concurrent eval agents all sharing the pod, fallback rates were 50–80% and most "actions" in the metrics were not model decisions. A controlled re-run on hand-authored fixed scenarios (audited in parallel by Codex GPT-5) showed the opposite verdict: variant score tool calls median latency baseline 9×9 10/10 100% 2.2s viewport_5 8/10 100% 2.5s temp_0 9/10 100% 3.8s temp_high 9/10 100% 5.2s thinking_on 9/10 91% 12.0s Changes: - agent-brain.js: buildPickFirstPrompt default radius back to 4 (9×9). The 5×5 setting from 9f22305 came from a noisy long-horizon run. - Dockerfile: re-add ENV START_PAUSED=1. Commit 9f22305 removed it while the agent loop is bei…e782f75 -
chore: gitignore .claude/ runtime files
a1afbd7 -
feat: ship experiment winner — 5×5 viewport + cache, restore Space loop
Ran a controlled benchmark sweep (eval.ts) over five variants × multiple seeds × 20-30 turns each, on a paused-Space + restarted-pod (clean contention environment). Headline numbers from per-variant averages: variant n real/N entropy med ms tilesVisited viewport_5 2 0.62 1.49 7696 12.5 ← best on every metric temp_high 2 0.35 0.46 6536 8.0 baseline 1 0.30 0.00 7751 10.0 viewport_13 2 0.22 0.46 9513 5.5 temp_0 2 0.17 0.00 11956 4.5 cache_on 1 0.40 0.54 3787 n/a ← 80% cache hit, 4× faster Direction histogram across all 9 runs combined: down 41 / right 12 / left 7 / up 4. The "always up" finding from the empty-world probe was artificial — in real worlds with terrain features the model heavily biases *down*. Smaller viewport produced the most direction diversity (viewport_5 seed 2 hit entropy 1.98 with all four directions used). Changes: - agent-brain.js: buildP…9f22305 -
chore: boot Space paused during experiment phase
Add START_PAUSED env var support in server.ts. When START_PAUSED=1, agent loop comes up idle and waits for /api/resume. Set it in the Dockerfile so the deployed Space stops hammering the shared runpod endpoint while we run controlled experiments locally. Resume via the browser when the Space should run again. Local dev unaffected (env unset → unpaused as before). Also: - engine.js: SinglePlayerGame now accepts a {seed} option using a mulberry32 PRNG so eval runs are reproducible across variants. - agent-brain.js: buildPickFirstPrompt and analyzeViewport now take an optional radius (default 4 = 9×9). Allows variant sweeps. - eval.ts (new): headless agent benchmark. Takes --variant --seed --turns and emits one JSON metrics object per run. Variants in VARIANTS map (baseline, viewport_5, viewport_13, temp_0/high, thinking_on, cache_on). Captures: diamonds/N, realActionRate, illegalMoveRate, pickPrecision, directionEntropy, medianLatency, cacheHitRate, full per-turn token s…327ab12 -
fix: no-op the turn on inference failure instead of random walk
Prior behavior: when callModel failed (HTTP error after retries) or returned no usable tool_call, randomFallbackAction() picked a uniform- random direction and the agent moved. This meant the agent's body wandered randomly while the brain had no memory of those moves — fallbacks were invisible to memory because tool_call_id was null. The action histogram looked balanced because of these random-walk turns, masking the model's actual decision distribution. New behavior: on fallback, do nothing. - Snapshot memory.messages.length at the top of each iteration; if no usable action comes back, popLast() until we're back to that depth. Cleans up both an orphan user message (HTTP error path) and an empty assistant turn (no-tool_calls path). - Don't move the agent, don't push to actionLog, don't emit tool_execution_start/end. Just log fallback_action + turn_end and loop. - The agent stays in place. Next iteration rebuilds the same prompt fresh — the runpod LB may pick a healthier sl…700271c -
fix: cache contention + 9×9 viewport + tighter compaction
Three changes from a parallel-agent debugging round investigating why the live agent was hitting 0 diamonds in 34 turns. server.ts callModel: - Old retry only fired when the original request had cache_prompt:true, so once cooldown started, every subsequent 500 fell straight through to fallback. New retry fires on any "Context size has been exceeded" 500 regardless of cache state. - Up to 3 retries with 200ms gap so the upstream LB has a chance to route to a different (non-poisoned) slot. Slot contention is real on this build (b9038-2ca1161bd) — even bare "hi" 500s ~80% of the time when slots are saturated. - Critical: explicitly set `cache_prompt: false` on disabled / retry paths instead of deleting the key. Omitting it falls back to the server's broken default behavior, so deletion was a no-op. - Same explicit cache_prompt on the summarizer. agent-brain.js: - buildPickFirstPrompt viewport: 5×5 → 9×9 (radius 4). The 5×5 worked in unit tests but in the live game the …8c2dc59 -
feat: pause/resume the agent loop without hitting the model
POST /api/pause sets a flag that the loop checks at the top of each iteration; while paused, the loop idles in 500ms ticks and emits no inference calls. POST /api/resume clears the flag and the next iteration runs normally. - server.ts: paused flag, /api/pause + /api/resume handlers, agent_paused / agent_resumed trace events, paused exposed in /api/state debug block. - index.html: status dot renders gray (bg-gray-400, no pulse) when state is "paused" — distinguishable from green (running), yellow (thinking), red (error/fallback). Verified end-to-end: curl -X POST /api/pause → paused:true, status:paused 6s later → turn count unchanged (zero LLM calls) curl -X POST /api/resume → paused:false 12s later → turns advanced 2 → 425db49f -
feat: pi-mono compliant NDJSON traces, debug API, illegal-move rule, red dots
Several related changes that came up while debugging a "constant fallback" state on the live deploy. Game rules: - engine.js: moving onto a tile with a pickable object now throws "Cannot move onto <emoji> — use pick <dir> instead". Forces the model to choose the right tool; the error string self-corrects via the tool result fed back next turn. - agent-brain.js: drop the LEGAL_ACTIONS line and the diamond-adjacent warning from buildPickFirstPrompt — the engine error + tool/system prompt descriptions now carry the constraint. Update tool descriptions and system prompt to match (move fails on diamonds, pick is the way). - index.html: failed actions now render with a red dot in the action history (was always green/blue regardless of outcome). Server-side robustness: - server.ts: cache_prompt:true broke on the upstream llama.cpp build (b9038-2ca1161bd) once a slot accumulated >n_ctx of stale cache. callModel now retries without cache_prompt on "Context size has been ex…c8de5f5 -
feat: move agent loop server-side, multi-viewer SSE livestream
Previously each browser tab ran its own SinglePlayerGame, AgentMemory, and inference loop — two tabs meant two independent worlds with two independent agents. Now the agent runs once on a Bun server that owns the world state and broadcasts every turn to all connected viewers via Server-Sent Events. Multiple tabs see the same agent acting on the same world in lockstep. Files: - server.ts (new): Bun HTTP server. Lifts connect/callModel/callSummarizer/ agent loop verbatim from the previous client-side script. After each turn builds a JSON state snapshot {viewport, inventory, stats, actions, status, thinking, summary, debug} and broadcasts to a Set of SSE controllers. New connections get an immediate snapshot so they don't wait a full turn. All round-1+round-2 mechanics carry over: structured tool_calls, cache_prompt:true, enable_thinking:false, pair-aware trim, popLast on inference failure, n_ctx-derived budgets, LLM-summarization compaction. - index.html: stripped from a 3…f7df30f
-
chore: aggressive cleanup — keep only the browser harness
The repo started as a research project with a multi-agent REST API, ONNX-based eval scripts, a CLI agent client, and several test suites. The shipped browser harness now hits a remote llama.cpp endpoint directly and has no need for any of that infrastructure. Drop it. Removed: - server.ts, gameState.ts, aiService.ts (legacy multi-agent REST API) - middleware/, types.ts, agent-client.ts, replay.html - API.md, openapi.yaml (REST API docs) - __tests__/ entire directory: 10 ai-eval scripts (~1500 LOC) + their result JSONs, plus the e2e/integration/unit test suites for the multi-agent server - Dockerfile, package.json, bun.lockb (no runtime deps anymore) Slimmed: - engine.js: 481 → 175 LOC. Drops the prompt-building helpers (SYS_PROMPT, FEW_SHOT, buildUserPrompt, buildMessages, MCQ_*, getAdjacencyFromViewport, parseAction, isValidAction), the pixel-buffer renderers (renderMapToRGBA, renderAnnotatedMapToRGBA, EMOJI_COLOURS), and unexports the world-gen internals. Public surface…49df1c0 -
deploy: add HF Spaces Dockerfile and Space frontmatter
Mirrors the deploy config that was already running on huggingface.co/spaces/victor/mini-world before this branch was force-pushed. Bun image, server.ts on port 7860, Spaces SDK. Pulls back in: - Dockerfile: oven/bun:1-alpine, frozen-lockfile install, runs as bun user, exposes 7860, CMD runs `bun server.ts`. - README YAML frontmatter: title/emoji/colors, sdk: docker, app_port: 7860 — needed for the Space to build and render the card.f40f7c8 -
docs: refresh README; drop dup AVATAR_EMOJIS from engine.js; commit pending image renderers
- README.md: update to match the current codebase. Document the remote-only Qwen3.6-27B browser harness (cache_prompt, structured tool calling, LLM-summarization compaction). Refresh Architecture, Agent Brain exports, URL params, eval scripts table. Drop sections that referenced deleted multiturn evals. - engine.js: drop the duplicate AVATAR_EMOJIS export. The canonical list is in types.ts and that's what every consumer imports. - engine.js: commit the pending renderMapToRGBA / renderAnnotatedMapToRGBA / EMOJI_COLOURS additions used by the vision eval scripts (tool-calling-eval.ts, tool-calling-v2-eval.ts).a04dc2b -
chore: drop dead code
- aiService.ts: remove the unused re-export of buildUserPrompt; the only consumer (server.ts) imports AIService and MODEL only, and every other caller pulls buildUserPrompt directly from engine.js. - index.html: drop the unused local `lastUsage` variable. The harness uses window.lastUsage for the in-browser test assertions; the local was only ever assigned, never read. - messages.json: delete. Zero references in code; orphan fixture.0a4b824 -
feat: LLM-summarization compaction for long-running sessions
Add a compaction layer to AgentMemory so sessions don't lose episodic memory when the sliding window evicts old turns. When the estimated full-prompt token count exceeds triggerCompactTokens, the loop: 1. walks backward from the newest message to find a cut that snaps to a role:'user' boundary (no orphan tool_call_ids), 2. serializes the evicted prefix into a compact "Turn N: action:dir → result" log (~10x cheaper than replaying raw chat history), 3. calls a summarizer (same llama.cpp endpoint, separate static system prompt, max_tokens=400, temperature=0.2), 4. stores the result on memory.summary and replaces the evicted messages with it. memory.getMessages() injects the summary as a synthetic user→assistant pair right after the system prompt, so the system-prompt prefix stays byte-stable (cache hot) — only the summary anchor moves on compaction. Incremental updates pass the previous summary to the summarizer so it merges rather than re-summarizes fro…54c21b8 -
feat: remote-only harness with proper tool calling and KV-cache reuse
Wire the browser game to an OpenAI-compatible llama.cpp endpoint (Qwen3.6-27B on RunPod) and rebuild the inference loop around it. Drops the in-browser ONNX path and the five non-pick_first strategies that were research vehicles in earlier evals. agent-brain.js shrinks from 462 to 156 LOC; index.html from 487 to 345. Conversation memory now stores OpenAI wire-format messages verbatim (structured tool_calls + role:'tool' results with tool_call_id), so the server can match calls to results and llama.cpp's KV cache reuses the byte-stable prefix across turns. Adds cache_prompt:true to every chat request — at 18 turns the cache hit rate is ~95% (measured via prompt_tokens_details.cached_tokens). The sliding-window trim is now pair-aware: it never leaves a role:'tool' or role:'assistant' message at the head of the conversation, so trims at any token budget can't orphan a tool_call_id pairing. Verification (browser smoke + Chrome DevTools assertions): - every assistant message has a struc…9319953 -
chore: squash pre-2026-05-06 history
Initial mini-world snapshot at c0da002 — collapses 25 commits of research and feature work into a single root: - single-player game engine (Perlin world gen, viewport rendering, image rendering for vision evals) - in-browser ONNX agent with pick_first strategy and 5 alternative prompting strategies for evals - multi-agent REST API server with auth, rate limiting, and SSE - 10 eval scripts comparing prompt strategies, tool calling, vision, and context compaction at 0.8B/2B/4B - agent-client.ts CLI for autonomous play against the API - replay viewer for recorded eval sessions The squashed history is preserved in reflog locally; for the public record this is the starting point that the remote-only harness + compaction work builds on.e208045