diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 4fdab9c3..ef847bd5 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -114,7 +114,7 @@ "@vitejs/plugin-react": "^5.1.2", "autoprefixer": "^10.4.22", "cross-env": "^10.1.0", - "electron": "^39.2.7", + "electron": "39.2.7", "electron-builder": "^26.0.12", "electron-vite": "^5.0.0", "eslint": "^9.39.1", diff --git a/apps/frontend/src/main/changelog/generator.ts b/apps/frontend/src/main/changelog/generator.ts index c71af9c3..6fa75c06 100644 --- a/apps/frontend/src/main/changelog/generator.ts +++ b/apps/frontend/src/main/changelog/generator.ts @@ -13,6 +13,7 @@ import { extractChangelog } from './parser'; import { getCommits, getBranchDiffCommits } from './git-integration'; import { detectRateLimit, createSDKRateLimitInfo, getProfileEnv } from '../rate-limit-detector'; import { parsePythonCommand } from '../python-detector'; +import { getAugmentedEnv } from '../env-utils'; /** * Core changelog generation logic @@ -246,21 +247,9 @@ export class ChangelogGenerator extends EventEmitter { const homeDir = os.homedir(); const isWindows = process.platform === 'win32'; - // Build PATH with platform-appropriate separator and locations - const pathAdditions = isWindows - ? [ - path.join(homeDir, 'AppData', 'Local', 'Programs', 'claude'), - path.join(homeDir, 'AppData', 'Roaming', 'npm'), - path.join(homeDir, '.local', 'bin'), - 'C:\\Program Files\\Claude', - 'C:\\Program Files (x86)\\Claude' - ] - : [ - '/usr/local/bin', - '/opt/homebrew/bin', - path.join(homeDir, '.local', 'bin'), - path.join(homeDir, 'bin') - ]; + // Use getAugmentedEnv() to ensure common tool paths are available + // even when app is launched from Finder/Dock + const augmentedEnv = getAugmentedEnv(); // Get active Claude profile environment (OAuth token preferred, falls back to CLAUDE_CONFIG_DIR) const profileEnv = getProfileEnv(); @@ -271,15 +260,13 @@ export class ChangelogGenerator extends EventEmitter { }); const spawnEnv: Record = { - ...process.env as Record, + ...augmentedEnv, ...this.autoBuildEnv, ...profileEnv, // Include active Claude profile config // Ensure critical env vars are set for claude CLI // Use USERPROFILE on Windows, HOME on Unix ...(isWindows ? { USERPROFILE: homeDir } : { HOME: homeDir }), USER: process.env.USER || process.env.USERNAME || 'user', - // Add common binary locations to PATH for claude CLI - PATH: [process.env.PATH || '', ...pathAdditions].filter(Boolean).join(path.delimiter), PYTHONUNBUFFERED: '1', PYTHONIOENCODING: 'utf-8', PYTHONUTF8: '1' diff --git a/apps/frontend/src/main/changelog/version-suggester.ts b/apps/frontend/src/main/changelog/version-suggester.ts index 4869fe41..027df15f 100644 --- a/apps/frontend/src/main/changelog/version-suggester.ts +++ b/apps/frontend/src/main/changelog/version-suggester.ts @@ -4,6 +4,7 @@ import * as os from 'os'; import type { GitCommit } from '../../shared/types'; import { getProfileEnv } from '../rate-limit-detector'; import { parsePythonCommand } from '../python-detector'; +import { getAugmentedEnv } from '../env-utils'; interface VersionSuggestion { version: string; @@ -215,31 +216,19 @@ except Exception as e: const homeDir = os.homedir(); const isWindows = process.platform === 'win32'; - // Build PATH with platform-appropriate separator and locations - const pathAdditions = isWindows - ? [ - path.join(homeDir, 'AppData', 'Local', 'Programs', 'claude'), - path.join(homeDir, 'AppData', 'Roaming', 'npm'), - path.join(homeDir, '.local', 'bin'), - 'C:\\Program Files\\Claude', - 'C:\\Program Files (x86)\\Claude' - ] - : [ - '/usr/local/bin', - '/opt/homebrew/bin', - path.join(homeDir, '.local', 'bin'), - path.join(homeDir, 'bin') - ]; + // Use getAugmentedEnv() to ensure common tool paths are available + // even when app is launched from Finder/Dock + const augmentedEnv = getAugmentedEnv(); // Get active Claude profile environment const profileEnv = getProfileEnv(); const spawnEnv: Record = { - ...process.env as Record, + ...augmentedEnv, ...profileEnv, + // Ensure critical env vars are set for claude CLI ...(isWindows ? { USERPROFILE: homeDir } : { HOME: homeDir }), USER: process.env.USER || process.env.USERNAME || 'user', - PATH: [process.env.PATH || '', ...pathAdditions].filter(Boolean).join(path.delimiter), PYTHONUNBUFFERED: '1', PYTHONIOENCODING: 'utf-8', PYTHONUTF8: '1' diff --git a/apps/frontend/src/main/insights/config.ts b/apps/frontend/src/main/insights/config.ts index 0ca1609c..3ef00f30 100644 --- a/apps/frontend/src/main/insights/config.ts +++ b/apps/frontend/src/main/insights/config.ts @@ -3,7 +3,8 @@ import { existsSync, readFileSync } from 'fs'; import { app } from 'electron'; import { getProfileEnv } from '../rate-limit-detector'; import { getValidatedPythonPath } from '../python-detector'; -import { getConfiguredPythonPath } from '../python-env-manager'; +import { getConfiguredPythonPath, pythonEnvManager } from '../python-env-manager'; +import { getAugmentedEnv } from '../env-utils'; /** * Configuration manager for insights service @@ -107,9 +108,15 @@ export class InsightsConfig { getProcessEnv(): Record { const autoBuildEnv = this.loadAutoBuildEnv(); const profileEnv = getProfileEnv(); + // Get Python environment (PYTHONPATH for bundled packages like python-dotenv) + const pythonEnv = pythonEnvManager.getPythonEnv(); + // Use getAugmentedEnv() to ensure common tool paths (claude, dotnet, etc.) + // are available even when app is launched from Finder/Dock + const augmentedEnv = getAugmentedEnv(); return { - ...process.env as Record, + ...augmentedEnv, + ...pythonEnv, // Include PYTHONPATH for bundled site-packages ...autoBuildEnv, ...profileEnv, PYTHONUNBUFFERED: '1', diff --git a/apps/frontend/src/main/insights/insights-executor.ts b/apps/frontend/src/main/insights/insights-executor.ts index d5565620..4cae6e4a 100644 --- a/apps/frontend/src/main/insights/insights-executor.ts +++ b/apps/frontend/src/main/insights/insights-executor.ts @@ -130,6 +130,7 @@ export class InsightsExecutor extends EventEmitter { let suggestedTask: InsightsChatMessage['suggestedTask'] | undefined; const toolsUsed: InsightsToolUsage[] = []; let allInsightsOutput = ''; + let stderrOutput = ''; proc.stdout?.on('data', (data: Buffer) => { const text = data.toString(); @@ -159,8 +160,9 @@ export class InsightsExecutor extends EventEmitter { proc.stderr?.on('data', (data: Buffer) => { const text = data.toString(); - // Collect stderr for rate limit detection too + // Collect stderr for rate limit detection and error reporting allInsightsOutput = (allInsightsOutput + text).slice(-10000); + stderrOutput = (stderrOutput + text).slice(-2000); console.error('[Insights]', text); }); @@ -196,7 +198,11 @@ export class InsightsExecutor extends EventEmitter { toolsUsed }); } else { - const error = `Process exited with code ${code}`; + // Include stderr output in error message for debugging + const stderrSummary = stderrOutput.trim() + ? `\n\nError output:\n${stderrOutput.slice(-500)}` + : ''; + const error = `Process exited with code ${code}${stderrSummary}`; this.emit('stream-chunk', projectId, { type: 'error', error