Download src/utils/swarm/backends/it2Setup.ts from chenbhao/codev: direct link, hf CLI and curl.
- Browser
- Download file 6.92 kB
-
https://huggingface.co/chenbhao/codev/resolve/main/src/utils/swarm/backends/it2Setup.ts
- Command line
-
hf download hf://chenbhao/codev/src/utils/swarm/backends/it2Setup.ts
-
curl -L -o it2Setup.ts https://huggingface.co/chenbhao/codev/resolve/main/src/utils/swarm/backends/it2Setup.ts
6.92 kB
| import { homedir } from 'os' | |
| import { getGlobalConfig, saveGlobalConfig } from '../../../utils/config.js' | |
| import { logForDebugging } from '../../../utils/debug.js' | |
| import { | |
| execFileNoThrow, | |
| execFileNoThrowWithCwd, | |
| } from '../../../utils/execFileNoThrow.js' | |
| import { logError } from '../../../utils/log.js' | |
| /** | |
| * Package manager types for installing it2. | |
| * Listed in order of preference. | |
| */ | |
| export type PythonPackageManager = 'uvx' | 'pipx' | 'pip' | |
| /** | |
| * Result of attempting to install it2. | |
| */ | |
| export type It2InstallResult = { | |
| success: boolean | |
| error?: string | |
| packageManager?: PythonPackageManager | |
| } | |
| /** | |
| * Result of verifying it2 setup. | |
| */ | |
| export type It2VerifyResult = { | |
| success: boolean | |
| error?: string | |
| needsPythonApiEnabled?: boolean | |
| } | |
| /** | |
| * Detects which Python package manager is available on the system. | |
| * Checks in order of preference: uvx, pipx, pip. | |
| * | |
| * @returns The detected package manager, or null if none found | |
| */ | |
| export async function detectPythonPackageManager(): Promise<PythonPackageManager | null> { | |
| // Check uv first (preferred for isolated environments) | |
| // We check for 'uv' since 'uv tool install' is the install command | |
| const uvResult = await execFileNoThrow('which', ['uv']) | |
| if (uvResult.code === 0) { | |
| logForDebugging('[it2Setup] Found uv (will use uv tool install)') | |
| return 'uvx' // Keep the type name for compatibility | |
| } | |
| // Check pipx (good for isolated environments) | |
| const pipxResult = await execFileNoThrow('which', ['pipx']) | |
| if (pipxResult.code === 0) { | |
| logForDebugging('[it2Setup] Found pipx package manager') | |
| return 'pipx' | |
| } | |
| // Check pip (fallback) | |
| const pipResult = await execFileNoThrow('which', ['pip']) | |
| if (pipResult.code === 0) { | |
| logForDebugging('[it2Setup] Found pip package manager') | |
| return 'pip' | |
| } | |
| // Also check pip3 | |
| const pip3Result = await execFileNoThrow('which', ['pip3']) | |
| if (pip3Result.code === 0) { | |
| logForDebugging('[it2Setup] Found pip3 package manager') | |
| return 'pip' | |
| } | |
| logForDebugging('[it2Setup] No Python package manager found') | |
| return null | |
| } | |
| /** | |
| * Checks if the it2 CLI tool is installed and accessible. | |
| * | |
| * @returns true if it2 is available | |
| */ | |
| export async function isIt2CliAvailable(): Promise<boolean> { | |
| const result = await execFileNoThrow('which', ['it2']) | |
| return result.code === 0 | |
| } | |
| /** | |
| * Installs the it2 CLI tool using the detected package manager. | |
| * | |
| * @param packageManager - The package manager to use for installation | |
| * @returns Result indicating success or failure | |
| */ | |
| export async function installIt2( | |
| packageManager: PythonPackageManager, | |
| ): Promise<It2InstallResult> { | |
| logForDebugging(`[it2Setup] Installing it2 using ${packageManager}`) | |
| // Run from home directory to avoid reading project-level pip.conf/uv.toml | |
| // which could be maliciously crafted to redirect to an attacker's PyPI server | |
| let result | |
| switch (packageManager) { | |
| case 'uvx': | |
| // uv tool install it2 installs it globally in isolated env | |
| // (uvx is for running, uv tool install is for installing) | |
| result = await execFileNoThrowWithCwd('uv', ['tool', 'install', 'it2'], { | |
| cwd: homedir(), | |
| }) | |
| break | |
| case 'pipx': | |
| result = await execFileNoThrowWithCwd('pipx', ['install', 'it2'], { | |
| cwd: homedir(), | |
| }) | |
| break | |
| case 'pip': | |
| // Use --user to install without sudo | |
| result = await execFileNoThrowWithCwd( | |
| 'pip', | |
| ['install', '--user', 'it2'], | |
| { cwd: homedir() }, | |
| ) | |
| if (result.code !== 0) { | |
| // Try pip3 if pip fails | |
| result = await execFileNoThrowWithCwd( | |
| 'pip3', | |
| ['install', '--user', 'it2'], | |
| { cwd: homedir() }, | |
| ) | |
| } | |
| break | |
| } | |
| if (result.code !== 0) { | |
| const error = result.stderr || 'Unknown installation error' | |
| logError(new Error(`[it2Setup] Failed to install it2: ${error}`)) | |
| return { | |
| success: false, | |
| error, | |
| packageManager, | |
| } | |
| } | |
| logForDebugging('[it2Setup] it2 installed successfully') | |
| return { | |
| success: true, | |
| packageManager, | |
| } | |
| } | |
| /** | |
| * Verifies that it2 is properly configured and can communicate with iTerm2. | |
| * This tests the Python API connection by running a simple it2 command. | |
| * | |
| * @returns Result indicating success or the specific failure reason | |
| */ | |
| export async function verifyIt2Setup(): Promise<It2VerifyResult> { | |
| logForDebugging('[it2Setup] Verifying it2 setup...') | |
| // First check if it2 is installed | |
| const installed = await isIt2CliAvailable() | |
| if (!installed) { | |
| return { | |
| success: false, | |
| error: 'it2 CLI is not installed or not in PATH', | |
| } | |
| } | |
| // Try to list sessions - this tests the Python API connection | |
| const result = await execFileNoThrow('it2', ['session', 'list']) | |
| if (result.code !== 0) { | |
| const stderr = result.stderr.toLowerCase() | |
| // Check for common Python API errors | |
| if ( | |
| stderr.includes('api') || | |
| stderr.includes('python') || | |
| stderr.includes('connection refused') || | |
| stderr.includes('not enabled') | |
| ) { | |
| logForDebugging('[it2Setup] Python API not enabled in iTerm2') | |
| return { | |
| success: false, | |
| error: 'Python API not enabled in iTerm2 preferences', | |
| needsPythonApiEnabled: true, | |
| } | |
| } | |
| return { | |
| success: false, | |
| error: result.stderr || 'Failed to communicate with iTerm2', | |
| } | |
| } | |
| logForDebugging('[it2Setup] it2 setup verified successfully') | |
| return { | |
| success: true, | |
| } | |
| } | |
| /** | |
| * Returns instructions for enabling the Python API in iTerm2. | |
| */ | |
| export function getPythonApiInstructions(): string[] { | |
| return [ | |
| 'Almost done! Enable the Python API in iTerm2:', | |
| '', | |
| ' iTerm2 → Settings → General → Magic → Enable Python API', | |
| '', | |
| 'After enabling, you may need to restart iTerm2.', | |
| ] | |
| } | |
| /** | |
| * Marks that it2 setup has been completed successfully. | |
| * This prevents showing the setup prompt again. | |
| */ | |
| export function markIt2SetupComplete(): void { | |
| const config = getGlobalConfig() | |
| if (config.iterm2It2SetupComplete !== true) { | |
| saveGlobalConfig(current => ({ | |
| ...current, | |
| iterm2It2SetupComplete: true, | |
| })) | |
| logForDebugging('[it2Setup] Marked it2 setup as complete') | |
| } | |
| } | |
| /** | |
| * Marks that the user prefers to use tmux over iTerm2 split panes. | |
| * This prevents showing the setup prompt when in iTerm2. | |
| */ | |
| export function setPreferTmuxOverIterm2(prefer: boolean): void { | |
| const config = getGlobalConfig() | |
| if (config.preferTmuxOverIterm2 !== prefer) { | |
| saveGlobalConfig(current => ({ | |
| ...current, | |
| preferTmuxOverIterm2: prefer, | |
| })) | |
| logForDebugging(`[it2Setup] Set preferTmuxOverIterm2 = ${prefer}`) | |
| } | |
| } | |
| /** | |
| * Checks if the user prefers tmux over iTerm2 split panes. | |
| */ | |
| export function getPreferTmuxOverIterm2(): boolean { | |
| return getGlobalConfig().preferTmuxOverIterm2 === true | |
| } | |