@freysa/create-sovereign-agent
Version:
CLI tool to make your agent sovereign.
156 lines (130 loc) • 5.93 kB
JavaScript
import { Command } from 'commander';
import fs from 'fs-extra';
import path from 'path';
import { fileURLToPath } from 'url';
// Get the package root directory
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const PACKAGE_ROOT = path.join(__dirname, '..');
const program = new Command();
program
.name('create-sovereign-agent')
.description('CLI to create or modify agent repos with Sovereign Enclave scaffold');
// create-sovereign-agent new <projectName>
program
.command('new <projectName>')
.description('Create a new directory with Sovereign Enclave scaffold')
.action(async (projectName) => {
try {
await createNewProject(projectName);
} catch (err) {
console.error('Error:', err.message || err);
process.exit(1);
}
});
// create-sovereign-agent add <sourceAgentDir>
program
.command('add <sourceAgentDir>')
.description('Add Sovereign Enclave scaffold to an existing agent folder')
.option('--docker-url <string>', 'Full Docker image URL to inject into Dockerfiles')
.action(async (sourceAgentDir, options) => {
try {
await wrapAgentFolder(sourceAgentDir, options);
} catch (err) {
console.error('Error:', err.message || err);
process.exit(1);
}
});
program.parse(process.argv);
/**
* Wrap the user's existing agent code into a new folder containing:
* - agent/ (copied from sourceAgentDir)
* - Dockerfile, Dockerfile.agent, config.json, start.sh, run_enclave.sh, Makefile, etc.
*/
async function wrapAgentFolder(sourceAgentDir, options) {
const absoluteTarget = path.resolve(process.cwd(), sourceAgentDir);
// Ensure source exists
if (!(await fs.pathExists(absoluteTarget))) {
throw new Error(`Source folder "${sourceAgentDir}" does not exist.`);
}
console.log(`\nAdding Sovereign Enclave scaffold to "${sourceAgentDir}"...\n`);
// Copy template files from templates directory
const enclaveTemplateDir = path.join(__dirname, 'templates', 'enclave');
const dockerfileAgent = path.join(__dirname, 'templates', 'Dockerfile.agent');
if (!(await fs.pathExists(enclaveTemplateDir))) {
throw new Error(`Missing enclave template directory: ${enclaveTemplateDir}`);
}
if (!(await fs.pathExists(dockerfileAgent))) {
throw new Error(`Missing Dockerfile.agent template: ${dockerfileAgent}`);
}
// Copy enclave folder
await fs.copy(enclaveTemplateDir, path.join(absoluteTarget, 'enclave'), { overwrite: true });
// Copy Dockerfile.agent to root
await fs.copy(dockerfileAgent, path.join(absoluteTarget, 'Dockerfile.agent'), { overwrite: true });
// If user provided --docker-url, do string replacement on placeholders
if (options.dockerUrl) {
const templateFiles = await fs.readdir(enclaveTemplateDir);
for (const file of templateFiles) {
const destFile = path.join(absoluteTarget, file);
if ((await fs.stat(destFile)).isFile()) {
let content = await fs.readFile(destFile, 'utf-8');
if (content.includes('{{DOCKER_IMAGE_URL}}')) {
content = content.replace(/{{DOCKER_IMAGE_URL}}/g, options.dockerUrl);
await fs.writeFile(destFile, content, 'utf-8');
}
}
}
console.log(`Injected --docker-url (${options.dockerUrl}) into Dockerfiles.`);
} else {
console.log(`No --docker-url provided; left {{DOCKER_IMAGE_URL}} placeholders as-is.`);
}
// Print final instructions
console.log(`\nSuccess! Your enclave wrapper has been added to "${sourceAgentDir}".\n`);
console.log(`Template files added:\n`);
console.log(` Dockerfile.agent (in root)`);
console.log(` enclave/ folder containing:`);
console.log(` Dockerfile, config.json, start.sh, run_enclave.sh, Makefile, etc.\n`);
console.log(`You can now build images, reference your Docker URL, etc.\n`);
console.log(`Example steps:\n`);
console.log(` cd ${sourceAgentDir}`);
console.log(` # If you want to build the agent image (Dockerfile.agent) and push`);
console.log(` docker build -t <your-repo/agent:tag> -f Dockerfile.agent .`);
console.log(` docker push <your-repo/agent:tag>\n`);
console.log(` # Then build the runner/enclave image (Dockerfile)`);
console.log(` docker build -t <your-repo/runner:tag> -f Dockerfile .`);
console.log(` docker push <your-repo/runner:tag>\n`);
console.log(` # Then run it!`);
console.log(` docker run --rm <your-repo/runner:tag>\n`);
}
async function createNewProject(projectName) {
const targetDir = path.resolve(process.cwd(), projectName);
// Ensure target doesn't exist
if (await fs.pathExists(targetDir)) {
throw new Error(`Directory "${projectName}" already exists.`);
}
console.log(`\nCreating new Sovereign Enclave project in "${projectName}"...\n`);
// Create the directory
await fs.mkdirp(targetDir);
// Copy template files from templates directory
const enclaveDir = path.join(__dirname, 'templates', 'enclave');
const dockerfileAgent = path.join(__dirname, 'templates', 'Dockerfile.agent');
if (!(await fs.pathExists(enclaveDir))) {
throw new Error(`Missing enclave directory: ${enclaveDir}`);
}
if (!(await fs.pathExists(dockerfileAgent))) {
throw new Error(`Missing Dockerfile.agent: ${dockerfileAgent}`);
}
// Copy enclave folder and Dockerfile.agent
await fs.copy(enclaveDir, path.join(targetDir, 'enclave'));
await fs.copy(dockerfileAgent, path.join(targetDir, 'Dockerfile.agent'));
console.log(`\nSuccess! Created new project in "${projectName}".\n`);
console.log(`Template files added:\n`);
console.log(` Dockerfile.agent (in root)`);
console.log(` enclave/ folder containing:`);
console.log(` Dockerfile, config.json, start.sh, run_enclave.sh, Makefile, etc.\n`);
console.log(`Next steps:\n`);
console.log(` cd ${projectName}`);
console.log(` git init`);
console.log(` # Start adding your agent code!\n`);
}