Ctrl K
ComunidadGuías…

scripts/fix-venv-paths.js

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/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();