UNPKG

@avikalpa/codex-litellm

Version:

Patched OpenAI Codex CLI with first-class LiteLLM support

124 lines (102 loc) 4.07 kB
#!/usr/bin/env node const crypto = require('crypto'); const fs = require('fs'); const { mkdirSync, rmSync } = fs; const path = require('path'); const os = require('os'); const https = require('https'); const { execFileSync } = require('child_process'); if (process.env.CODEX_LITELLM_SKIP_DOWNLOAD === '1') { console.log('Skipping codex-litellm binary download.'); process.exit(0); } const TARGET_SUFFIX = new Map([ ['linux:x64', 'linux-x64'], ['linux:arm64', 'linux-arm64'], ['android:arm64', 'android-arm64'], ['darwin:x64', 'macos-x64'], ['darwin:arm64', 'macos-arm64'], ['win32:x64', 'windows-x64'], ['win32:arm64', 'windows-arm64'], ['freebsd:x64', 'freebsd-x64'], ['sunos:x64', 'illumos-x64'], ]); const key = `${process.platform}:${process.arch}`; const suffix = TARGET_SUFFIX.get(key); if (!suffix) { console.error(`codex-litellm: no prebuilt binary for ${process.platform}/${process.arch}.`); console.error('Please build from source instead: https://github.com/avikalpa/codex-litellm'); process.exit(0); } const pkg = require('../package.json'); const version = pkg.version; const tag = process.env.CODEX_LITELLM_RELEASE_TAG || (pkg.codexLitellm && pkg.codexLitellm.releaseTag) || `v${version}`; const baseUrl = `https://github.com/avikalpa/codex-litellm/releases/download/${tag}`; const archiveName = `codex-litellm-${suffix}.tar.gz`; const archiveUrl = `${baseUrl}/${archiveName}`; const checksumUrl = `${archiveUrl}.sha256`; const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'codex-litellm-')); const archivePath = path.join(tmpDir, archiveName); const checksumPath = `${archivePath}.sha256`; function download(url, dest) { return new Promise((resolve, reject) => { const request = https.get(url, (res) => { if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { res.resume(); download(res.headers.location, dest).then(resolve).catch(reject); return; } if (res.statusCode !== 200) { reject(new Error(`Request failed. Status code: ${res.statusCode} for ${url}`)); res.resume(); return; } const file = fs.createWriteStream(dest); res.pipe(file); file.on('finish', () => file.close(resolve)); file.on('error', (err) => { file.close(() => fs.unlink(dest, () => {})); reject(err); }); }); request.on('error', (err) => { reject(err); }); }); } function verifyChecksum(filePath, checksumFile) { const expected = fs.readFileSync(checksumFile, 'utf8').split(/\s+/)[0].trim(); const hash = crypto.createHash('sha256'); const data = fs.readFileSync(filePath); hash.update(data); const actual = hash.digest('hex'); if (expected !== actual) { throw new Error(`Checksum mismatch: expected ${expected}, got ${actual}`); } } (async () => { try { console.log(`Downloading ${archiveName} (${version})...`); await download(archiveUrl, archivePath); console.log('Downloading checksum...'); await download(checksumUrl, checksumPath); verifyChecksum(archivePath, checksumPath); const distRoot = path.join(__dirname, '..', 'dist'); const destDir = path.join(distRoot, suffix); rmSync(destDir, { recursive: true, force: true }); mkdirSync(destDir, { recursive: true }); console.log('Extracting binary...'); execFileSync('tar', ['-xzf', archivePath, '-C', destDir]); const binaryName = process.platform === 'win32' ? 'codex-litellm.exe' : 'codex-litellm'; const binaryPath = path.join(destDir, binaryName); if (!fs.existsSync(binaryPath)) { throw new Error(`Binary missing after extraction: ${binaryPath}`); } fs.chmodSync(binaryPath, 0o755); console.log(`codex-litellm binary installed for ${suffix}.`); } catch (err) { console.error(`Failed to install codex-litellm prebuilt binary: ${err.message}`); console.error('You can build manually by running `npm explore @avikalpa/codex-litellm -- ./build.sh`.'); process.exit(1); } })();