diff --git a/v2/sidecar/agent-runner-deno.ts b/v2/sidecar/agent-runner-deno.ts index 15f9542..ceb21c9 100644 --- a/v2/sidecar/agent-runner-deno.ts +++ b/v2/sidecar/agent-runner-deno.ts @@ -71,10 +71,16 @@ async function handleQuery(msg: QueryMessage) { } } + if (!claudePath) { + send({ type: "agent_error", sessionId, message: "Claude CLI not found. Install Claude Code first." }); + return; + } + try { const q = query({ prompt, options: { + pathToClaudeCodeExecutable: claudePath, abortController: controller, cwd: cwd || Deno.cwd(), env: cleanEnv, @@ -144,6 +150,32 @@ function handleStop(msg: StopMessage) { controller.abort(); } +function findClaudeCli(): string | undefined { + const home = Deno.env.get("HOME") ?? Deno.env.get("USERPROFILE") ?? ""; + const candidates = [ + `${home}/.local/bin/claude`, + `${home}/.claude/local/claude`, + "/usr/local/bin/claude", + "/usr/bin/claude", + ]; + for (const p of candidates) { + try { Deno.statSync(p); return p; } catch { /* not found */ } + } + try { + const proc = new Deno.Command("which", { args: ["claude"], stdout: "piped", stderr: "null" }); + const out = new TextDecoder().decode(proc.outputSync().stdout).trim(); + if (out) return out.split("\n")[0]; + } catch { /* not found */ } + return undefined; +} + +const claudePath = findClaudeCli(); +if (claudePath) { + log(`Found Claude CLI at ${claudePath}`); +} else { + log("WARNING: Claude CLI not found — agent sessions will fail"); +} + // Main: read NDJSON from stdin log("Sidecar started (Deno)"); send({ type: "ready" }); diff --git a/v2/sidecar/agent-runner.ts b/v2/sidecar/agent-runner.ts index 9589396..1d8e318 100644 --- a/v2/sidecar/agent-runner.ts +++ b/v2/sidecar/agent-runner.ts @@ -4,6 +4,10 @@ import { stdin, stdout, stderr } from 'process'; import { createInterface } from 'readline'; +import { execSync } from 'child_process'; +import { existsSync } from 'fs'; +import { join } from 'path'; +import { homedir } from 'os'; import { query, type Query } from '@anthropic-ai/claude-agent-sdk'; const rl = createInterface({ input: stdin }); @@ -81,9 +85,15 @@ async function handleQuery(msg: QueryMessage) { } try { + if (!claudePath) { + send({ type: 'agent_error', sessionId, message: 'Claude CLI not found. Install Claude Code first.' }); + return; + } + const q = query({ prompt, options: { + pathToClaudeCodeExecutable: claudePath, abortController: controller, cwd: cwd || process.cwd(), env: cleanEnv, @@ -155,5 +165,31 @@ function handleStop(msg: StopMessage) { session.controller.abort(); } +function findClaudeCli(): string | undefined { + // Check common locations + const candidates = [ + join(homedir(), '.local', 'bin', 'claude'), + join(homedir(), '.claude', 'local', 'claude'), + '/usr/local/bin/claude', + '/usr/bin/claude', + ]; + for (const p of candidates) { + if (existsSync(p)) return p; + } + // Fall back to which/where + try { + return execSync('which claude 2>/dev/null || where claude 2>nul', { encoding: 'utf-8' }).trim().split('\n')[0]; + } catch { + return undefined; + } +} + +const claudePath = findClaudeCli(); +if (claudePath) { + log(`Found Claude CLI at ${claudePath}`); +} else { + log('WARNING: Claude CLI not found — agent sessions will fail'); +} + log('Sidecar started'); send({ type: 'ready' });