Merge branch 'node-pty' into pr-18335

This commit is contained in:
Dax Raad
2026-03-26 19:04:00 -04:00
10 changed files with 131 additions and 15 deletions
+4 -7
View File
@@ -3,7 +3,7 @@ import { Bus } from "@/bus"
import { InstanceState } from "@/effect/instance-state"
import { makeRuntime } from "@/effect/run-service"
import { Instance } from "@/project/instance"
import { type IPty } from "bun-pty"
import type { Proc } from "#pty"
import z from "zod"
import { Log } from "../util/log"
import { lazy } from "@opencode-ai/util/lazy"
@@ -30,7 +30,7 @@ export namespace Pty {
type Active = {
info: Info
process: IPty
process: Proc
buffer: string
bufferCursor: number
cursor: number
@@ -52,10 +52,7 @@ export namespace Pty {
return out
}
const pty = lazy(async () => {
const { spawn } = await import("bun-pty")
return spawn
})
const pty = lazy(() => import("#pty"))
export const Info = z
.object({
@@ -199,7 +196,7 @@ export namespace Pty {
}
log.info("creating session", { id, cmd: command, args, cwd })
const spawn = await pty()
const { spawn } = await pty()
const proc = spawn(command, args, {
name: "xterm-256color",
cwd,
+26
View File
@@ -0,0 +1,26 @@
import { spawn as create } from "bun-pty"
import type { Opts, Proc } from "./pty"
export type { Disp, Exit, Opts, Proc } from "./pty"
export function spawn(file: string, args: string[], opts: Opts): Proc {
const pty = create(file, args, opts)
return {
pid: pty.pid,
onData(listener) {
return pty.onData(listener)
},
onExit(listener) {
return pty.onExit(listener)
},
write(data) {
pty.write(data)
},
resize(cols, rows) {
pty.resize(cols, rows)
},
kill(signal) {
pty.kill(signal)
},
}
}
+26
View File
@@ -0,0 +1,26 @@
import * as pty from "node-pty"
import type { Opts, Proc } from "./pty"
export type { Disp, Exit, Opts, Proc } from "./pty"
export function spawn(file: string, args: string[], opts: Opts): Proc {
const proc = pty.spawn(file, args, opts)
return {
pid: proc.pid,
onData(listener) {
return proc.onData(listener)
},
onExit(listener) {
return proc.onExit(listener)
},
write(data) {
proc.write(data)
},
resize(cols, rows) {
proc.resize(cols, rows)
},
kill(signal) {
proc.kill(signal)
},
}
}
+25
View File
@@ -0,0 +1,25 @@
export type Disp = {
dispose(): void
}
export type Exit = {
exitCode: number
signal?: number | string
}
export type Opts = {
name: string
cols?: number
rows?: number
cwd?: string
env?: Record<string, string>
}
export type Proc = {
pid: number
onData(listener: (data: string) => void): Disp
onExit(listener: (event: Exit) => void): Disp
write(data: string): void
resize(cols: number, rows: number): void
kill(signal?: string): void
}
+2 -1
View File
@@ -25,7 +25,7 @@ import { ProviderID } from "../provider/schema"
import { WorkspaceRouterMiddleware } from "../control-plane/workspace-router-middleware"
import { ProjectRoutes } from "./routes/project"
import { SessionRoutes } from "./routes/session"
// import { PtyRoutes } from "./routes/pty"
import { PtyRoutes } from "./routes/pty"
import { McpRoutes } from "./routes/mcp"
import { FileRoutes } from "./routes/file"
import { ConfigRoutes } from "./routes/config"
@@ -524,6 +524,7 @@ export namespace Server {
return c.json(await Format.status())
},
)
.route("/pty", PtyRoutes(ws.upgradeWebSocket))
.all("/*", async (c) => {
const embeddedWebUI = await embeddedUIPromise
const path = c.req.path