// Manual smoke test of bridge/server.mjs with a scripted fake page. Starts the bridge on a spare // port, connects, answers tool calls with canned state, sends one short prompt and prints the // events. It runs a real Claude Code turn (uses your login/quota), so it is not part of `npm test`. import { spawn } from "node:child_process"; const port = 8799; const bridge = spawn(process.execPath, ["bridge/server.mjs", "--port", String(port)], { stdio: ["ignore", "pipe", "pipe"] }); bridge.stdout.on("data", (d) => process.stdout.write(`[bridge stdout] ${d}`)); bridge.stderr.on("data", (d) => process.stdout.write(`[bridge stderr] ${d}`)); await new Promise((r) => setTimeout(r, 1500)); const ws = new WebSocket(`ws://localhost:${port}`); const fakeState = { yaml: "hits:\n- time: 0\n r: 0.137\n phi: 0.3\n velocity: 8\n exciter: {kind: mallet}\n", issues: [], preset: "crash_mallet", backend: "webgpu", run: { state: "done", samplesDone: 88200, samplesTotal: 88200, audioSeconds: 2, wallSeconds: 41, audioAvailableSeconds: 1.9999, signal: "unbaffled" }, setup: "mesh: 4657 nodes ...", diagnostics: { time: 2, kinetic: 0.1, membrane: 0.02, bending: 0.05, exciters: 5.2, maxWoverH: 3.1, hits: [{ kind: "mallet", peakForceN: 1310, contactMs: 5.8, exciterVelocity: 5.9 }] }, spectrogram: { bands: [{ lo: 125, hi: 250, onsetMs: 3, peakMs: 29, levelDb: -23 }, { lo: 2000, hi: 4000, onsetMs: 7.3, peakMs: 123, levelDb: -9.6 }, { lo: 8000, hi: 16000, onsetMs: 36, peakMs: 300, levelDb: -30 }], centroidHz: [{ ms: 5, hz: 612 }, { ms: 100, hz: 2393 }] } }; let text = ""; const done = new Promise((resolve) => { ws.onmessage = (ev) => { const m = JSON.parse(ev.data); if (m.type === "delta") { text += m.text; return; } if (m.type === "tool_call") { console.log(`[page] tool call ${m.name} ${JSON.stringify(m.args)}`); ws.send(JSON.stringify({ type: "tool_result", id: m.id, text: m.name === "get_app_state" ? JSON.stringify(fakeState) : "ok" })); return; } console.log(`[event] ${JSON.stringify(m).slice(0, 200)}`); if (m.type === "result") resolve(m); }; }); ws.onopen = () => ws.send(JSON.stringify({ type: "user", text: "Look at the app state and tell me in two sentences whether the last run shows an upward cascade. Do not read any files." })); const result = await Promise.race([done, new Promise((r) => setTimeout(() => r({ timeout: true }), 240000))]); console.log("=== assistant text ===\n" + text + "\n=== result", JSON.stringify(result)); ws.close(); bridge.kill(); process.exit(result.ok ? 0 : 1);