mirror of https://github.com/garrytan/gstack.git
fix: resolve claude binary path for daemon-spawned agent
The browse server runs as a daemon and may not inherit the user's shell PATH. Add findClaudeBin() that checks ~/.local/bin/claude (standard install location), which claude, and common system paths. Shows a clear error in the sidebar chat if claude CLI is not found. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e840a8ca70
commit
c795e498c1
|
|
@ -141,6 +141,27 @@ function findBrowseBin(): string {
|
||||||
|
|
||||||
const BROWSE_BIN = findBrowseBin();
|
const BROWSE_BIN = findBrowseBin();
|
||||||
|
|
||||||
|
function findClaudeBin(): string | null {
|
||||||
|
const candidates = [
|
||||||
|
path.join(process.env.HOME || '', '.local', 'bin', 'claude'),
|
||||||
|
path.join(process.env.HOME || '', '.local', 'share', 'claude', 'versions', 'latest'),
|
||||||
|
'/usr/local/bin/claude',
|
||||||
|
'/opt/homebrew/bin/claude',
|
||||||
|
];
|
||||||
|
// Also check if 'claude' is in current PATH (works when spawned from shell)
|
||||||
|
try {
|
||||||
|
const proc = Bun.spawnSync(['which', 'claude'], { stdout: 'pipe', stderr: 'pipe', timeout: 2000 });
|
||||||
|
if (proc.exitCode === 0) {
|
||||||
|
const p = proc.stdout.toString().trim();
|
||||||
|
if (p) candidates.unshift(p);
|
||||||
|
}
|
||||||
|
} catch {}
|
||||||
|
for (const c of candidates) {
|
||||||
|
try { if (fs.existsSync(c)) return c; } catch {}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
function shortenPath(str: string): string {
|
function shortenPath(str: string): string {
|
||||||
return str
|
return str
|
||||||
.replace(new RegExp(BROWSE_BIN.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), '$B')
|
.replace(new RegExp(BROWSE_BIN.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), '$B')
|
||||||
|
|
@ -362,9 +383,19 @@ function spawnClaude(userMessage: string): void {
|
||||||
|
|
||||||
addChatEntry({ ts: new Date().toISOString(), role: 'agent', type: 'agent_start' });
|
addChatEntry({ ts: new Date().toISOString(), role: 'agent', type: 'agent_start' });
|
||||||
|
|
||||||
const proc = spawn('claude', args, {
|
// Resolve claude binary — daemon process may not have user's PATH
|
||||||
|
const claudeBin = findClaudeBin();
|
||||||
|
if (!claudeBin) {
|
||||||
|
addChatEntry({ ts: new Date().toISOString(), role: 'agent', type: 'agent_error', error: 'Claude CLI not found. Install: npm install -g @anthropic-ai/claude-code' });
|
||||||
|
agentStatus = 'idle';
|
||||||
|
agentStartTime = null;
|
||||||
|
currentMessage = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proc = spawn(claudeBin, args, {
|
||||||
stdio: ['pipe', 'pipe', 'pipe'],
|
stdio: ['pipe', 'pipe', 'pipe'],
|
||||||
cwd: sidebarSession?.worktreePath || process.cwd(),
|
cwd: (sidebarSession as any)?.worktreePath || process.cwd(),
|
||||||
env: { ...process.env, BROWSE_STATE_FILE: config.stateFile },
|
env: { ...process.env, BROWSE_STATE_FILE: config.stateFile },
|
||||||
} as any);
|
} as any);
|
||||||
proc.stdin?.end();
|
proc.stdin?.end();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue