Просмотр исходного кода

feat(core): add workspace-serve command (experimental) (#14960)

James Long 1 месяц назад
Родитель
Сommit
2c00eb60bd
2 измененных файлов с 67 добавлено и 1 удалено
  1. 59 0
      packages/opencode/src/cli/cmd/workspace-serve.ts
  2. 8 1
      packages/opencode/src/index.ts

+ 59 - 0
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(() => {})
+  },
+})

+ 8 - 1
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") ||