refactor(simulation): scope Drive lifecycle with Effect (#36908)
This commit is contained in:
parent
a149a61a89
commit
947566f611
30 changed files with 1313 additions and 600 deletions
|
|
@ -1,31 +1,19 @@
|
|||
import { Effect } from "effect"
|
||||
import { SimulationControlServer } from "../control-server"
|
||||
import { SimulationProtocol } from "../protocol"
|
||||
import { SimulationActions, type Harness } from "./actions"
|
||||
import { SimulationRenderer } from "./renderer"
|
||||
|
||||
export interface Server {
|
||||
readonly url: string
|
||||
readonly stop: () => void
|
||||
}
|
||||
|
||||
function parseRequest(input: string | Buffer) {
|
||||
return SimulationProtocol.Frontend.decodeRequest(JSON.parse(typeof input === "string" ? input : input.toString()))
|
||||
}
|
||||
|
||||
async function handle(
|
||||
harness: Harness,
|
||||
request: SimulationProtocol.Frontend.Request,
|
||||
finishRecording?: () => Promise<string>,
|
||||
) {
|
||||
function handle(harness: Harness, request: SimulationProtocol.Frontend.Request) {
|
||||
switch (request.method) {
|
||||
case "ui.screenshot":
|
||||
return SimulationActions.screenshot(harness, request.params?.name)
|
||||
case "ui.state": {
|
||||
return SimulationActions.state(harness)
|
||||
}
|
||||
case "ui.state":
|
||||
return Effect.sync(() => SimulationActions.state(harness))
|
||||
case "ui.matches":
|
||||
return SimulationActions.matches(harness, request.params.text)
|
||||
return Effect.sync(() => SimulationActions.matches(harness, request.params.text))
|
||||
case "ui.recording.finish":
|
||||
if (!finishRecording) throw new Error("UI recording is not available")
|
||||
return finishRecording()
|
||||
return SimulationRenderer.finish(harness.renderer)
|
||||
case "ui.type":
|
||||
return SimulationActions.execute(harness, { type: "ui.type", text: request.params.text })
|
||||
case "ui.enter":
|
||||
|
|
@ -48,39 +36,22 @@ async function handle(
|
|||
y: request.params.y,
|
||||
})
|
||||
case "ui.resize":
|
||||
return SimulationActions.execute(harness, { type: "ui.resize", cols: request.params.cols, rows: request.params.rows })
|
||||
return SimulationActions.execute(harness, {
|
||||
type: "ui.resize",
|
||||
cols: request.params.cols,
|
||||
rows: request.params.rows,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function start(harness: Harness, endpoint: string, finishRecording?: () => Promise<string>): Server {
|
||||
const url = new URL(endpoint)
|
||||
const server = Bun.serve<{ readonly drive: true }>({
|
||||
hostname: url.hostname,
|
||||
port: Number(url.port),
|
||||
fetch(request, server) {
|
||||
if (server.upgrade(request, { data: { drive: true } })) return undefined
|
||||
return new Response("opencode drive ui websocket", { status: 426 })
|
||||
},
|
||||
websocket: {
|
||||
async message(socket, message) {
|
||||
let request: SimulationProtocol.Frontend.Request | undefined
|
||||
try {
|
||||
request = parseRequest(message)
|
||||
const result = await handle(harness, request, finishRecording)
|
||||
const next = SimulationProtocol.JsonRpc.success(request.id, result)
|
||||
if (next) socket.send(JSON.stringify(next))
|
||||
} catch (error) {
|
||||
socket.send(JSON.stringify(SimulationProtocol.JsonRpc.failure(request?.id, error)))
|
||||
}
|
||||
},
|
||||
},
|
||||
export const start = Effect.fn("SimulationServer.start")(function* (harness: Harness, endpoint: string) {
|
||||
return yield* SimulationControlServer.start({
|
||||
endpoint,
|
||||
label: "opencode drive ui websocket",
|
||||
data: () => ({ drive: true as const }),
|
||||
decode: SimulationProtocol.Frontend.decodeRequestEffect,
|
||||
handle: (_socket, request) => handle(harness, request),
|
||||
})
|
||||
return {
|
||||
url: endpoint,
|
||||
stop: () => {
|
||||
server.stop(true)
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export * as SimulationServer from "./server"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue