Lets the worker-side agent see whether the project it just wrote actually compiles in the user's browser, so it can fix dependency typos and build errors without human intervention. bolt.new / Replit Agent pattern, adapted for an edge runtime where
run_commandis disabled.
In framework mode (framework: "react" | "vue" | "svelte" | "vanilla") the
agent runs on Cloudflare Workers and writes files into a virtual filesystem.
Execution happens in the user's browser, inside a WebContainer. Pre-B2,
the agent was blind:
- The worker has no
run_command(edge runtime can't spawn processes). - Build/install errors only ever reached the human looking at the preview tab.
- An agent that mis-spelt
react-doominstead ofreact-domwould happily emit a "Project ready" final answer while the dev server crashed.
That's the gap bolt.new and Replit Agent close — they let the agent see its own build failures and patch them. B2 closes the same gap for BSCode.
┌──────────────────────────────────────────────────────┐
│ Browser (Next.js) │
│ ┌────────────────────────────────────────────────┐ │
│ │ useWebContainer() │ │
│ │ • runProject() / hotUpdate() │ │
│ │ • on stage transitions ──────► fetch POST │ │
│ │ {status, stage, exitCode, stderr, ...} │ │
│ └────────────────────────────────────────────────┘ │
└──────────────┬───────────────────────────────────────┘
│ POST /build-result (X-Session-Id: …)
▼
┌──────────────────────────────────────────────────────┐
│ Worker (Hono) │
│ ┌─────────────────┐ ┌──────────────────────┐ │
│ │ POST /build- │──► │ build-results store │ │
│ │ result │ │ (memory + KV mirror)│ │
│ └─────────────────┘ └──────────┬───────────┘ │
│ │ │
│ ┌─────────────────────────────┐ │ │
│ │ framework agent's tools │ │ │
│ │ • read_build_result ◄─────┼────┘ │
│ └─────────────────────────────┘ │
└──────────────────────────────────────────────────────┘
- Browser-side
useWebContainerreports stage transitions (install start/end, dev-server ready, build error) toPOST /build-resultwith the session id inX-Session-Id. - Worker stores the latest snapshot per session in memory; mirrors to
BSCODE_BUILD_RESULTSKV when bound, so a worker recycle does not drop it mid-conversation. - When the agent runs in framework mode, the
read_build_resulttool is registered. Calling it returns the most recent snapshot. - The framework system prompt (see
BUILD_VALIDATIONinapps/worker/src/agents/prompts.ts) instructs the agent to callread_build_resultafter writing files, branch onsuccess | failed | running | unknown, and patch the source on failure.
| Method | Path | Purpose |
|---|---|---|
| POST | /build-result |
Browser writes the latest snapshot |
| GET | /build-result |
Debug readback (the agent uses the tool) |
| DELETE | /build-result |
Clears the snapshot (eg on session reset) |
The X-Session-Id header partitions snapshots; without it requests fall
back to the default session id used by everything else in BSCode.
{
name: "read_build_result",
readOnly: true,
idempotent: true,
// returns: a multi-line string the model can branch on:
//
// status: success (dev) 3s ago
// exitCode: 0
// previewUrl: https://x.local
//
// status: failed (build) 1s ago
// --- stderr (tail) ---
// src/App.tsx:5:8 - error TS2307: Cannot find module 'react-doom'
}Registered automatically when:
- the run is in framework mode (
body.frameworkis set), AND X-Session-Idis present.
useWebContainer() already surfaces buildError and terminalLines for the
UI; B2 adds reportBuildResult() calls at the same lifecycle points
(install start/end, dev-server ready, build error). No new return value —
the wiring is invisible to the rest of the React tree.
# apps/worker/wrangler.toml
[[kv_namespaces]]
binding = "BSCODE_BUILD_RESULTS"
id = "your-kv-namespace-id"Without the binding the store is in-memory only. That is fine for local dev (a single Bun watcher process holds the snapshot), and even on Workers it's usually fine for a single conversation — the binding is the durability upgrade for cross-recycle continuity.
apps/worker/src/build-results.ts— store implementationapps/worker/src/tools/build-result.ts— agent-facing toolapps/worker/src/build-results.test.ts— store testsapps/worker/src/tools/build-result.test.ts— tool testsapps/worker/src/app.test.ts— HTTP route tests under "Build result reverse channel (B2)"apps/web/src/hooks/useWebContainer.ts— browser-side reporter