Improve cmux omo error when opencode is not installed (#2230)
* Improve cmux omo error when opencode is not installed On a fresh computer without opencode, cmux omo would fail with the unhelpful "Failed to launch opencode: No such file or directory". Now checks for opencode before doing setup work and shows install instructions: npm install -g opencode-ai * Show npm install progress and improve first-run experience On first run, npm install oh-my-opencode can take 30+ seconds. Previously piped to /dev/null, making it look like cmux omo hung. Now pipes npm output directly to stderr so users see progress. Also improves the message: "this may take a minute on first run". * Move opencode check before plugin setup to fail fast --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
parent
30cb3718fc
commit
6e5903e4e9
1 changed files with 25 additions and 26 deletions
|
|
@ -9779,30 +9779,14 @@ struct CMUXCLI {
|
|||
} else {
|
||||
throw CLIError(message: "Neither bun nor npm found in PATH. Install oh-my-opencode manually: bunx oh-my-opencode install")
|
||||
}
|
||||
let stdoutPipe = Pipe()
|
||||
let stderrPipe = Pipe()
|
||||
process.standardOutput = stdoutPipe
|
||||
process.standardError = stderrPipe
|
||||
FileHandle.standardError.write("Installing oh-my-opencode plugin...\n".data(using: .utf8)!)
|
||||
// Show install output directly so the user sees progress (npm can take 30s+)
|
||||
process.standardOutput = FileHandle.standardError
|
||||
process.standardError = FileHandle.standardError
|
||||
FileHandle.standardError.write("Installing oh-my-opencode plugin (this may take a minute on first run)...\n".data(using: .utf8)!)
|
||||
try process.run()
|
||||
// Drain pipes concurrently to prevent deadlock from full buffers
|
||||
var stderrData = Data()
|
||||
let drainGroup = DispatchGroup()
|
||||
drainGroup.enter()
|
||||
DispatchQueue.global().async {
|
||||
stderrData = stderrPipe.fileHandleForReading.readDataToEndOfFile()
|
||||
drainGroup.leave()
|
||||
}
|
||||
drainGroup.enter()
|
||||
DispatchQueue.global().async {
|
||||
_ = stdoutPipe.fileHandleForReading.readDataToEndOfFile()
|
||||
drainGroup.leave()
|
||||
}
|
||||
drainGroup.wait()
|
||||
process.waitUntilExit()
|
||||
if process.terminationStatus != 0 {
|
||||
let errText = String(data: stderrData, encoding: .utf8) ?? ""
|
||||
throw CLIError(message: "Failed to install oh-my-opencode: \(errText)")
|
||||
throw CLIError(message: "Failed to install oh-my-opencode. Try manually: npm install -g oh-my-opencode")
|
||||
}
|
||||
FileHandle.standardError.write("oh-my-opencode plugin installed\n".data(using: .utf8)!)
|
||||
// Re-create symlink if we installed into user dir
|
||||
|
|
@ -9899,9 +9883,6 @@ struct CMUXCLI {
|
|||
socketPath: String,
|
||||
explicitPassword: String?
|
||||
) throws {
|
||||
// Ensure oh-my-opencode plugin is registered and installed
|
||||
try omoEnsurePlugin()
|
||||
|
||||
let processEnvironment = ProcessInfo.processInfo.environment
|
||||
var launcherEnvironment = processEnvironment
|
||||
launcherEnvironment["CMUX_SOCKET_PATH"] = socketPath
|
||||
|
|
@ -9910,13 +9891,31 @@ struct CMUXCLI {
|
|||
!explicitPassword.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
launcherEnvironment["CMUX_SOCKET_PASSWORD"] = explicitPassword
|
||||
}
|
||||
|
||||
// Check for opencode before doing expensive plugin setup
|
||||
let openCodeExecutablePath = resolveOpenCodeExecutable(searchPath: launcherEnvironment["PATH"])
|
||||
if openCodeExecutablePath == nil {
|
||||
let checkProcess = Process()
|
||||
checkProcess.executableURL = URL(fileURLWithPath: "/usr/bin/which")
|
||||
checkProcess.arguments = ["opencode"]
|
||||
checkProcess.standardOutput = Pipe()
|
||||
checkProcess.standardError = Pipe()
|
||||
try? checkProcess.run()
|
||||
checkProcess.waitUntilExit()
|
||||
if checkProcess.terminationStatus != 0 {
|
||||
throw CLIError(message: "opencode is not installed. Install it first:\n npm install -g opencode-ai\n # or\n bun install -g opencode-ai\n\nThen run: cmux omo")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure oh-my-opencode plugin is registered and installed
|
||||
try omoEnsurePlugin()
|
||||
|
||||
let shimDirectory = try createOMOShimDirectory()
|
||||
let executablePath = resolvedExecutableURL()?.path ?? (args.first ?? "cmux")
|
||||
let focusedContext = tmuxCompatFocusedContext(
|
||||
processEnvironment: launcherEnvironment,
|
||||
explicitPassword: explicitPassword
|
||||
)
|
||||
let openCodeExecutablePath = resolveOpenCodeExecutable(searchPath: launcherEnvironment["PATH"])
|
||||
configureOMOEnvironment(
|
||||
processEnvironment: launcherEnvironment,
|
||||
shimDirectory: shimDirectory,
|
||||
|
|
@ -9949,7 +9948,7 @@ struct CMUXCLI {
|
|||
execvp("opencode", &argv)
|
||||
}
|
||||
let code = errno
|
||||
throw CLIError(message: "Failed to launch opencode: \(String(cString: strerror(code)))")
|
||||
throw CLIError(message: "Failed to launch opencode: \(String(cString: strerror(code)))\n\nIs opencode installed? Install with:\n npm install -g opencode-ai")
|
||||
}
|
||||
|
||||
private func runClaudeTeamsTmuxCompat(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue