diff --git a/cli/scripts/claude_local_launcher.cjs b/cli/scripts/claude_local_launcher.cjs index 6afab097..e4e55647 100644 --- a/cli/scripts/claude_local_launcher.cjs +++ b/cli/scripts/claude_local_launcher.cjs @@ -1,73 +1,7 @@ -const fs = require('fs'); - -// Disable autoupdater (never works really) +// Disable autoupdater process.env.DISABLE_AUTOUPDATER = '1'; -// Helper to write JSON messages to fd 3 -function writeMessage(message) { - try { - fs.writeSync(3, JSON.stringify(message) + '\n'); - } catch (err) { - // fd 3 not available, ignore - } -} - -// Intercept fetch to track thinking state -const originalFetch = global.fetch; -let fetchCounter = 0; - -global.fetch = function(...args) { - const id = ++fetchCounter; - const url = typeof args[0] === 'string' ? args[0] : args[0]?.url || ''; - const method = args[1]?.method || 'GET'; - - // Parse URL for privacy - let hostname = ''; - let path = ''; - try { - const urlObj = new URL(url, 'http://localhost'); - hostname = urlObj.hostname; - path = urlObj.pathname; - } catch (e) { - // If URL parsing fails, use defaults - hostname = 'unknown'; - path = url; - } - - // Send fetch start event - writeMessage({ - type: 'fetch-start', - id, - hostname, - path, - method, - timestamp: Date.now() - }); - - // Execute the original fetch immediately - const fetchPromise = originalFetch(...args); - - // Attach handlers to send fetch end event - const sendEnd = () => { - writeMessage({ - type: 'fetch-end', - id, - timestamp: Date.now() - }); - }; - - // Send end event on both success and failure - fetchPromise.then(sendEnd, sendEnd); - - // Return the original promise unchanged - return fetchPromise; -}; - -// Preserve fetch properties -Object.defineProperty(global.fetch, 'name', { value: 'fetch' }); -Object.defineProperty(global.fetch, 'length', { value: originalFetch.length }); - // Import global Claude Code CLI const { getClaudeCliPath, runClaudeCli } = require('./claude_version_utils.cjs'); -runClaudeCli(getClaudeCliPath()); \ No newline at end of file +runClaudeCli(getClaudeCliPath()); diff --git a/cli/src/claude/claudeLocal.ts b/cli/src/claude/claudeLocal.ts index f2c9fc03..0519c768 100644 --- a/cli/src/claude/claudeLocal.ts +++ b/cli/src/claude/claudeLocal.ts @@ -1,6 +1,5 @@ import { spawn } from "node:child_process"; import { resolve, join } from "node:path"; -import { createInterface } from "node:readline"; import { mkdirSync, existsSync } from "node:fs"; import { randomUUID } from "node:crypto"; import { logger } from "@/ui/logger"; @@ -20,7 +19,6 @@ export async function claudeLocal(opts: { mcpServers?: Record, path: string, onSessionFound: (id: string) => void, - onThinkingChange?: (thinking: boolean) => void, claudeEnvVars?: Record, claudeArgs?: string[] allowedTools?: string[] @@ -51,19 +49,6 @@ export async function claudeLocal(opts: { opts.onSessionFound(startFrom!); } - // Thinking state - let thinking = false; - let stopThinkingTimeout: NodeJS.Timeout | null = null; - const updateThinking = (newThinking: boolean) => { - if (thinking !== newThinking) { - thinking = newThinking; - logger.debug(`[ClaudeLocal] Thinking state changed to: ${thinking}`); - if (opts.onThinkingChange) { - opts.onThinkingChange(thinking); - } - } - }; - // Spawn the process try { // Start the interactive process @@ -100,7 +85,6 @@ export async function claudeLocal(opts: { // Prepare environment variables // Note: Local mode uses global Claude installation with --session-id flag - // Launcher only intercepts fetch for thinking state tracking const env = { ...process.env, ...opts.claudeEnvVars @@ -110,79 +94,11 @@ export async function claudeLocal(opts: { logger.debug(`[ClaudeLocal] Args: ${JSON.stringify(args)}`); const child = spawn(process.execPath, [claudeCliPath, ...args], { - stdio: ['inherit', 'inherit', 'inherit', 'pipe'], + stdio: ['inherit', 'inherit', 'inherit'], signal: opts.abort, cwd: opts.path, env: withBunRuntimeEnv(env), }); - - // Listen to the custom fd (fd 3) for thinking state tracking - if (child.stdio[3]) { - const rl = createInterface({ - input: child.stdio[3] as any, - crlfDelay: Infinity - }); - - // Track active fetches for thinking state - const activeFetches = new Map(); - - rl.on('line', (line) => { - try { - const message = JSON.parse(line); - - switch (message.type) { - case 'fetch-start': - activeFetches.set(message.id, { - hostname: message.hostname, - path: message.path, - startTime: message.timestamp - }); - - // Clear any pending stop timeout - if (stopThinkingTimeout) { - clearTimeout(stopThinkingTimeout); - stopThinkingTimeout = null; - } - - // Start thinking - updateThinking(true); - break; - - case 'fetch-end': - activeFetches.delete(message.id); - - // Stop thinking when no active fetches - if (activeFetches.size === 0 && thinking && !stopThinkingTimeout) { - stopThinkingTimeout = setTimeout(() => { - if (activeFetches.size === 0) { - updateThinking(false); - } - stopThinkingTimeout = null; - }, 500); // Small delay to avoid flickering - } - break; - - default: - logger.debug(`[ClaudeLocal] Unknown message type: ${message.type}`); - } - } catch (e) { - // Not JSON, ignore (could be other output) - logger.debug(`[ClaudeLocal] Non-JSON line from fd3: ${line}`); - } - }); - - rl.on('error', (err) => { - console.error('Error reading from fd 3:', err); - }); - - // Cleanup on child exit - child.on('exit', () => { - if (stopThinkingTimeout) { - clearTimeout(stopThinkingTimeout); - } - updateThinking(false); - }); - } child.on('error', (error) => { // Ignore }); @@ -199,11 +115,6 @@ export async function claudeLocal(opts: { }); } finally { process.stdin.resume(); - if (stopThinkingTimeout) { - clearTimeout(stopThinkingTimeout); - stopThinkingTimeout = null; - } - updateThinking(false); } return effectiveSessionId; diff --git a/cli/src/claude/claudeLocalLauncher.ts b/cli/src/claude/claudeLocalLauncher.ts index f2b1d958..f8a656f4 100644 --- a/cli/src/claude/claudeLocalLauncher.ts +++ b/cli/src/claude/claudeLocalLauncher.ts @@ -95,7 +95,6 @@ export async function claudeLocalLauncher(session: Session): Promise<'switch' | path: session.path, sessionId: session.sessionId, onSessionFound: handleSessionStart, - onThinkingChange: session.onThinkingChange, abort: processAbortController.signal, claudeEnvVars: session.claudeEnvVars, claudeArgs: session.claudeArgs, @@ -139,4 +138,4 @@ export async function claudeLocalLauncher(session: Session): Promise<'switch' | // Return return exitReason || 'exit'; -} \ No newline at end of file +}