/** * Repository Manager - Handles Git repository cloning and updates */ import { execSync } from 'child_process'; import { existsSync, mkdirSync } from 'fs'; import { dirname } from 'path'; export interface RepositoryInfo { owner: string; repo: string; sshUrl: string; } /** * Fetch repository information from Gogs MCP */ async function fetchRepositoryInfo(owner: string, repo: string): Promise { // This will be called from the context where Gogs MCP is already connected // For now, we'll use a simple approach: try to fetch the repo info using the Gogs API // In the actual implementation, this will be provided by the MCP server // Since we're running in a context where we can use the mcp__gogs__get_repository tool, // we'll need to make this work within the Agent SDK context // For now, return a placeholder that will be populated by the caller return { owner, repo, sshUrl: '' // Will be populated by the caller }; } /** * Clone a Git repository */ export function cloneRepository(gitUrl: string, targetPath: string): void { console.log(`Repository not found at ${targetPath}, cloning...`); // Create parent directory if it doesn't exist const parentDir = dirname(targetPath); if (!existsSync(parentDir)) { mkdirSync(parentDir, { recursive: true }); } try { execSync(`git clone "${gitUrl}" "${targetPath}"`, { stdio: 'inherit', encoding: 'utf-8' }); console.log('Repository cloned successfully'); } catch (error) { console.error('Failed to clone repository:', error); throw new Error('Failed to clone repository'); } } /** * Pull latest changes from a Git repository */ export function pullRepository(repoPath: string): void { console.log('Repository found, pulling latest changes...'); try { execSync('git pull', { cwd: repoPath, stdio: 'inherit', encoding: 'utf-8' }); console.log('Repository updated successfully'); } catch (error) { console.warn('Warning: git pull failed, continuing with existing repository state'); console.warn(error); } } /** * Ensure repository exists and is up to date * Returns the ssh_url from Gogs MCP that should be used */ export function ensureRepository(repoPath: string, sshUrl: string): void { if (!existsSync(repoPath)) { cloneRepository(sshUrl, repoPath); } else { pullRepository(repoPath); } } /** * Setup environment variables for proper execution */ export function setupEnvironment(): void { // Ensure HOME is set (systemd might not set it) if (!process.env.HOME) { // Try to get HOME from system try { const whoami = execSync('whoami', { encoding: 'utf-8' }).trim(); const homeDir = execSync(`getent passwd "${whoami}" | cut -d: -f6`, { encoding: 'utf-8' }).trim(); if (homeDir) { process.env.HOME = homeDir; } } catch (error) { console.warn('Could not determine HOME directory, using /root'); process.env.HOME = '/root'; } } // Add NODE to PATH const localBin = `${process.env.HOME}/.local/bin`; if (!process.env.PATH?.includes(localBin)) { process.env.PATH = `${localBin}:${process.env.PATH || ''}`; } // Ensure XDG directories are set process.env.XDG_CACHE_HOME = process.env.XDG_CACHE_HOME || `${process.env.HOME}/.cache`; process.env.XDG_CONFIG_HOME = process.env.XDG_CONFIG_HOME || `${process.env.HOME}/.config`; process.env.XDG_DATA_HOME = process.env.XDG_DATA_HOME || `${process.env.HOME}/.local/share`; process.env.XDG_STATE_HOME = process.env.XDG_STATE_HOME || `${process.env.HOME}/.local/state`; // Create XDG directories if they don't exist const xdgDirs = [ process.env.XDG_CACHE_HOME, process.env.XDG_CONFIG_HOME, process.env.XDG_DATA_HOME, process.env.XDG_STATE_HOME ]; for (const dir of xdgDirs) { if (dir && !existsSync(dir)) { try { mkdirSync(dir, { recursive: true }); } catch (error) { console.warn(`Warning: Could not create directory ${dir}:`, error); } } } } /** * Detect Agent Manager path */ export function detectAgentManagerPath(): string { // Try multiple possible locations for the agent-manager .env file const possiblePaths = [ '/home/claude/agent-manager', '/data/agent-manager', `${process.env.HOME}/agent-manager` ]; for (const path of possiblePaths) { const envPath = `${path}/.env`; if (existsSync(envPath)) { console.log(`Found agent-manager at: ${path}`); return path; } } // Fallback: try to detect from current file location // This file is in client/src/, so agent-manager root is ../../ const scriptDir = dirname(new URL(import.meta.url).pathname); const agentManagerPath = dirname(dirname(scriptDir)); console.log(`Using detected path from script location: ${agentManagerPath}`); return agentManagerPath; }