Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions plugins/opencode/scripts/lib/opencode-server.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { spawn } from "node:child_process";

const IS_WINDOWS = process.platform === "win32";
const DEFAULT_PORT = 4096;
const DEFAULT_HOST = "127.0.0.1";
const SERVER_START_TIMEOUT = 30_000;
Expand Down Expand Up @@ -43,10 +44,12 @@ export async function ensureServer(opts = {}) {
}

// Start the server
// Windows npm shims are .cmd/.ps1; spawn() only resolves those via a shell.
const proc = spawn("opencode", ["serve", "--port", String(port)], {
stdio: ["ignore", "pipe", "pipe"],
detached: true,
cwd: opts.cwd,
shell: IS_WINDOWS,
});
proc.unref();

Expand Down
16 changes: 14 additions & 2 deletions plugins/opencode/scripts/lib/process.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,22 @@

import { spawn } from "node:child_process";

const IS_WINDOWS = process.platform === "win32";

/**
* Resolve the full path to the `opencode` binary.
* @returns {Promise<string|null>}
*/
export async function resolveOpencodeBinary() {
return new Promise((resolve) => {
const proc = spawn("which", ["opencode"], { stdio: ["ignore", "pipe", "ignore"] });
// `which` isn't a native Windows binary; `where` is the equivalent.
const proc = spawn(IS_WINDOWS ? "where" : "which", ["opencode"], {
stdio: ["ignore", "pipe", "ignore"],
});
let out = "";
proc.stdout.on("data", (d) => (out += d));
proc.on("close", (code) => resolve(code === 0 ? out.trim() : null));
proc.on("close", (code) => resolve(code === 0 ? out.trim().split(/\r?\n/)[0] : null));
proc.on("error", () => resolve(null));
});
}

Expand All @@ -30,12 +36,15 @@ export async function isOpencodeInstalled() {
*/
export async function getOpencodeVersion() {
return new Promise((resolve) => {
// Windows npm shims are .cmd/.ps1; spawn() only resolves those via a shell.
const proc = spawn("opencode", ["--version"], {
stdio: ["ignore", "pipe", "ignore"],
shell: IS_WINDOWS,
});
let out = "";
proc.stdout.on("data", (d) => (out += d));
proc.on("close", (code) => resolve(code === 0 ? out.trim() : null));
proc.on("error", () => resolve(null));
});
}

Expand All @@ -52,12 +61,14 @@ export function runCommand(cmd, args, opts = {}) {
stdio: ["ignore", "pipe", "pipe"],
cwd: opts.cwd,
env: { ...process.env, ...opts.env },
shell: IS_WINDOWS,
});
let stdout = "";
let stderr = "";
proc.stdout.on("data", (d) => (stdout += d));
proc.stderr.on("data", (d) => (stderr += d));
proc.on("close", (exitCode) => resolve({ stdout, stderr, exitCode: exitCode ?? 1 }));
proc.on("error", (err) => resolve({ stdout: "", stderr: String(err), exitCode: 1 }));
});
}

Expand All @@ -74,6 +85,7 @@ export function spawnDetached(cmd, args, opts = {}) {
detached: true,
cwd: opts.cwd,
env: { ...process.env, ...opts.env },
shell: IS_WINDOWS,
});
child.unref();
return child;
Expand Down