diff --git a/packages/simulation/src/frontend/actions.ts b/packages/simulation/src/frontend/actions.ts index d03e4a5f75..9e5b7bdead 100644 --- a/packages/simulation/src/frontend/actions.ts +++ b/packages/simulation/src/frontend/actions.ts @@ -47,7 +47,7 @@ function hit(renderer: CliRenderer, renderable: Renderable) { /** * Builds the harness the simulation server drives. * - * When the renderer is the fake simulation renderer, its TestRendererSetup + * When the renderer is the headless simulation renderer, its TestRendererSetup * provides the supported testing APIs. For the visible terminal renderer the * harness falls back to `requestRender` + `idle` and reading the private * `currentRenderBuffer`. diff --git a/packages/simulation/src/frontend/renderer.ts b/packages/simulation/src/frontend/renderer.ts index 168a8999b6..e973d57a98 100644 --- a/packages/simulation/src/frontend/renderer.ts +++ b/packages/simulation/src/frontend/renderer.ts @@ -4,7 +4,7 @@ import { createTestRenderer, type TestRendererSetup } from "@opentui/core/testin const setups = new WeakMap() /** - * Creates the fake simulation renderer: a real CliRenderer backed by an + * Creates the headless simulation renderer: a real CliRenderer backed by an * in-memory screen buffer instead of a terminal. The TestRendererSetup is * kept module-side (keyed by renderer) so the harness can use the supported * testing APIs without app code carrying it around. diff --git a/packages/simulation/src/frontend/server.ts b/packages/simulation/src/frontend/server.ts index 854b5e9846..d99334d6a2 100644 --- a/packages/simulation/src/frontend/server.ts +++ b/packages/simulation/src/frontend/server.ts @@ -15,21 +15,16 @@ function parseRequest(input: string | Buffer) { return SimulationProtocol.JsonRpc.decodeRequest(JSON.parse(typeof input === "string" ? input : input.toString())) } -async function handle(harness: Harness, request: SimulationProtocol.JsonRpc.Request) { +async function handle(harness: Harness, request: SimulationProtocol.JsonRpc.Request, headless: boolean) { switch (request.method) { case "ui.state": { + if (headless) await harness.renderOnce() const result = SimulationActions.state(harness) SimulationTrace.add("ui.state", { elements: result.elements.length, actions: result.actions.length }) return result } case "ui.action": return SimulationActions.execute(harness, actionParam(request.params)) - case "ui.render": { - await harness.renderOnce() - const result = SimulationActions.state(harness) - SimulationTrace.add("ui.render", { elements: result.elements.length, actions: result.actions.length }) - return result - } case "trace.list": return { records: SimulationTrace.list() } case "trace.clear": @@ -41,7 +36,7 @@ async function handle(harness: Harness, request: SimulationProtocol.JsonRpc.Requ throw new Error(`Unknown simulation method: ${request.method}`) } -export function start(harness: Harness, endpoint: string): Server { +export function start(harness: Harness, endpoint: string, headless: boolean): Server { const url = new URL(endpoint) const server = Bun.serve<{ readonly drive: true }>({ hostname: url.hostname, @@ -61,7 +56,7 @@ export function start(harness: Harness, endpoint: string): Server { let request: SimulationProtocol.JsonRpc.Request | undefined try { request = parseRequest(message) - const result = await handle(harness, request) + const result = await handle(harness, request, headless) const next = SimulationProtocol.JsonRpc.success(request.id, result) if (next) socket.send(JSON.stringify(next)) } catch (error) { diff --git a/packages/simulation/src/frontend/simulation.ts b/packages/simulation/src/frontend/simulation.ts index 96e68e8dca..c2a56ad8c1 100644 --- a/packages/simulation/src/frontend/simulation.ts +++ b/packages/simulation/src/frontend/simulation.ts @@ -7,19 +7,18 @@ import { SimulationServer } from "./server" /** * Drive-mode renderer entry point. * - * Creates the renderer (fake when OPENCODE_DRIVE_RENDERER=fake, the normal + * Creates the renderer (headless when OPENCODE_DRIVE_RENDERER=headless, the normal * visible renderer otherwise) and starts the UI control * server against it. The server stops when the renderer is destroyed, so the * caller only manages the renderer lifecycle. */ export async function create(options: CliRendererConfig): Promise { - const renderer = - process.env.OPENCODE_DRIVE_RENDERER === "fake" - ? await SimulationRenderer.create(options) - : await createCliRenderer(options) + const headless = process.env.OPENCODE_DRIVE_RENDERER === "headless" + const renderer = headless ? await SimulationRenderer.create(options) : await createCliRenderer(options) const server = SimulationServer.start( SimulationActions.createHarness(renderer), DriveManifest.resolve().endpoints.ui, + headless, ) process.stderr.write(`opencode drive ui websocket: ${server.url}\n`) renderer.once("destroy", () => server.stop())