fix(title-generator): add production path resolution for backend source (#1778)
* fix(title-generator): add production path resolution for backend source getAutoBuildSourcePath() only checked development-mode relative paths, causing AI title generation to silently fail in packaged builds. Added app.isPackaged check with userData override and process.resourcesPath fallbacks, matching the pattern already used by terminal-name-generator and other services. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(path-resolution): consolidate duplicated backend path logic into shared resolver Both title-generator and terminal-name-generator duplicated the production path resolution logic (userData override, resourcesPath fallback, dev paths) that already exists in getEffectiveSourcePath() from updater/path-resolver.ts. Replaced inline implementations with the shared utility, matching the pattern used by insights/config.ts. Also removed unused imports (app, fileURLToPath, __dirname) that were only needed for the old inline path resolution. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,16 +1,11 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import { spawn } from 'child_process';
|
||||
import { app } from 'electron';
|
||||
|
||||
// ESM-compatible __dirname
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
import { EventEmitter } from 'events';
|
||||
import { detectRateLimit, createSDKRateLimitInfo, getBestAvailableProfileEnv } from './rate-limit-detector';
|
||||
import { parsePythonCommand } from './python-detector';
|
||||
import { pythonEnvManager } from './python-env-manager';
|
||||
import { getEffectiveSourcePath } from './updater/path-resolver';
|
||||
|
||||
/**
|
||||
* Debug logging - only logs when DEBUG=true or in development mode
|
||||
@@ -51,35 +46,16 @@ export class TerminalNameGenerator extends EventEmitter {
|
||||
return this.autoBuildSourcePath;
|
||||
}
|
||||
|
||||
// In packaged app, check userData override first (consistent with path-resolver.ts)
|
||||
if (app.isPackaged) {
|
||||
// Check for user-updated backend source first (takes priority over bundled)
|
||||
const overridePath = path.join(app.getPath('userData'), 'backend-source');
|
||||
if (existsSync(overridePath) && existsSync(path.join(overridePath, 'runners', 'spec_runner.py'))) {
|
||||
debug('Using user-updated backend from userData:', overridePath);
|
||||
return overridePath;
|
||||
}
|
||||
// Fall back to bundled backend in resources
|
||||
const resourcesPath = path.join(process.resourcesPath, 'backend');
|
||||
if (existsSync(resourcesPath) && existsSync(path.join(resourcesPath, 'runners', 'spec_runner.py'))) {
|
||||
debug('Using bundled backend from resources:', resourcesPath);
|
||||
return resourcesPath;
|
||||
}
|
||||
// Use shared path resolver which handles:
|
||||
// 1. User settings (autoBuildPath)
|
||||
// 2. userData override (backend-source) for user-updated backend
|
||||
// 3. Bundled backend (process.resourcesPath/backend)
|
||||
// 4. Development paths
|
||||
const effectivePath = getEffectiveSourcePath();
|
||||
if (existsSync(effectivePath) && existsSync(path.join(effectivePath, 'runners', 'spec_runner.py'))) {
|
||||
return effectivePath;
|
||||
}
|
||||
|
||||
// Development mode paths
|
||||
const possiblePaths = [
|
||||
// Apps structure: from out/main -> apps/backend
|
||||
path.resolve(__dirname, '..', '..', '..', 'backend'),
|
||||
path.resolve(app.getAppPath(), '..', 'backend'),
|
||||
path.resolve(process.cwd(), 'apps', 'backend')
|
||||
];
|
||||
|
||||
for (const p of possiblePaths) {
|
||||
if (existsSync(p) && existsSync(path.join(p, 'runners', 'spec_runner.py'))) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import { spawn } from 'child_process';
|
||||
import { app } from 'electron';
|
||||
|
||||
// ESM-compatible __dirname
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
import { EventEmitter } from 'events';
|
||||
import { detectRateLimit, createSDKRateLimitInfo, getBestAvailableProfileEnv } from './rate-limit-detector';
|
||||
import { parsePythonCommand, getValidatedPythonPath } from './python-detector';
|
||||
import { getConfiguredPythonPath } from './python-env-manager';
|
||||
import { getAPIProfileEnv } from './services/profile';
|
||||
import { getOAuthModeClearVars } from './agent/env-utils';
|
||||
import { getEffectiveSourcePath } from './updater/path-resolver';
|
||||
|
||||
/**
|
||||
* Debug logging - only logs when DEBUG=true or in development mode
|
||||
@@ -67,18 +62,16 @@ export class TitleGenerator extends EventEmitter {
|
||||
return this.autoBuildSourcePath;
|
||||
}
|
||||
|
||||
const possiblePaths = [
|
||||
// Apps structure: from out/main -> apps/backend
|
||||
path.resolve(__dirname, '..', '..', '..', 'backend'),
|
||||
path.resolve(app.getAppPath(), '..', 'backend'),
|
||||
path.resolve(process.cwd(), 'apps', 'backend')
|
||||
];
|
||||
|
||||
for (const p of possiblePaths) {
|
||||
if (existsSync(p) && existsSync(path.join(p, 'runners', 'spec_runner.py'))) {
|
||||
return p;
|
||||
}
|
||||
// Use shared path resolver which handles:
|
||||
// 1. User settings (autoBuildPath)
|
||||
// 2. userData override (backend-source) for user-updated backend
|
||||
// 3. Bundled backend (process.resourcesPath/backend)
|
||||
// 4. Development paths
|
||||
const effectivePath = getEffectiveSourcePath();
|
||||
if (existsSync(effectivePath) && existsSync(path.join(effectivePath, 'runners', 'spec_runner.py'))) {
|
||||
return effectivePath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user