Skip to content

Xeo Forge v1.20.1 — Local-First Agent Workbench

Choose a tag to compare

@github-actions github-actions released this 26 Aug 10:06
· 56 commits to master since this release

v1.20.1 — The Honest Hotfix

Summary

This release exists because an audit ran real workloads against the
product instead of trusting its own tests. Every fix below was proven
against a live server before it shipped.

Your answer survives even when the run doesn't

The worst finding: a streamed chat reply lived only in the event log.
If the run failed or was cancelled, everything the user had already
read vanished from history — 6,280 characters of a real reply were the
proof. Now failRun and the cancellation path persist the accumulated
prose as the assistant message before the terminal status lands.

A greeting is not a work order

Chat still offered todo_update, git_op, and http_request — so the
model "worked" on a simple hello, mutating todos, until the progress
guard correctly killed the run as failed. Chat now offers read-only
inspection only (file_read, file_list, skill_view), and the chat
prompt orders zero tool calls for greetings. Live: greeting runs make
zero work-tool calls.

Cancel that actually cancels

A live test caught cancel reporting "no live loop found" while events
kept flowing for another 97 seconds — the registry was a per-bundle Map,
so the cancel route and the loop could hold different copies. The
registry is now anchored on globalThis: one instance per process,
verified with signalled: true and terminal state in under 5 seconds.

Provider errors speak human

Raw internals like 503 auth_unavailable (providers=...) are classified
into honest language with next steps — "The model provider rejected the
API key. Check the key in Settings → Providers, then retry." The full
technical text goes to server logs where it belongs.

Capability probes — proof, not promises

The audit demanded live evidence for every feature. These ship as
reusable scripts:

  • scripts/mcp-live-probe.ts — spawns a real MCP stdio server through
    the project's own client: handshake, listTools (9 tools with full
    schemas), tools/call — PASS. Server output arrives wrapped in the
    untrusted-data quarantine block, exactly as designed.
  • scripts/browser-live-probe.ts — starts the real browser bridge:
    loopback token auth, honest empty state, and navigate blocked by
    the read-only default until explicit permission — PASS.
  • scripts/tools-live-probe.tsskill_view reads a real imported
    skill file through its manifest with the path-escape guard intact;
    http_request returned HTTP 200 live; file_list works — PASS.

Verification

tsc --noEmit clean · lint clean · 818/818 tests · every hotfix
exercised against a running dev server with DB-level confirmation ·
CI green on the merge.