feat(tui): wire simulation control server

This commit is contained in:
James Long
2026-07-01 14:34:23 -04:00
parent 842e6b77ee
commit 48a7685db6
5 changed files with 13 additions and 2 deletions
+2 -2
View File
@@ -12,14 +12,14 @@ This phase proves the core shape without swapping every foundational layer yet.
Implementation checklist:
- [ ] Add `OPENCODE_SIMULATION=1` activation in V1/full-TUI startup.
- [x] Add `OPENCODE_SIMULATION=1` activation in V1/full-TUI startup.
- [x] Add simulation trace service with in-memory append-only records.
- [x] Add OpenTUI UI state extraction for screen, focus, elements, and generated actions.
- [x] Add OpenTUI UI action execution for typing, keys, enter, arrows, focus, and click.
- [x] Add reusable JSON-RPC WebSocket server on `127.0.0.1:40900+`.
- [x] Expose `ui.state`, `ui.action`, `ui.render`.
- [x] Expose `trace.list`, `trace.clear`, `trace.export`.
- [ ] Wire fake and visible V1/full-TUI renderer paths through the same action protocol.
- [x] Wire visible V1/full-TUI renderer path through the same action protocol.
- [ ] Verify a local driver can inspect state and execute a real TUI input.
Scope:
+11
View File
@@ -230,6 +230,17 @@ export const run = Effect.fn("Tui.run")(function* (input: TuiInput) {
renderer.once("destroy", () => Deferred.doneUnsafe(shutdown, Effect.void))
const pluginRuntime = createPluginRuntime()
const simulation = yield* Effect.promise(async () => {
if (process.env.OPENCODE_SIMULATION !== "1" && process.env.OPENCODE_SIMULATION !== "true") return
const { SimulationActions } = await import("./simulation/actions")
const { SimulationServer } = await import("./simulation/server")
return SimulationServer.start(SimulationActions.createHarness(renderer))
})
if (simulation) {
process.stderr.write(`opencode simulation websocket: ${simulation.url}\n`)
yield* Effect.addFinalizer(() => Effect.sync(() => simulation.stop()))
}
yield* Effect.tryPromise(async () => {
// Prewarm palette before ThemeProvider mounts so `system` theme avoids a first-paint fallback flash.
void renderer.getPalette({ size: 16 }).catch(() => undefined)