Add experimental durable exe.dev agent environments

Keep one VM per environment with independent lease cgroups, persistent workspaces, immutable runner images, and an explicit experimental gate. Add live compatibility, recovery, browser-preview, and stress campaigns.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-09-17 09:47:20 -05:00
1 parent e26d787928
commit 056703424a
56 files changed
+1782 -2062

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
import { execFileSync, spawnSync } from "node:child_process";
import { readFile } from "node:fs/promises";
import path from "node:path";
import { computeDaytonaImageContentId, DAYTONA_IMAGE_INPUT_PATHS, extractDaytonaDockerfileFrontendDigest } from "../tests/runner-e2e/daytona-image-content.js";
const root = path.resolve(import.meta.dirname, "..");
const args = process.argv.slice(2);
const option = (name: string) => { const i = args.indexOf(name); return i < 0 ? undefined : args[i + 1]; };
const dockerfile = await readFile(path.join(root, "docker/exe-dev-runner/Dockerfile"), "utf8");
const revision = execFileSync("git", ["rev-parse", "HEAD"], { cwd: root, encoding: "utf8" }).trim();
const dirty = execFileSync("git", ["status", "--porcelain"], { cwd: root, encoding: "utf8" }).trim().length > 0;
if (dirty && process.env.PAPERCLIP_IMAGE_ALLOW_DIRTY !== "1") throw new Error("Commit the image inputs before building, or explicitly set PAPERCLIP_IMAGE_ALLOW_DIRTY=1 for a development image");
// COPY packages includes the workspace graph. Hash every source-owned package
// input so changes outside the runner can never reuse an old content tag.
const packageInputs = execFileSync("git", ["ls-files", "--cached", "--others", "--exclude-standard", "-z", "packages"], { cwd: root, encoding: "utf8" }).split("\0").filter(Boolean);
const contentId = await computeDaytonaImageContentId({
repositoryRoot: root,
inputPaths: [...new Set([...DAYTONA_IMAGE_INPUT_PATHS.filter((p) => p !== "docker/daytona-runner/Dockerfile" && !p.startsWith("packages/")), ...packageInputs, "server/package.json", "ui/package.json", "cli/package.json", "docker/exe-dev-runner", "scripts/build-exe-dev-image.ts"])].sort(),
baseImages: [...dockerfile.matchAll(/^FROM (\S+@sha256:[a-f0-9]{64})/gm)].map((match) => match[1]),
frontendDigest: extractDaytonaDockerfileFrontendDigest(dockerfile),
});
if (args.includes("--content-id")) { console.log(contentId); process.exit(0); }
const tag = option("--tag") ?? `ghcr.io/paperclipai/paperclip-exe-runner:experimental-${contentId}`;
const build = spawnSync("docker", ["buildx", "build", "--platform", "linux/amd64", "--file", "docker/exe-dev-runner/Dockerfile",
"--build-arg", `PAPERCLIP_RUNNER_SOURCE_REVISION=${revision}`,
"--build-arg", `PAPERCLIP_RUNNER_CONTENT_ID=${contentId}`,
"--tag", tag, ...(args.includes("--push") ? ["--push"] : ["--load"]),
...(option("--metadata-file") ? ["--metadata-file", option("--metadata-file")!] : []), "."], { cwd: root, stdio: "inherit" });
if (build.error) throw build.error;
process.exitCode = build.status ?? 1;
+1 -1
View File
@@ -64,7 +64,7 @@ const requiredSourceFragments = [
["scripts/install.sh", "DEFAULT_NODE_MAJOR=24"],
["docker/agent-runtime/Dockerfile.base", "ARG NODE_VERSION=24"],
["packages/adapter-utils/src/sandbox-install-command.ts", "NODE_VERSION=\"v24.11.0\""],
["packages/plugins/sandbox-providers/exe-dev/src/plugin.ts", "nodesource.com/setup_24.x"],
["docker/exe-dev-runner/Dockerfile", "FROM node:24-bookworm@sha256:"],
["packages/plugins/sandbox-providers/modal/src/manifest.ts", 'default: "node:24"'],
["cli/esbuild.config.mjs", 'target: "node24"'],
["packages/plugins/sdk/src/bundlers.ts", 'target: "node24"'],