|
1 | | -import { spawnSync } from "node:child_process"; |
| 1 | +import { spawn } from "node:child_process"; |
2 | 2 | import { existsSync } from "node:fs"; |
3 | 3 | import path from "node:path"; |
4 | 4 | import { buildContextPackage } from "../../core/context-builder.js"; |
@@ -57,7 +57,7 @@ export async function launchOpenCodeWithSidecar(options: OpenCodeLauncherOptions |
57 | 57 | if (!opencode.ok) return { repo, steps, command, launched: false, exitCode: 1 }; |
58 | 58 | if (options.dryRun) return { repo, steps, command, launched: false, exitCode: 0 }; |
59 | 59 | options.onPreflight?.({ repo, steps, command }); |
60 | | - const result = spawnOpenCodeTui(repo); |
| 60 | + const result = await spawnOpenCodeTui(repo); |
61 | 61 | return { repo, steps, command, launched: true, exitCode: typeof result.status === "number" ? result.status : result.error ? 1 : null }; |
62 | 62 | } |
63 | 63 |
|
@@ -105,7 +105,7 @@ export async function launchOpenCodeWithSidecar(options: OpenCodeLauncherOptions |
105 | 105 | } |
106 | 106 |
|
107 | 107 | options.onPreflight?.({ repo, steps, command }); |
108 | | - const result = spawnOpenCodeTui(repo); |
| 108 | + const result = await spawnOpenCodeTui(repo); |
109 | 109 | return { repo, steps, command, launched: true, exitCode: typeof result.status === "number" ? result.status : result.error ? 1 : null }; |
110 | 110 | } |
111 | 111 |
|
@@ -162,10 +162,29 @@ function checkGitRepo(repo: string): { ok: boolean; error: string } { |
162 | 162 | } |
163 | 163 | } |
164 | 164 |
|
165 | | -function spawnOpenCodeTui(repo: string): ReturnType<typeof spawnSync> { |
166 | | - const result = spawnSync("opencode", [repo], { cwd: repo, stdio: "inherit", shell: false }); |
| 165 | +async function spawnOpenCodeTui(repo: string): Promise<{ status: number | null; error?: Error }> { |
| 166 | + const result = await spawnOpenCodeProcess("opencode", [repo], repo); |
167 | 167 | if (!shouldTryWindowsCmdFallback(result.error)) return result; |
168 | | - return spawnSync("cmd.exe", ["/d", "/s", "/c", `opencode.cmd ${windowsCmdQuote(repo)}`], { cwd: repo, stdio: "inherit", shell: false }); |
| 168 | + return spawnOpenCodeProcess("cmd.exe", ["/d", "/s", "/c", `opencode.cmd ${windowsCmdQuote(repo)}`], repo); |
| 169 | +} |
| 170 | + |
| 171 | +function spawnOpenCodeProcess(command: string, args: string[], cwd: string): Promise<{ status: number | null; error?: Error }> { |
| 172 | + return new Promise((resolve) => { |
| 173 | + const child = spawn(command, args, { cwd, stdio: "inherit", shell: false }); |
| 174 | + let settled = false; |
| 175 | + |
| 176 | + child.once("error", (error) => { |
| 177 | + if (settled) return; |
| 178 | + settled = true; |
| 179 | + resolve({ status: null, error }); |
| 180 | + }); |
| 181 | + |
| 182 | + child.once("close", (code) => { |
| 183 | + if (settled) return; |
| 184 | + settled = true; |
| 185 | + resolve({ status: code }); |
| 186 | + }); |
| 187 | + }); |
169 | 188 | } |
170 | 189 |
|
171 | 190 | function shouldTryWindowsCmdFallback(error: Error | undefined): boolean { |
|
0 commit comments