feat(v2): auto-detect Claude CLI path and pass to SDK via pathToClaudeCodeExecutable
Both sidecar runners (agent-runner.ts and agent-runner-deno.ts) now include findClaudeCli() which checks common paths (~/.local/bin/claude, ~/.claude/local/claude, /usr/local/bin/claude, /usr/bin/claude) and falls back to `which claude`. The resolved path is passed to the SDK query() options as pathToClaudeCodeExecutable. If the CLI is not found, an agent_error is emitted immediately instead of a cryptic SDK failure.
This commit is contained in:
parent
14b62da729
commit
d35b3dc7fc
2 changed files with 68 additions and 0 deletions
|
|
@ -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" });
|
||||
|
|
|
|||
|
|
@ -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' });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue