Integrate immutable Boat provider pack cache

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-10 11:51:58 -05:00
commit a8e7bc576d
3 files changed
+324 -5

No files matched your search

@@ -42,6 +42,7 @@ import { nativeCompletionFeedback } from "./native-completion-feedback.js";
import { hasAcknowledgedNativeReassignmentStopIntent, hasAcknowledgedNativeStopIntent } from "../acknowledged-native-stop.js";
import { stoppedCodexTurnIsTextOnly } from "./stopped-codex-turn.js";
import { prepareVerifiedRemoteProviderPack } from "./remote-provider-pack.js";
import { computerProviderPackCachePath, prepareComputerProviderPackCache } from "./remote-provider-pack-cache.js";
import { selectRemotePiCompanion } from "./remote-pi-companion.js";
import { readNativeLocalProcessStop, PROCESS_START_REQUESTED } from "../native-local-process-stop.js";
import { remoteLeaseCleanupScope } from "../remote-execution-termination.js";
@@ -11963,9 +11964,9 @@ async function createRunnerdBackendWithinSessionClaim(
configuredProviderPackRoot,
);
}
const stagedRemoteProviderPackRoot = remoteRuntimeRoot
? posix.join(remoteRuntimeRoot, "provider-pack")
: null;
const stagedRemoteProviderPackRoot = remoteTarget?.transport === "computer" && expectedProviderPackManifest
? computerProviderPackCachePath(remoteTarget.fileAuthority.agentHome, expectedProviderPackManifest.digest)
: remoteRuntimeRoot ? posix.join(remoteRuntimeRoot, "provider-pack") : null;
let activeRemoteProviderPackRoot: string | null = null;
const remoteBinary = remoteRuntimeRoot
? posix.join(remoteRuntimeRoot, "bin", "paperclip-runnerd")
@@ -12510,7 +12511,31 @@ async function createRunnerdBackendWithinSessionClaim(
expectedProviderPackManifest &&
stagedRemoteProviderPackRoot
) {
const packSource = await prepareVerifiedRemoteProviderPack({
const packSource = remoteTarget.transport === "computer"
? await prepareComputerProviderPackCache({
cacheRoot: stagedRemoteProviderPackRoot,
sessionKey: nativeSessionKey(input.execution),
owner: remoteTarget.resourceAuthority,
runner: remoteCommandRunner,
verify: (root) => measureNativeRunnerSpan(input.trace, "provider_pack.verify", () => verifyRemoteProviderPack(root)),
stage: async (root, runner) => {
if (!configuredProviderPackRoot) {
throw new Error("runner_remote_provider_artifact_incompatible: configure the build-owned provider pack for first use on this computer");
}
await input.onLog?.("stderr", "[paperclip-runner] Preparing the provider pack for first use.\n");
await stageRemoteRunnerDirectory({
target: remoteTarget,
runner,
sourcePath: configuredProviderPackRoot,
targetPath: root,
mode: 0o700,
onProgress: async (completed, total) => {
await input.onLog?.("stderr", `[paperclip-runner] Uploading provider pack: ${Math.round(completed / 1024 / 1024)} / ${Math.round(total / 1024 / 1024)} MiB.\n`);
},
});
},
})
: await prepareVerifiedRemoteProviderPack({
verifyStaged: () => measureNativeRunnerSpan(
input.trace,
"provider_pack.verify",
@@ -12600,7 +12625,7 @@ async function createRunnerdBackendWithinSessionClaim(
},
});
activeRemoteProviderPackRoot = stagedRemoteProviderPackRoot;
if (packSource === "staged") {
if (packSource === "staged" || packSource === "reused") {
await input.onLog?.(
"stderr",
"[paperclip-runner] reusing manifest-matched provider pack from the workspace\n",
@@ -0,0 +1,145 @@
import { spawn } from "node:child_process";
import { promises as fs } from "node:fs";
import { tmpdir } from "node:os";
import { dirname, join } from "node:path";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { CommandManagedRuntimeRunner } from "@paperclipai/adapter-utils/command-managed-runtime";
import { computerProviderPackCachePath, prepareComputerProviderPackCache } from "./remote-provider-pack-cache.js";
const roots: string[] = [];
const digest = `sha256:${"a".repeat(64)}`;
const runner: CommandManagedRuntimeRunner = {
execute: (input) => new Promise((resolve, reject) => {
const child = spawn(input.command, input.args, { cwd: input.cwd, env: { ...process.env, ...input.env } });
let stdout = ""; let stderr = "";
child.stdout.on("data", (chunk) => { stdout += chunk; void input.onLog?.("stdout", String(chunk)); });
child.stderr.on("data", (chunk) => { stderr += chunk; });
child.on("error", reject);
child.on("close", (exitCode, signal) => resolve({ exitCode, signal, stdout, stderr, timedOut: false, pid: child.pid ?? null, startedAt: null }));
child.stdin.end(input.stdin);
}),
};
async function fixture() {
const home = await fs.realpath(await fs.mkdtemp(join(tmpdir(), "provider-cache-")));
roots.push(home);
return {
cacheRoot: computerProviderPackCachePath(home, digest), sessionKey: "task-a",
owner: { ownerId: "owner-a", generation: 1 }, runner,
verify: async (root: string) => { expect(await fs.readFile(join(root, "payload"), "utf8")).toBe("verified bytes"); },
stage: async (root: string, guarded: CommandManagedRuntimeRunner) => {
const result = await guarded.execute({ command: "python3", args: ["-c", "import os,sys;os.mkdir(sys.argv[1],0o700);open(os.path.join(sys.argv[1],'payload'),'w').write(sys.stdin.read())", root], stdin: "verified bytes" });
if (result.exitCode !== 0) throw new Error(result.stderr);
},
};
}
function deferred() { let resolve!: () => void; const promise = new Promise<void>((done) => { resolve = done; }); return { promise, resolve }; }
afterEach(async () => { await Promise.all(roots.splice(0).map((root) => fs.rm(root, { recursive: true, force: true }))); });
describe("persistent computer provider pack cache", () => {
it("shares immutable identity across tasks, with separate agents and digests", () => {
expect(computerProviderPackCachePath("/agents/a", digest)).not.toBe(computerProviderPackCachePath("/agents/b", digest));
expect(computerProviderPackCachePath("/agents/a", digest)).not.toBe(computerProviderPackCachePath("/agents/a", `sha256:${"b".repeat(64)}`));
expect(() => computerProviderPackCachePath("/agents/../a", digest)).toThrow("identity_invalid");
});
it("verifies a shared hit before the compression/upload callback and excludes its ownership marker", async () => {
const input = await fixture();
const stage = vi.fn(input.stage); const verify = vi.fn(input.verify);
await expect(prepareComputerProviderPackCache({ ...input, stage, verify })).resolves.toBe("published");
await expect(prepareComputerProviderPackCache({ ...input, stage, verify, sessionKey: "task-b" })).resolves.toBe("reused");
expect(stage).toHaveBeenCalledTimes(1);
expect(verify).toHaveBeenCalledTimes(3);
expect(await fs.readdir(input.cacheRoot)).toEqual(["payload"]);
});
it("fails closed on a corrupt published pack, preserving its exact contents", async () => {
const input = await fixture();
await fs.mkdir(input.cacheRoot, { recursive: true });
await fs.writeFile(join(input.cacheRoot, "payload"), "corrupt");
const stage = vi.fn(input.stage);
await expect(prepareComputerProviderPackCache({ ...input, stage })).rejects.toThrow("operator remove or quarantine this exact cache");
expect(stage).not.toHaveBeenCalled();
expect(await fs.readFile(join(input.cacheRoot, "payload"), "utf8")).toBe("corrupt");
});
it("publishes without replacement when two tasks race and verifies the winner", async () => {
const input = await fixture(); const both = deferred(); let staged = 0;
const stage = async (root: string, guarded: CommandManagedRuntimeRunner) => {
await input.stage(root, guarded); if (++staged === 2) both.resolve(); await both.promise;
};
await Promise.all(["task-a", "task-b"].map((sessionKey) => prepareComputerProviderPackCache({ ...input, sessionKey, stage })));
expect(staged).toBe(2);
await input.verify(input.cacheRoot);
const directories = await fs.readdir(join(dirname(input.cacheRoot), ".uploads"));
for (const session of directories) expect(await fs.readdir(join(dirname(input.cacheRoot), ".uploads", session, "a".repeat(64)))).toEqual(["lock"]);
});
it("cleans only its marked private upload after failure", async () => {
const input = await fixture(); const unrelated = join(dirname(input.cacheRoot), ".uploads", "user-data");
await fs.mkdir(unrelated, { recursive: true }); await fs.writeFile(join(unrelated, "keep"), "mine");
let attempted = "";
await expect(prepareComputerProviderPackCache({ ...input, stage: async (root, guarded) => {
attempted = dirname(root); await input.stage(root, guarded); throw new Error("upload disconnected");
} })).rejects.toThrow("upload disconnected");
await expect(fs.stat(attempted)).rejects.toMatchObject({ code: "ENOENT" });
expect(await fs.readFile(join(unrelated, "keep"), "utf8")).toBe("mine");
});
it("rejects delayed old writes and keeps the replacement when a session retries", async () => {
const input = await fixture(); const oldReady = deferred(); const releaseOld = deferred();
let oldRoot = ""; let oldRunner!: CommandManagedRuntimeRunner;
const old = prepareComputerProviderPackCache({ ...input, stage: async (root, guarded) => {
oldRoot = root; oldRunner = guarded; await input.stage(root, guarded); oldReady.resolve(); await releaseOld.promise;
throw new Error("old attempt retired");
} });
const rejectedOld = expect(old).rejects.toThrow("old attempt retired");
await oldReady.promise;
await prepareComputerProviderPackCache({ ...input, owner: { ...input.owner, generation: 2 } });
const staleWrite = await oldRunner.execute({ command: "python3", args: ["-c", "import os,sys;os.makedirs(sys.argv[1],exist_ok=True)", oldRoot] });
expect(staleWrite.exitCode).not.toBe(0);
expect(staleWrite.stderr).toContain("stale upload generation");
releaseOld.resolve(); await rejectedOld;
await input.verify(input.cacheRoot);
await expect(fs.stat(dirname(oldRoot))).rejects.toMatchObject({ code: "ENOENT" });
});
it("waits for an in-flight guarded writer before replacing its receipt", async () => {
const input = await fixture(); const entered = deferred(); const releaseStage = deferred();
const releaseFile = join(roots.at(-1)!, "release-writer");
let write!: Promise<Awaited<ReturnType<CommandManagedRuntimeRunner["execute"]>>>;
const old = prepareComputerProviderPackCache({ ...input, stage: async (root, guarded) => {
await input.stage(root, guarded);
write = guarded.execute({ command: "python3", args: ["-c", "import os,sys,time;print('entered',flush=True)\nwhile not os.path.exists(sys.argv[1]):time.sleep(0.01)", releaseFile], onLog: async (_stream, text) => { if (text.includes("entered")) entered.resolve(); } });
await releaseStage.promise; await write; throw new Error("old retired");
} });
const rejectedOld = expect(old).rejects.toThrow("old retired");
await entered.promise;
let replacementStaged = false;
const replacement = prepareComputerProviderPackCache({ ...input, owner: { ...input.owner, generation: 2 }, stage: async (root, guarded) => {
replacementStaged = true; await input.stage(root, guarded);
} });
await new Promise((resolve) => setTimeout(resolve, 100));
expect(replacementStaged).toBe(false);
await fs.writeFile(releaseFile, "release");
expect((await write).exitCode).toBe(0);
await replacement; releaseStage.resolve(); await rejectedOld;
await input.verify(input.cacheRoot);
});
it("reclaims an interrupted marked upload on the next attempt", async () => {
const input = await fixture(); let attempted = "";
const disconnected: CommandManagedRuntimeRunner = { execute: (command) => {
if (command.args?.[2] === "cleanup") return Promise.reject(new Error("controller disconnected"));
return runner.execute(command);
} };
await expect(prepareComputerProviderPackCache({ ...input, runner: disconnected, stage: async (root, guarded) => {
attempted = dirname(root); await input.stage(root, guarded); throw new Error("interrupted");
} })).rejects.toThrow("interrupted");
expect((await fs.stat(attempted)).isDirectory()).toBe(true);
// Another task can publish while this session is disconnected. Retrying
// this session must reclaim its exact old upload even on the shared hit.
await prepareComputerProviderPackCache({ ...input, sessionKey: "another-task" });
await expect(prepareComputerProviderPackCache({ ...input, owner: { ...input.owner, generation: 2 } })).resolves.toBe("reused");
await expect(fs.stat(attempted)).rejects.toMatchObject({ code: "ENOENT" });
});
});
@@ -0,0 +1,149 @@
import { createHash, randomUUID } from "node:crypto";
import { posix } from "node:path";
import type { CommandManagedRuntimeRunner } from "@paperclipai/adapter-utils/command-managed-runtime";
export function computerProviderPackCachePath(agentHome: string, digest: string): string {
if (!posix.isAbsolute(agentHome) || posix.normalize(agentHome) !== agentHome || !/^sha256:[a-f0-9]{64}$/.test(digest)) {
throw new Error("runner_remote_provider_cache_identity_invalid");
}
return posix.join(agentHome, ".paperclip-runtime", "paperclip-runner", "provider-packs", digest.slice(7));
}
// Publication never replaces shared bytes. The per-session receipt fences every
// staging command; a retry waits for in-flight writes before replacing its receipt.
// A session never retried can retain its private partial upload for operator cleanup.
const cacheProgram = String.raw`
import os,sys,json,stat,fcntl,ctypes,errno,shutil,subprocess
op,root,session,identity_json=sys.argv[1:5];identity=json.loads(identity_json)
def fail(message):raise RuntimeError(message)
def directory(path):
fd=os.open('/',os.O_RDONLY|os.O_DIRECTORY)
try:
for part in path.split('/'):
if not part:continue
if part in ('.','..'):fail('invalid cache path')
try:os.mkdir(part,0o700,dir_fd=fd)
except FileExistsError:pass
nxt=os.open(part,os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=fd);os.close(fd);fd=nxt
return fd
except BaseException:os.close(fd);raise
parent=directory(os.path.dirname(root));name=os.path.basename(root)
try:
if op=='exists':
try:
info=os.stat(name,dir_fd=parent,follow_symlinks=False)
if not stat.S_ISDIR(info.st_mode):fail('cache is not a real directory')
print('true')
except FileNotFoundError:print('false')
sys.exit(0)
slot=directory(os.path.join(os.path.dirname(root),'.uploads',session,name))
lock=os.open('lock',os.O_CREAT|os.O_RDWR|os.O_NOFOLLOW,0o600,dir_fd=slot)
if not stat.S_ISREG(os.fstat(lock).st_mode) or os.fstat(lock).st_nlink!=1:fail('invalid cache lock')
fcntl.flock(lock,fcntl.LOCK_SH if op=='guard' else fcntl.LOCK_EX)
def read(name,fd=slot):
source=os.open(name,os.O_RDONLY|os.O_NOFOLLOW,dir_fd=fd)
with os.fdopen(source,'rb') as f:
info=os.fstat(f.fileno())
if not stat.S_ISREG(info.st_mode) or info.st_nlink!=1 or info.st_size>4096:fail('invalid cache receipt')
return json.load(f)
def owned(value):
return isinstance(value,dict) and value.get('purpose')=='paperclip-provider-pack-upload-v1' and value.get('cacheRoot')==root and value.get('session')==session and isinstance(value.get('attemptId'),str) and len(value['attemptId'])==36 and all(c in '0123456789abcdef-' for c in value['attemptId'])
def cleanup(value):
if not owned(value):fail('invalid upload ownership')
try:fd=os.open(value['attemptId'],os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=slot)
except FileNotFoundError:return
try:
try:marker=read('owner.json',fd)
except FileNotFoundError:
os.rmdir(value['attemptId'],dir_fd=slot);return
if marker!=value:fail('upload ownership mismatch')
finally:os.close(fd)
shutil.rmtree(value['attemptId'],dir_fd=slot)
try:current=read('current.json')
except FileNotFoundError:current=None
if op in ('begin','reap'):
if current is not None:
if not owned(current):fail('invalid upload receipt')
if current.get('ownerId')==identity['ownerId'] and current.get('generation',0)>identity['generation']:fail('stale upload generation')
cleanup(current)
if op=='reap':
if current is not None:os.unlink('current.json',dir_fd=slot)
sys.exit(0)
# Reserve the exact attempt before creating its directory. An interrupted
# begin is recoverable without recursively deleting unmarked user content.
try:os.stat(identity['attemptId'],dir_fd=slot,follow_symlinks=False);fail('upload already exists')
except FileNotFoundError:pass
fd=os.open('current.tmp',os.O_CREAT|os.O_WRONLY|os.O_NOFOLLOW,0o600,dir_fd=slot)
with os.fdopen(fd,'wb') as f:
info=os.fstat(f.fileno())
if not stat.S_ISREG(info.st_mode) or info.st_nlink!=1:fail('invalid receipt temporary file')
f.truncate(0);f.write(identity_json.encode());f.flush();os.fsync(f.fileno())
os.rename('current.tmp','current.json',src_dir_fd=slot,dst_dir_fd=slot);os.fsync(slot)
os.mkdir(identity['attemptId'],0o700,dir_fd=slot)
upload=os.open(identity['attemptId'],os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=slot)
try:
marker=os.open('owner.json',os.O_CREAT|os.O_EXCL|os.O_WRONLY|os.O_NOFOLLOW,0o600,dir_fd=upload)
with os.fdopen(marker,'wb') as f:f.write(identity_json.encode());f.flush();os.fsync(f.fileno())
finally:os.close(upload)
elif op=='cleanup':
cleanup(identity)
if current==identity:os.unlink('current.json',dir_fd=slot)
elif op in ('guard','publish'):
if current!=identity:fail('stale upload generation')
if op=='guard':sys.exit(subprocess.run(sys.argv[5:],stdin=sys.stdin,pass_fds=(lock,)).returncode)
upload=os.open(identity['attemptId'],os.O_RDONLY|os.O_DIRECTORY|os.O_NOFOLLOW,dir_fd=slot)
try:
if read('owner.json',upload)!=identity:fail('upload ownership mismatch')
libc=ctypes.CDLL(None,use_errno=True)
if hasattr(libc,'renameat2'):status=libc.renameat2(upload,b'pack',parent,os.fsencode(name),1)
elif hasattr(libc,'renameatx_np'):status=libc.renameatx_np(upload,b'pack',parent,os.fsencode(name),4)
else:fail('atomic publication unavailable')
if status!=0 and ctypes.get_errno() not in (errno.EEXIST,errno.ENOTEMPTY):raise OSError(ctypes.get_errno(),'cache publication failed')
finally:os.close(upload)
else:fail('unknown cache operation')
finally:os.close(parent)
`;
export async function prepareComputerProviderPackCache(input: {
cacheRoot: string;
sessionKey: string;
owner: { ownerId: string; generation: number };
runner: CommandManagedRuntimeRunner;
verify: (root: string) => Promise<void>;
stage: (root: string, runner: CommandManagedRuntimeRunner) => Promise<void>;
}): Promise<"reused" | "published"> {
const session = createHash("sha256").update(input.sessionKey).digest("hex");
const identity = { purpose: "paperclip-provider-pack-upload-v1", cacheRoot: input.cacheRoot, session,
attemptId: randomUUID(), ownerId: input.owner.ownerId, generation: input.owner.generation };
const args = (op: string) => ["-c", cacheProgram, op, input.cacheRoot, session, JSON.stringify(identity)];
const operation = async (op: string) => {
const result = await input.runner.execute({ command: "python3", args: args(op), bypassSession: true, timeoutMs: 180_000 });
if (result.exitCode !== 0 || result.timedOut) throw new Error(`runner_remote_provider_cache_${op}_failed`);
return result.stdout.trim();
};
const verifyShared = async () => {
try { await input.verify(input.cacheRoot); }
catch (cause) { throw new Error(`runner_remote_provider_cache_corrupt: ${input.cacheRoot}; stop tasks using this pack and have an operator remove or quarantine this exact cache directory before retrying`, { cause }); }
};
if (await operation("exists") === "true") {
await verifyShared();
await operation("reap");
return "reused";
}
const stagingRoot = posix.join(posix.dirname(input.cacheRoot), ".uploads", session, posix.basename(input.cacheRoot), identity.attemptId, "pack");
const guardedRunner: CommandManagedRuntimeRunner = {
execute: (command) => input.runner.execute({ ...command, command: "python3", args: [...args("guard"), command.command, ...(command.args ?? [])] }),
};
try {
await operation("begin");
await input.stage(stagingRoot, guardedRunner);
await input.verify(stagingRoot);
await operation("publish");
await verifyShared();
return "published";
} finally {
// The marker and attempt identity prevent a delayed cleanup from touching
// a successor, even when the same session retries under a new generation.
await operation("cleanup").catch(() => undefined);
}
}