1212// limitations under the License.
1313// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
1414
15- import { execSync , spawn } from 'child_process' ;
15+ import { execFileSync , execSync , spawn } from 'child_process' ;
1616import { app } from 'electron' ;
1717import log from 'electron-log' ;
1818import fs from 'fs' ;
@@ -111,6 +111,24 @@ export async function getBinaryPath(name?: string): Promise<string> {
111111 }
112112 }
113113
114+ // In dev: prefer system PATH uv (e.g. Homebrew) for speed - reuses existing cache
115+ if ( ! app . isPackaged && name === 'uv' ) {
116+ try {
117+ const whichCmd = process . platform === 'win32' ? 'where.exe' : 'which' ;
118+ const found = execFileSync ( whichCmd , [ name ] , {
119+ encoding : 'utf-8' ,
120+ stdio : [ 'pipe' , 'pipe' , 'pipe' ] ,
121+ } ) . trim ( ) ;
122+ const systemPath = found . split ( / \r ? \n / ) [ 0 ] ?. trim ( ) ;
123+ if ( systemPath && fs . existsSync ( systemPath ) ) {
124+ log . info ( `[DEV] Using system uv from PATH: ${ systemPath } ` ) ;
125+ return systemPath ;
126+ }
127+ } catch {
128+ // Not found on PATH, fall through to .eigent/bin
129+ }
130+ }
131+
114132 const binariesDir = path . join ( os . homedir ( ) , '.eigent' , 'bin' ) ;
115133
116134 // Ensure .eigent/bin directory exists
@@ -943,7 +961,8 @@ export function ensureNpmWrappersForBrowserToolkit(
943961 const eigentBinDir = path . join ( os . homedir ( ) , '.eigent' , 'bin' ) ;
944962 fs . mkdirSync ( eigentBinDir , { recursive : true } ) ;
945963
946- const wrapperVersion = '1' ;
964+ // Store wrapper target so wrappers are recreated when venv path changes (e.g. app upgrade)
965+ const wrapperVersion = `wrapper:${ pythonPath } ` ;
947966 const versionFile = path . join ( eigentBinDir , '.npm_wrapper_version' ) ;
948967 const storedVersion = fs . existsSync ( versionFile )
949968 ? fs . readFileSync ( versionFile , 'utf-8' ) . trim ( )
@@ -958,10 +977,14 @@ export function ensureNpmWrappersForBrowserToolkit(
958977 process . platform === 'win32' ? 'npx.cmd' : 'npx'
959978 ) ;
960979
980+ // Recreate wrappers when: version changed, wrappers missing, or existing shebang points to wrong Python
961981 const needsUpdate =
962982 storedVersion !== wrapperVersion ||
963983 ! fs . existsSync ( npmWrapper ) ||
964- ! fs . existsSync ( npxWrapper ) ;
984+ ! fs . existsSync ( npxWrapper ) ||
985+ ( process . platform !== 'win32' &&
986+ fs . existsSync ( npmWrapper ) &&
987+ ! fs . readFileSync ( npmWrapper , 'utf-8' ) . startsWith ( `#!${ pythonPath } ` ) ) ;
965988
966989 if ( needsUpdate ) {
967990 try {
0 commit comments