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

add `createOpencodeServer` to js sdk and wait for readiness. always use random port for `opencode serve`. add `/client` and `/server` imports for js sdk

Dax Raad 7 месяцев назад
Родитель
Сommit
d9233872b9
3 измененных файлов с 57 добавлено и 6 удалено
  1. 1 1
      packages/opencode/src/cli/cmd/serve.ts
  2. 51 4
      packages/sdk/js/src/server.ts
  3. 5 1
      tsconfig.json

+ 1 - 1
packages/opencode/src/cli/cmd/serve.ts

@@ -11,7 +11,7 @@ export const ServeCommand = cmd({
         alias: ["p"],
         type: "number",
         describe: "port to listen on",
-        default: 4096,
+        default: 0,
       })
       .option("hostname", {
         alias: ["h"],

+ 51 - 4
packages/sdk/js/src/server.ts

@@ -1,21 +1,68 @@
 import { spawn } from "node:child_process"
 
 export type ServerConfig = {
-  host?: string
+  hostname?: string
   port?: number
+  signal?: AbortSignal
+  timeout?: number
 }
 
 export async function createOpencodeServer(config?: ServerConfig) {
   config = Object.assign(
     {
-      host: "127.0.0.1",
+      hostname: "127.0.0.1",
       port: 4096,
+      timeout: 5000,
     },
     config ?? {},
   )
 
-  const proc = spawn(`opencode`, [`serve`, `--host=${config.host}`, `--port=${config.port}`])
-  const url = `http://${config.host}:${config.port}`
+  const proc = spawn(`opencode`, [`servel`, `--hostname=${config.hostname}`, `--port=${config.port}`], {
+    signal: config.signal,
+  })
+
+  const url = await new Promise<string>((resolve, reject) => {
+    const id = setTimeout(() => {
+      reject(new Error(`Timeout waiting for server to start after ${config.timeout}ms`))
+    }, config.timeout)
+    let output = ""
+    proc.stdout?.on("data", (chunk) => {
+      output += chunk.toString()
+      const lines = output.split("\n")
+      for (const line of lines) {
+        if (line.startsWith("opencode server listening")) {
+          const match = line.match(/on\s+(https?:\/\/[^\s]+)/)
+          if (!match) {
+            throw new Error(`Failed to parse server url from output: ${line}`)
+          }
+          clearTimeout(id)
+          resolve(match[1])
+          return
+        }
+      }
+    })
+    proc.stderr?.on("data", (chunk) => {
+      output += chunk.toString()
+    })
+    proc.on("exit", (code) => {
+      clearTimeout(id)
+      let msg = `Server exited with code ${code}`
+      if (output.trim()) {
+        msg += `\nServer output: ${output}`
+      }
+      reject(new Error(msg))
+    })
+    proc.on("error", (error) => {
+      clearTimeout(id)
+      reject(error)
+    })
+    if (config.signal) {
+      config.signal.addEventListener("abort", () => {
+        clearTimeout(id)
+        reject(new Error("Aborted"))
+      })
+    }
+  })
 
   return {
     url,

+ 5 - 1
tsconfig.json

@@ -1,5 +1,9 @@
 {
   "$schema": "https://json.schemastore.org/tsconfig",
   "extends": "@tsconfig/bun/tsconfig.json",
-  "compilerOptions": {}
+  "compilerOptions": {
+    "customConditions": [
+      "development"
+    ],
+  }
 }