summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--packages/opencode/src/cli/cmd/workspace-serve.ts59
-rw-r--r--packages/opencode/src/index.ts9
2 files changed, 67 insertions, 1 deletions
diff --git a/packages/opencode/src/cli/cmd/workspace-serve.ts b/packages/opencode/src/cli/cmd/workspace-serve.ts
new file mode 100644
index 000000000..9b47defd3
--- /dev/null
+++ b/packages/opencode/src/cli/cmd/workspace-serve.ts
@@ -0,0 +1,59 @@
+import { cmd } from "./cmd"
+import { withNetworkOptions, resolveNetworkOptions } from "../network"
+import { Installation } from "../../installation"
+
+export const WorkspaceServeCommand = cmd({
+ command: "workspace-serve",
+ builder: (yargs) => withNetworkOptions(yargs),
+ describe: "starts a remote workspace websocket server",
+ handler: async (args) => {
+ const opts = await resolveNetworkOptions(args)
+ const server = Bun.serve<{ id: string }>({
+ hostname: opts.hostname,
+ port: opts.port,
+ fetch(req, server) {
+ const url = new URL(req.url)
+ if (url.pathname === "/ws") {
+ const id = Bun.randomUUIDv7()
+ if (server.upgrade(req, { data: { id } })) return
+ return new Response("Upgrade failed", { status: 400 })
+ }
+
+ if (url.pathname === "/health") {
+ return new Response("ok", {
+ status: 200,
+ headers: {
+ "content-type": "text/plain; charset=utf-8",
+ },
+ })
+ }
+
+ return new Response(
+ JSON.stringify({
+ service: "workspace-server",
+ ws: `ws://${server.hostname}:${server.port}/ws`,
+ }),
+ {
+ status: 200,
+ headers: {
+ "content-type": "application/json; charset=utf-8",
+ },
+ },
+ )
+ },
+ websocket: {
+ open(ws) {
+ ws.send(JSON.stringify({ type: "ready", id: ws.data.id }))
+ },
+ message(ws, msg) {
+ const text = typeof msg === "string" ? msg : msg.toString()
+ ws.send(JSON.stringify({ type: "message", id: ws.data.id, text }))
+ },
+ close() {},
+ },
+ })
+
+ console.log(`workspace websocket server listening on ws://${server.hostname}:${server.port}/ws`)
+ await new Promise(() => {})
+ },
+})
diff --git a/packages/opencode/src/index.ts b/packages/opencode/src/index.ts
index 655156588..9af79278c 100644
--- a/packages/opencode/src/index.ts
+++ b/packages/opencode/src/index.ts
@@ -13,6 +13,7 @@ import { Installation } from "./installation"
import { NamedError } from "@opencode-ai/util/error"
import { FormatError } from "./cli/error"
import { ServeCommand } from "./cli/cmd/serve"
+import { WorkspaceServeCommand } from "./cli/cmd/workspace-serve"
import { Filesystem } from "./util/filesystem"
import { DebugCommand } from "./cli/cmd/debug"
import { StatsCommand } from "./cli/cmd/stats"
@@ -45,7 +46,7 @@ process.on("uncaughtException", (e) => {
})
})
-const cli = yargs(hideBin(process.argv))
+let cli = yargs(hideBin(process.argv))
.parserConfiguration({ "populate--": true })
.scriptName("opencode")
.wrap(100)
@@ -141,6 +142,12 @@ const cli = yargs(hideBin(process.argv))
.command(PrCommand)
.command(SessionCommand)
.command(DbCommand)
+
+if (Installation.isLocal()) {
+ cli = cli.command(WorkspaceServeCommand)
+}
+
+cli = cli
.fail((msg, err) => {
if (
msg?.startsWith("Unknown argument") ||