UNPKG

framework

Version:

The (AI) Framework: turnkey, zero-config AI orchestration that wraps a coding-agent CLI (Claude Code) as a black box and takes you from an idea to a running app. Vite for AI.

63 lines 2.44 kB
import { readdir, readFile, stat } from 'node:fs/promises'; import { join, relative, sep } from 'node:path'; /** * Directory names never copied into a sandbox: build output, VCS, and caches. The * sandbox installs its own deps, so `node_modules` is copied by nobody — it is * rebuilt inside the container from the seeded `package.json`. */ export const SANDBOX_IGNORE = new Set([ 'node_modules', '.git', 'dist', 'build', 'out', '.next', '.turbo', '.vite', '.cache', 'coverage', '.the-framework', ]); /** * Read a host workspace into a Runner {@link FileTree} (relative path → contents), * so a fresh sandbox container can be seeded with just the source the driver wrote. * This is the Docker analog of `LocalRunner.adopt`: Local adopts the host dir in * place, Docker cannot, so we copy the source in. * * Text only, and deliberately shallow on cost: build/VCS/cache dirs are skipped, * oversized files are skipped, and a file containing a NUL byte is treated as * binary and skipped (its absence does not stop the app from booting for a health * check). This is a first-slice serve-verification seed, not a faithful mirror. */ export async function snapshotWorkspace(dir, opts = {}) { const ignore = opts.ignore ?? SANDBOX_IGNORE; const maxBytes = opts.maxFileBytes ?? 1024 * 1024; const tree = {}; async function walk(abs) { const entries = await readdir(abs, { withFileTypes: true }); for (const entry of entries) { if (ignore.has(entry.name)) continue; const child = join(abs, entry.name); if (entry.isDirectory()) { await walk(child); continue; } if (!entry.isFile()) continue; // skip symlinks, sockets, devices // Check the size before reading, so a huge asset is skipped without ever // loading it into memory. const st = await stat(child); if (st.size > maxBytes) continue; const buf = await readFile(child); if (buf.includes(0)) continue; // binary // Always use POSIX separators: the key is a path inside a Linux container. tree[relative(dir, child).split(sep).join('/')] = buf.toString('utf8'); } } await walk(dir); return tree; } //# sourceMappingURL=sandbox.js.map