eigent/scripts/fix-venv-paths.js
Tong Chen 38f5fbc8cc
Some checks are pending
CodeQL Advanced / Analyze (actions) (push) Waiting to run
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
CodeQL Advanced / Analyze (python) (push) Waiting to run
Pre-commit / pre-commit (push) Waiting to run
Test / Run Python Tests (push) Waiting to run
Fix win 0.0.82 prebuilt issue (#1109)
Co-authored-by: Wendong-Fan <133094783+Wendong-Fan@users.noreply.github.com>
Co-authored-by: Wendong-Fan <w3ndong.fan@gmail.com>
2026-02-06 07:19:29 +08:00

158 lines
5.1 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
/**
* Fix pyvenv.cfg paths before packaging
*
* Problem:
* - pyvenv.cfg contains absolute paths from the build machine
* - Example: home = /Users/builder/project/resources/prebuilt/cache/uv_python/cpython-3.10.19-macos-aarch64-none/bin
* - These paths don't exist on user machines, causing venv to fail
*
* Solution:
* - Replace absolute paths with placeholder tokens
* - At runtime, replace tokens with actual paths on user's machine
* - This makes prebuilt venvs portable across different machines
*/
/* global process, console */
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const projectRoot = path.resolve(__dirname, '..');
/**
* Fix pyvenv.cfg in a venv directory
*/
function fixPyvenvCfg(venvPath, venvName) {
const pyvenvCfgPath = path.join(venvPath, 'pyvenv.cfg');
if (!fs.existsSync(pyvenvCfgPath)) {
console.log(`⚠️ pyvenv.cfg not found: ${pyvenvCfgPath}`);
return false;
}
try {
let content = fs.readFileSync(pyvenvCfgPath, 'utf-8');
const originalContent = content;
// Extract the home path
const homeMatch = content.match(/^home\s*=\s*(.+)$/m);
if (!homeMatch) {
console.log(`⚠️ No 'home' line found in ${venvName}/pyvenv.cfg`);
return false;
}
const originalHome = homeMatch[1].trim();
console.log(`\n📝 Processing ${venvName}/pyvenv.cfg`);
console.log(` Original home: ${originalHome}`);
// Extract cpython directory name from the path
// Example: /path/to/cpython-3.10.19-macos-aarch64-none/bin -> cpython-3.10.19-macos-aarch64-none + /bin
const cpythonMatch = originalHome.match(/(cpython-[\w.-]+)(.*)/);
if (!cpythonMatch) {
console.log(
`⚠️ Could not extract cpython directory from: ${originalHome}`
);
return false;
}
const cpythonDir = cpythonMatch[1];
const pathAfterCpython = cpythonMatch[2];
// Determine if this is Windows or Unix path
const isWindowsPath =
/^[A-Za-z]:\\/.test(originalHome) ||
originalHome.startsWith('\\\\') ||
originalHome.includes('\\');
// Replace with placeholder that will be substituted at runtime
// {{PREBUILT_PYTHON_DIR}} will be replaced with the actual path on user's machine
// Use appropriate path separator for the platform
const pathSep = isWindowsPath ? '\\' : '/';
const newHome = `{{PREBUILT_PYTHON_DIR}}${pathSep}${cpythonDir}${pathAfterCpython}`;
content = content.replace(/^home\s*=\s*.+$/m, `home = ${newHome}`);
// Only write if content changed
if (content !== originalContent) {
fs.writeFileSync(pyvenvCfgPath, content);
console.log(` ✅ Updated to: ${newHome}`);
console.log(
` 🔧 Runtime will replace {{PREBUILT_PYTHON_DIR}} with actual path`
);
return true;
} else {
console.log(` Already using placeholder, no change needed`);
return true;
}
} catch (error) {
console.error(`❌ Error processing ${venvName}/pyvenv.cfg:`, error.message);
return false;
}
}
/**
* Main function
*/
function main() {
console.log('🔧 Fixing pyvenv.cfg paths for portable venvs...');
console.log('================================================\n');
const venvDirs = [
{
path: path.join(projectRoot, 'resources', 'prebuilt', 'venv'),
name: 'backend venv',
},
{
path: path.join(projectRoot, 'resources', 'prebuilt', 'terminal_venv'),
name: 'terminal venv',
},
];
let successCount = 0;
let totalCount = 0;
for (const { path: venvPath, name } of venvDirs) {
if (fs.existsSync(venvPath)) {
totalCount++;
if (fixPyvenvCfg(venvPath, name)) {
successCount++;
}
} else {
console.log(`⚠️ ${name} directory not found: ${venvPath}`);
}
}
console.log('\n================================================');
if (successCount === totalCount && totalCount > 0) {
console.log(
`✅ Successfully fixed ${successCount}/${totalCount} pyvenv.cfg files`
);
console.log('✅ Venvs are now portable and will work on user machines!');
} else if (totalCount === 0) {
console.log(
'⚠️ No venv directories found - this is OK for development builds'
);
} else {
console.log(`⚠️ Fixed ${successCount}/${totalCount} pyvenv.cfg files`);
process.exit(1);
}
}
main();