From aa4f46acc550d00f8a89535405a0c2bd05ee15ea Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Tue, 3 Feb 2026 08:09:46 +0000 Subject: [PATCH] fix: Add utility and config source files --- src/utils/env-utils.ts | 197 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 src/utils/env-utils.ts diff --git a/src/utils/env-utils.ts b/src/utils/env-utils.ts new file mode 100644 index 0000000..5175cca --- /dev/null +++ b/src/utils/env-utils.ts @@ -0,0 +1,197 @@ +import * as path from 'path'; +import * as fs from 'fs-extra'; +import { execa } from 'execa'; +import * as os from 'os'; +import { CreateOptions } from '../types/index'; +import { GitAgentSyncError } from './errors'; +import { createEnvironmentFile, readPackageJson } from './file-utils'; + +const DEFAULT_ENV_TEMPLATE = `# Environment variables for agent workspace +AGENT_ID={agentName} +WORKSPACE_PATH={workspacePath} +AGENT_WORKSPACE={workspacePath} +GIT_USER_EMAIL={gitUserEmail} +GIT_USER_NAME={gitUserName} +`; + +export async function installDependencies(workspacePath: string): Promise { + const pkgJson = await readPackageJson(workspacePath); + + if (!pkgJson) { + return; + } + + const packageManager = detectPackageManager(workspacePath); + + if (!packageManager) { + throw new GitAgentSyncError('No package manager detected (package.json found but no lockfile)'); + } + + const command = packageManager === 'npm' ? 'npm install' : `${packageManager} install`; + + await execa(command, { + cwd: workspacePath, + stdio: 'inherit' + }); +} + +function detectPackageManager(workspacePath: string): 'npm' | 'yarn' | 'pnpm' | null { + if (fs.existsSync(path.join(workspacePath, 'yarn.lock'))) { + return 'yarn'; + } + if (fs.existsSync(path.join(workspacePath, 'pnpm-lock.yaml'))) { + return 'pnpm'; + } + if (fs.existsSync(path.join(workspacePath, 'package-lock.json'))) { + return 'npm'; + } + return null; +} + +export async function setupEnvironment( + workspacePath: string, + agentName: string, + options: CreateOptions +): Promise { + const envVars: Record = { + AGENT_ID: agentName, + WORKSPACE_PATH: workspacePath, + AGENT_WORKSPACE: workspacePath, + ...(options.environment || {}) + }; + + const templatePath = options.template + ? path.resolve(options.template) + : undefined; + + if (templatePath && await fs.pathExists(templatePath)) { + await applyEnvironmentTemplate(templatePath, workspacePath, agentName, envVars); + } else { + await createEnvironmentFile(workspacePath, envVars); + } +} + +async function applyEnvironmentTemplate( + templatePath: string, + workspacePath: string, + agentName: string, + additionalVars: Record +): Promise { + const templateEnvPath = path.join(templatePath, '.env.template'); + const templateReadmePath = path.join(templatePath, 'README.md'); + + if (await fs.pathExists(templateEnvPath)) { + const templateContent = await fs.readFile(templateEnvPath, 'utf-8'); + const processedContent = processTemplate(templateContent, { + agentName, + workspacePath, + ...additionalVars + }); + await fs.writeFile(path.join(workspacePath, '.env'), processedContent, 'utf-8'); + } else { + const defaultContent = DEFAULT_ENV_TEMPLATE + .replace(/{agentName}/g, agentName) + .replace(/{workspacePath}/g, workspacePath) + .replace(/{gitUserEmail}/g, '') + .replace(/{gitUserName}/g, ''); + await fs.writeFile(path.join(workspacePath, '.env'), defaultContent, 'utf-8'); + } + + if (await fs.pathExists(templateReadmePath)) { + const readmeContent = await fs.readFile(templateReadmePath, 'utf-8'); + await fs.writeFile(path.join(workspacePath, 'SETUP.md'), readmeContent, 'utf-8'); + } + + const otherFiles = await fs.readdir(templatePath); + for (const file of otherFiles) { + if (file !== '.env.template' && file !== 'README.md') { + const src = path.join(templatePath, file); + const dest = path.join(workspacePath, file); + if ((await fs.stat(src)).isFile()) { + await fs.copy(src, dest); + } + } + } +} + +function processTemplate( + content: string, + variables: Record +): string { + let result = content; + for (const [key, value] of Object.entries(variables)) { + result = result.replace(new RegExp(`\\{${key}\\}`, 'g'), value); + } + return result; +} + +export async function runCustomSetupScript( + workspacePath: string, + scriptPath: string +): Promise { + if (!(await fs.pathExists(scriptPath))) { + throw new GitAgentSyncError(`Setup script not found: ${scriptPath}`); + } + + const absoluteScriptPath = path.resolve(scriptPath); + const extension = path.extname(absoluteScriptPath); + + if (extension === '.sh') { + await execa('bash', [absoluteScriptPath], { + cwd: workspacePath, + stdio: 'inherit' + }); + } else if (extension === '.js' || extension === '.mjs') { + await execa(process.execPath, [absoluteScriptPath], { + cwd: workspacePath, + stdio: 'inherit' + }); + } else { + throw new GitAgentSyncError(`Unsupported setup script: ${extension}`); + } +} + +export async function getGitUserInfo(): Promise<{ name: string; email: string }> { + try { + const { stdout: name } = await execa('git', ['config', '--global', 'user.name'], { + reject: false + }); + const { stdout: email } = await execa('git', ['config', '--global', 'user.email'], { + reject: false + }); + + return { + name: name || os.userInfo().username, + email: email || `${os.userInfo().username}@localhost` + }; + } catch { + return { + name: os.userInfo().username, + email: `${os.userInfo().username}@localhost` + }; + } +} + +export async function checkCommandAvailability(command: string): Promise { + try { + await execa(command, ['--version'], { reject: false }); + return true; + } catch { + return false; + } +} + +export function generateAgentEnvironment( + agentName: string, + workspacePath: string, + gitUserInfo: { name: string; email: string } +): Record { + return { + AGENT_ID: agentName, + WORKSPACE_PATH: workspacePath, + AGENT_WORKSPACE: workspacePath, + GIT_USER_EMAIL: gitUserInfo.email, + GIT_USER_NAME: gitUserInfo.name, + AGENT_CREATED_AT: new Date().toISOString() + }; +}