UNPKG

@blockxai/camp-codegen

Version:

JavaScript/TypeScript SDK for Camp Codegen AI → Compile → Deploy API (parity with Python SDK)

200 lines (199 loc) 8.16 kB
/* eslint-disable no-console */ // Simple CLI matching Python SDK capabilities (non-interactive) // Commands: // - pipeline:start --prompt "..." [--network str] [--maxIters N] [--filename str] [--arg val]* // - job:status <jobId> // - job:logs <jobId> [--since N] // - job:wait <jobId> [--timeout 900] [--interval 2] [--stream] // - artifacts <jobId> [--include all|sources|abis|scripts] // - erc20:deploy --name --symbol --supply N [--network str] [--owner addr] // - ai:generate --prompt "..." // - ai:fix --code "..." --errors "..." // - ai:compile --filename "..." --code "..." import { AcadClient } from "./index.js"; function getArgv() { return (globalThis?.process?.argv ?? []); } function print(obj) { try { console.log(JSON.stringify(obj, null, 2)); } catch { console.log(String(obj)); } } function getFlag(name, fallback) { const argv = getArgv(); const i = argv.indexOf(`--${name}`); if (i !== -1 && i + 1 < argv.length) return argv[i + 1]; const eq = argv.find((a) => a.startsWith(`--${name}=`)); if (eq) return eq.slice(name.length + 3); return fallback; } function getBool(name, fallback = false) { const argv = getArgv(); if (argv.includes(`--${name}`)) return true; const eq = argv.find((a) => a.startsWith(`--${name}=`)); if (eq) { const v = eq.split("=")[1]; return v === "1" || v === "true"; } return fallback; } function getAllFlags(name) { const argv = getArgv(); const out = []; for (let i = 0; i < argv.length; i++) { if (argv[i] === `--${name}` && i + 1 < argv.length) out.push(argv[i + 1]); if (argv[i].startsWith(`--${name}=`)) out.push(argv[i].split("=")[1]); } return out; } export async function run() { const argv = getArgv().slice(2); const cmd = argv[0]; const client = new AcadClient(); try { switch (cmd) { case "pipeline:start": { const prompt = getFlag("prompt"); if (!prompt) throw new Error("--prompt is required"); const network = getFlag("network"); const maxItersStr = getFlag("maxIters"); const filename = getFlag("filename"); const args = getAllFlags("arg"); const constructorArgs = args.map((a) => { try { return JSON.parse(a); } catch { return a; } }); const maxIters = maxItersStr ? parseInt(maxItersStr, 10) : undefined; let jobId; if (network) { jobId = await client.start_pipeline(prompt, network, maxIters, filename, constructorArgs.length ? constructorArgs : undefined); } else { jobId = await client.start_pipeline_auto(prompt, { maxIters, filename, constructorArgs: constructorArgs.length ? constructorArgs : undefined }); } print({ jobId }); break; } case "job:status": { const jobId = argv[1]; if (!jobId) throw new Error("usage: job:status <jobId>"); const job = await client.get_job_status(jobId); print(job); break; } case "job:logs": { const jobId = argv[1]; if (!jobId) throw new Error("usage: job:logs <jobId> [--since N]"); const sinceStr = getFlag("since", "0"); const since = parseInt(sinceStr || "0", 10) || 0; const res = await client.get_job_logs(jobId, since); print(res); break; } case "job:wait": { const jobId = argv[1]; if (!jobId) throw new Error("usage: job:wait <jobId> [--timeout 900] [--interval 2] [--stream]"); const timeoutStr = getFlag("timeout", "900"); const intervalStr = getFlag("interval", "2"); const stream = getBool("stream", false); const job = await client.wait_for_completion(jobId, { timeoutSec: parseInt(timeoutStr || "900", 10) || 900, intervalSec: parseInt(intervalStr || "2", 10) || 2, streamLogs: stream, onUpdate: stream ? (j) => console.error(`[${j.state}] ${j.id}`) : undefined, }); print(job); if (job.state !== "completed") { const summary = client.summarize_failure(job); if (summary) console.error(summary); } break; } case "artifacts": { const jobId = argv[1]; if (!jobId) throw new Error("usage: artifacts <jobId> [--include all|sources|abis|scripts]"); const include = getFlag("include", "all"); const a = await client.get_artifacts(jobId, include); print(a); break; } case "erc20:deploy": { const name = getFlag("name"); const symbol = getFlag("symbol"); const supplyStr = getFlag("supply"); if (!name || !symbol || !supplyStr) throw new Error("--name, --symbol, --supply are required"); const network = getFlag("network"); const owner = getFlag("owner"); const supply = String(parseInt(supplyStr, 10)); const res = await client.deploy_erc20(name, symbol, supply, network || null, owner || undefined); print(res); break; } case "ai:generate": { const prompt = getFlag("prompt"); if (!prompt) throw new Error("--prompt is required"); const res = await client.ai_generate(prompt); print(res); break; } case "ai:fix": { const code = getFlag("code"); const errors = getFlag("errors"); if (!code || !errors) throw new Error("--code and --errors are required"); const res = await client.ai_fix(code, errors); print(res); break; } case "ai:compile": { const filename = getFlag("filename"); const code = getFlag("code"); if (!filename || !code) throw new Error("--filename and --code are required"); const res = await client.ai_compile(filename, code); print(res); break; } case "help": default: { console.log(`Camp Codegen CLI\n\n` + `Usage:\n` + ` camp pipeline:start --prompt "..." [--network basecamp] [--maxIters 5] [--filename AIGenerated.sol] [--arg value]*\n` + ` camp job:status <jobId>\n` + ` camp job:logs <jobId> [--since 0]\n` + ` camp job:wait <jobId> [--timeout 900] [--interval 2] [--stream]\n` + ` camp artifacts <jobId> [--include all|sources|abis|scripts]\n` + ` camp erc20:deploy --name NAME --symbol SYM --supply 1000000 [--network basecamp] [--owner 0x...]\n` + ` camp ai:generate --prompt "..."\n` + ` camp ai:fix --code "..." --errors "..."\n` + ` camp ai:compile --filename Foo.sol --code "..."\n`); break; } } } catch (err) { console.error(err?.message || String(err)); (globalThis?.process?.exit?.(1)); } } // no self-run; bin/cli.mjs will call run()