Merge master b189f586d into Codex runner default candidate

Preserve master transport, lifecycle, and release verification controls alongside macOS qualification.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-12 07:55:09 -05:00
commit f4abdc2cfc
749 files changed
+124181 -68418

No files matched your search

@@ -1,5 +1,7 @@
import { configuredEnvironment } from "../../vendor/paperclip-runner/index.js";
import { apiKeyBillingType } from "@paperclipai/adapter-utils/api-billing-type";
import { agents } from "@paperclipai/db";
import { isCloudManagedInstance } from "../cloud-instance.js";
import { dotRunnerBroker } from "../dot-runner-broker.js";
import { CURSOR_DISTRIBUTION_PINS, QUALIFIED_ACPX_PROFILES, QUALIFIED_ACPX_VERSION } from "../../vendor/paperclip-runner/index.js";
import { isProviderMode } from "../../vendor/paperclip-runner/index.js";
@@ -6187,6 +6189,7 @@ export function nativeSessionFailureDisposition(
sourceFailureCode?: ReturnType<typeof nativeSessionFailureSourceCode>,
) {
const permanentFailure =
sourceFailureCode === "native_provider_runtime_missing" ||
sourceFailureCode === "native_provider_model_rejected" ||
sourceFailureCode === "native_provider_approval_required" ||
sourceFailureCode === "native_event_replay_conflict" ||
@@ -6260,6 +6263,7 @@ export function nativeSessionFailureSourceCode(
| "native_runner_process_exited"
| "planning_mode_unsupported"
| "native_event_replay_conflict"
| "native_provider_runtime_missing"
| "native_provider_model_rejected"
| "native_current_wake_comments_unread"
| "native_current_wake_comments_changed_after_read"
@@ -6282,6 +6286,8 @@ export function nativeSessionFailureSourceCode(
if (error instanceof NativeSessionCleanupQuarantinedError)
return "native_session_cleanup_quarantined";
const message = error instanceof Error ? error.message : String(error);
if (/classification=runtime_package_missing\)/.test(message))
return "native_provider_runtime_missing";
if (/native_provider_model_rejected/i.test(message))
return "native_provider_model_rejected";
if (/native_adopted_runner_authentication_timeout/i.test(message)) {
@@ -7525,6 +7531,11 @@ export async function executePaperclipNativeSession(input: {
await retireSupersededWarmNativeSessions(
ownerScope, nativeSessionScopeKey(input.execution),
);
if (input.execution.provider.kind === "openai_dot" && isCloudManagedInstance()
&& (!input.useRunnerd || input.runnerExecutionTarget?.kind !== "remote"
|| input.runnerExecutionTarget.transport !== "sandbox")) {
throw new Error("dot_cloud_requires_managed_runner");
}
if (!input.useRunnerd) {
return await executePaperclipNativeSessionWithinScope(input);
}
@@ -7546,7 +7557,6 @@ export async function executePaperclipNativeSession(input: {
await closingWarmNativeSessions.get(sessionScopeId);
if (input.execution.provider.kind === "openai_dot") {
if (input.runnerExecutionTarget?.kind === "remote") throw new Error("dot_requires_local_runner_controller");
return await executePaperclipNativeSessionWithinScope(input);
}
const workspaceRoot = input.execution.workspace.cwd;
@@ -8532,7 +8542,7 @@ async function executePaperclipNativeSessionWithinScope(
: []),
),
eq(issueThreadInteractions.status, "pending"),
activeIssueInteractionCondition(),
activeIssueInteractionCondition({ runId: input.execution.binding.runId }),
// Live provider questions resume their current turn; only durable
// wake-based cards park it. A timeout creates a separate fallback.
sql`not (${issueThreadInteractions.kind} = 'ask_user_questions' and ${issueThreadInteractions.continuationPolicy} = 'none' and coalesce(${issueThreadInteractions.idempotencyKey}, '') like 'paperclip-runner-question:%')`,
@@ -9784,11 +9794,15 @@ export function resolveNativeBilling(provider: NativeExecutionInput["provider"],
const parts = (provider.model ?? "").split("/");
const biller = parts.length > 1 ? parts[0] : provider.kind === "acpx" ? nativeUsageBiller(provider) : "unknown";
const modelProvider = biller === "openrouter" && parts.length > 2 ? parts[1] : biller;
return { provider: modelProvider, biller, billingType: "unknown" };
const billingType = apiKeyBillingType(biller, env);
const effectiveBiller = biller === "openai" && billingType === "metered_api"
? inferOpenAiCompatibleBiller(env, "openai") ?? "unknown" : biller;
return { provider: modelProvider, biller: effectiveBiller, billingType };
}
if (provider.kind !== "codex" && !(provider.kind === "acpx" && provider.agent === "codex"))
return { provider: "unknown", biller: "unknown", billingType: "unknown" };
return { provider: "openai", biller: env.OPENAI_API_KEY ? inferOpenAiCompatibleBiller(env, "openai") : "unknown", billingType: env.OPENAI_API_KEY ? "metered_api" : "unknown" };
const billingType = apiKeyBillingType("openai", env, "codex");
return { provider: "openai", biller: billingType === "metered_api" ? inferOpenAiCompatibleBiller(env, "openai") : "unknown", billingType };
}
export function normalizeNativeUsage(usage: Record<string, unknown> | null, options: { inputIncludesCacheReads?: boolean } = {}) {
@@ -10131,6 +10145,7 @@ function readRemoteProviderPackIdentity(packRoot: string, verifyControllerFiles:
export function assertRemoteRunnerBuildMetadata(
value: unknown,
requiredMode: "dial_wss" | "listen_ws",
requiredExternalProvider?: "openai_dot_mcp",
): void {
if (!value || typeof value !== "object" || Array.isArray(value)) {
throw new Error("runner_remote_artifact_metadata_invalid");
@@ -10147,6 +10162,10 @@ export function assertRemoteRunnerBuildMetadata(
// Older sandbox images share binary contract v2, but reject the zero
// lifetime now used by the controller and cannot renew connection leases.
// Reject them before launch so preparation stages the bundled runner instead.
if (requiredExternalProvider && (!Array.isArray(metadata.externalProviderCapabilities)
|| !metadata.externalProviderCapabilities.includes(requiredExternalProvider))) {
throw new Error("runner_remote_dot_capability_missing: install the current Paperclip Runner artifact");
}
const sessionCapabilities = Array.isArray(metadata.durableSessionCapabilities)
? metadata.durableSessionCapabilities
: [];
@@ -10762,7 +10781,8 @@ async function waitForRemoteRunnerProcessIdentity(input: {
identityPath: string;
nonce: string;
runnerInstanceId: string;
}): Promise<{ pid: number; startedAt: string }> {
requireProcessStartFingerprint?: boolean;
}): Promise<{ pid: number; startedAt: string; processStartFingerprint?: string }> {
const deadline = Date.now() + REMOTE_RUNNER_PROCESS_IDENTITY_WAIT_MS;
while (Date.now() < deadline) {
const result = await input.runner
@@ -10782,7 +10802,7 @@ async function waitForRemoteRunnerProcessIdentity(input: {
result && result.exitCode === 0 && !result.timedOut
? parseRemoteRunnerProcessIdentity(result.stdout, input)
: null;
if (identity) return identity;
if (identity && (!input.requireProcessStartFingerprint || identity.processStartFingerprint)) return identity;
await new Promise<void>((resolve) => setTimeout(resolve, 100));
}
throw new Error("runner_remote_process_identity_unavailable");
@@ -10821,6 +10841,7 @@ export function createRemoteRunnerProcessLauncher(input: {
diagnosticsDirectory: string;
runnerInstanceId: string;
ensureArtifact?: () => Promise<void>;
requireProcessStartFingerprint?: boolean;
onSpawn?: (meta: {
pid: number;
processGroupId: number | null;
@@ -10956,6 +10977,7 @@ export function createRemoteRunnerProcessLauncher(input: {
identityPath: input.processIdentityPath,
nonce: identityNonce,
runnerInstanceId: input.runnerInstanceId,
requireProcessStartFingerprint: input.requireProcessStartFingerprint,
});
} catch {
const cleanupStartedAtMs = Date.now();
@@ -11196,6 +11218,129 @@ export async function createRunnerdBackend(input: {
}
}
/** Dot uses the same managed process launcher and authenticated PRP transports.
* Its execution contract still exposes no workspace, shell, or provider secrets. */
async function prepareRemoteDotRunner({ input, target, runner, root, identity }: {
input: Parameters<typeof createRunnerdBackend>[0];
target: Extract<AdapterExecutionTarget, { kind: "remote" }>;
runner: CommandManagedRuntimeRunner;
root: string;
identity: NonNullable<NonNullable<Parameters<typeof createNativeSessionBackend>[1]>["dotRunnerOptions"]>["identity"];
}) {
const runnerBinary = input.runnerRemoteBinaryPath?.trim() || resolvePaperclipRunnerBinary();
const remoteRoot = posix.join(target.remoteCwd, ".paperclip-runtime", "paperclip-runner");
const remoteBinary = posix.join(remoteRoot, "bin", "paperclip-runnerd");
const runnerStateDirectory = posix.join(remoteRoot, "sessions",
createHash("sha256").update(identity.normalizedSessionId).digest("hex"), "runner");
const requiredMode = resolveRemoteRunnerTransportMode({ target, runnerIngressAuthorized: input.runnerIngressAuthorized === true });
const artifact = readRunnerdArtifactBinding(runnerBinary);
const prepare = async () => {
if (input.restartRecovery?.kind !== "reattach_remote_runner") {
if (!input.runnerRemoteBinaryPath?.trim()) {
const platform = await runner.execute({ command: "sh", args: ["-c", "uname -s; uname -m"], bypassSession: true, timeoutMs: 10000 });
const [os, arch] = platform.stdout.trim().split(/\r?\n/);
if (platform.exitCode !== 0 || platform.timedOut || os !== (process.platform === "darwin" ? "Darwin" : "Linux")
|| ![process.arch === "x64" ? "x86_64" : "aarch64", process.arch].includes(arch)) {
throw new Error("runner_remote_artifact_platform_mismatch: configure PAPERCLIP_RUNNER_REMOTE_BINARY_PATH for the sandbox platform");
}
}
await stageRemoteRunnerFile({ target, runner, sourcePath: runnerBinary, targetPath: remoteBinary, mode: 0o700 });
}
const metadata = await runner.execute({ command: remoteBinary, args: ["--build-metadata"], bypassSession: true, timeoutMs: 30000 });
if (metadata.exitCode !== 0 || metadata.timedOut) throw new Error("runner_remote_artifact_verification_failed");
assertRemoteRunnerBuildMetadata(JSON.parse(metadata.stdout), requiredMode, "openai_dot_mcp");
const checksum = await runner.execute({ command: "sh", args: ["-c",
'if command -v sha256sum >/dev/null 2>&1; then sha256sum "$1"; else shasum -a 256 "$1"; fi', "paperclip-dot-artifact", remoteBinary],
bypassSession: true, timeoutMs: 10000 });
if (checksum.exitCode !== 0 || checksum.timedOut || `sha256:${checksum.stdout.trim().split(/\s+/)[0]}` !== artifact.digest) {
throw new Error("runner_remote_artifact_verification_failed");
}
};
const readProviderState = async () => {
const result = await runner.execute({ command: "sh", args: ["-c",
'set -eu; if test ! -e "$1" && test ! -L "$1"; then exit 3; fi; test -f "$1" && test ! -L "$1"; test "$(wc -c < "$1")" -le 33554432; base64 < "$1"',
"paperclip-dot-checkpoint", posix.join(runnerStateDirectory, "dot-provider-state.json")], bypassSession: true, timeoutMs: 10000 });
if (result.exitCode === 3 && !result.timedOut) return null;
if (result.exitCode !== 0 || result.timedOut) throw new Error("dot_provider_checkpoint_unavailable");
const state = record(JSON.parse(Buffer.from(result.stdout.replace(/\s+/g, ""), "base64").toString("utf8")));
if (state.schema !== "paperclip.runner.dot-provider-state.v1" || state.runId !== identity.runId
|| state.sessionId !== identity.normalizedSessionId || state.turnId !== identity.turnId) throw new Error("dot_runner_checkpoint_authority_mismatch");
// Retain inspectable recovery evidence on the controller without changing
// which execution target is authoritative for replay.
mkdirSync(join(root, "runner"), { recursive: true, mode: 0o700 });
const saved = join(root, "runner", "dot-provider-state.json");
const temporary = `${saved}.${randomUUID()}.tmp`;
writeFileSync(temporary, JSON.stringify(state), { mode: 0o600 });
renameSync(temporary, saved);
return state;
};
let spawned: () => void = () => {};
const processStarted = new Promise<void>(resolve => { spawned = resolve; });
// A transport handshake alone does not prove a recoverable process owner.
// Do not attach the Dot broker until the exact sandbox marker is validated.
let identityReady: () => void = () => {};
let identityFailed: (error: unknown) => void = () => {};
const processIdentityReady = new Promise<void>((resolve, reject) => { identityReady = resolve; identityFailed = reject; });
void processIdentityReady.catch(() => {});
const adoptExistingRunner = input.restartRecovery?.kind === "reattach_remote_runner"
? await verifyRemoteRunnerReattachment({ claim: input.restartRecovery, target, identity: { ...identity },
runId: input.execution.binding.runId, normalizedSessionId: nativeSessionKey(input.execution) }) : undefined;
if (adoptExistingRunner) { spawned(); identityReady(); }
const launch = createRemoteRunnerProcessLauncher({ target, runner, remoteBinary,
processIdentityPath: posix.join(runnerStateDirectory, "runner-process.identity"), stateDirectory: runnerStateDirectory,
diagnosticsDirectory: posix.join(remoteRoot, "diagnostics"), runnerInstanceId: input.runnerInstanceId,
requireProcessStartFingerprint: true,
onSpawn: async meta => { await input.onSpawn?.(meta); identityReady(); },
onLog: input.onLog, trace: input.trace, onRunnerProcessSpawned: () => spawned() });
const runnerProcessLauncher: typeof launch = spec => {
const handle = launch(spec);
void handle.completion.then(() => identityFailed(new Error("runner_remote_process_identity_unavailable")), identityFailed);
return handle;
};
const controlPlaneRegistration: NonNullable<NonNullable<NonNullable<Parameters<typeof createNativeSessionBackend>[1]>["dotRunnerOptions"]>["controlPlaneRegistration"]> = async authority => {
let transport: PaperclipRunnerTransport;
// Validate outbound URL before staging; provider ingress needs the staged
// listener binary before requesting the provider's private endpoint.
if (requiredMode === "dial_wss") {
transport = await resolvePaperclipRunnerTransport({ target, runId: input.execution.binding.runId,
localConnectUrl: "ws://127.0.0.1/unused", runnerPublicUrl: input.runnerPublicUrl,
runnerCaBundlePath: input.runnerCaBundlePath, runnerIngressAuthorized: input.runnerIngressAuthorized === true });
await prepare();
} else {
await prepare();
transport = await resolvePaperclipRunnerTransport({ target, runId: input.execution.binding.runId,
localConnectUrl: "ws://127.0.0.1/unused", runnerIngressAuthorized: input.runnerIngressAuthorized === true });
}
await input.onLog?.("stderr", `[paperclip-runner] Dot controller target=remote transport=${transport.mode}\n`);
if (transport.mode !== "provider_ingress") {
const registration = await registerRunnerPrpAuthority({ companyId: input.execution.binding.companyId,
issueId: input.execution.binding.issueId, agentId: input.execution.binding.agentId,
runId: input.execution.binding.runId, authority });
let caBundlePath = transport.mode === "direct_outbound" ? transport.caBundlePath : undefined;
if (caBundlePath) {
const remoteCaBundlePath = posix.join(remoteRoot, "bin", "runner-ca-bundle.pem");
await stageRemoteRunnerFile({ target, runner, sourcePath: caBundlePath, targetPath: remoteCaBundlePath, mode: 0o600 });
caBundlePath = remoteCaBundlePath;
}
return { ...registration, ready: async () => { await processIdentityReady; }, connection: { mode: "connect" as const, connectUrl: transport.connectUrl,
...(caBundlePath ? { caBundlePath } : {}) } };
}
let outbound: ReturnType<typeof connectRunnerPrpIngress> | null = null;
let activation: Promise<void> | null = null;
return { connection: { mode: "listen" as const, listenAddress: transport.listenAddress,
listenPort: transport.listenPort, listenPath: transport.listenPath },
activate: () => { activation = (async () => { await processStarted;
outbound = connectRunnerPrpIngress({ authority, endpoint: transport.ingress }); })();
void activation.catch(() => {}); },
ready: async () => { await activation; if (!outbound) throw new Error("runner_ingress_unavailable"); await outbound.ready; await processIdentityReady; },
get failure() { return outbound?.failure; },
startupFailureCode: "runner_ingress_unavailable" as const,
release: async () => { if (outbound) await outbound.close(); else await transport.ingress.close(); },
};
};
return { runnerBinary, runnerStateDirectory, runnerProcessLauncher, readProviderState, controlPlaneRegistration, adoptExistingRunner };
}
async function createRunnerdBackendWithinSessionClaim(
input: Parameters<typeof createRunnerdBackend>[0],
sessionScopeId: string,
@@ -11321,24 +11466,31 @@ async function createRunnerdBackendWithinSessionClaim(
input.execution.binding.executionWorkspaceId;
mkdirSync(root, { recursive: true, mode: 0o700 });
if (input.execution.schema === "paperclip.native-execution-input.v6") {
if (target.kind !== "local") throw new Error("dot_runner_requires_local_controller: Dot has no mounted workspace or sandbox process");
if (target.kind === "remote" && input.dotWorkspaceRoot) throw new Error("dot_remote_workspace_access_unavailable");
const remoteDot = target.kind === "remote"
? await prepareRemoteDotRunner({ input, target, runner: remoteCommandRunner!, root,
identity: { runnerInstanceId: effectiveRunnerInstanceId, environmentLeaseId: effectiveEnvironmentLeaseId,
runId: input.execution.binding.runId, normalizedSessionId: nativeSessionKey(input.execution),
turnId: `turn-${input.execution.binding.runId}`, itemId: `item-${input.execution.binding.runId}` } })
: null;
const recoveredProcess = input.restartRecovery?.kind === "reattach_existing_runner" ? input.restartRecovery.process : null;
const backend = createNativeSessionBackend(input.execution, {
onSpawn: input.onSpawn, dynamicTools,
dynamicToolHandler: async call => { await dotRunnerBroker(input.db).assertRunAuthority(input.execution as import("../../vendor/paperclip-runner/index.js").NativeExecutionInputV6); return authorityEpoch.execute(call); },
completionFeedback: async result => { await dotRunnerBroker(input.db).assertRunAuthority(input.execution as import("../../vendor/paperclip-runner/index.js").NativeExecutionInputV6); await authorityEpoch.definitions(); return nativeCompletionFeedback(input.db, input.execution.binding.runId, result); },
dotRunnerOptions: {
stateDirectory: root, runnerBinary: resolvePaperclipRunnerBinary(),
stateDirectory: root, runnerBinary: remoteDot?.runnerBinary ?? resolvePaperclipRunnerBinary(),
...(remoteDot ?? {}),
identity: { runnerInstanceId: effectiveRunnerInstanceId, environmentLeaseId: effectiveEnvironmentLeaseId,
runId: input.execution.binding.runId, normalizedSessionId: nativeSessionKey(input.execution),
turnId: `turn-${input.execution.binding.runId}`, itemId: `item-${input.execution.binding.runId}` },
port: dotRunnerBroker(input.db).port(input.execution),
controlPlaneRegistration: async authority => registerRunnerPrpAuthority({ companyId: input.execution.binding.companyId,
controlPlaneRegistration: remoteDot?.controlPlaneRegistration ?? (async authority => registerRunnerPrpAuthority({ companyId: input.execution.binding.companyId,
issueId: input.execution.binding.issueId, agentId: input.execution.binding.agentId,
runId: input.execution.binding.runId, authority }),
adoptExistingRunner: recoveredProcess ? { ...recoveredProcess,
runId: input.execution.binding.runId, authority })),
adoptExistingRunner: remoteDot?.adoptExistingRunner ?? (recoveredProcess ? { ...recoveredProcess,
isAlive: () => verifiedRecoveryProcessIsAlive(recoveredProcess),
signal: signal => signalVerifiedRecoveryProcess(recoveredProcess, signal) } : undefined,
signal: signal => signalVerifiedRecoveryProcess(recoveredProcess, signal) } : undefined),
},
});
const prior = sessionToolAuthorityEpochs.get(sessionScopeId); if (prior) prior.revoke();
@@ -11368,9 +11520,10 @@ async function createRunnerdBackendWithinSessionClaim(
const configuredProviderPackRoot =
input.runnerRemoteProviderPackPath?.trim() || remotePiCompanion?.providerPack || null;
let expectedProviderPackManifest: RemoteProviderPackManifest | null = null;
const useBundledCursorImageAssets = requiresRemoteProviderPack && !configuredProviderPackRoot &&
input.execution.provider.kind === "acpx" && input.execution.provider.agent === "cursor";
if (useBundledCursorImageAssets) {
const useBundledRemoteImageAssets = requiresRemoteProviderPack && !configuredProviderPackRoot &&
(input.execution.provider.kind === "opencode" ||
(input.execution.provider.kind === "acpx" && input.execution.provider.agent === "cursor"));
if (useBundledRemoteImageAssets) {
expectedProviderPackManifest = readBundledRemoteProviderPackManifest();
} else if (requiresRemoteProviderPack) {
if (
@@ -11399,7 +11552,7 @@ async function createRunnerdBackendWithinSessionClaim(
// When an explicit remote artifact is configured, prepareRemoteRunner stages
// these exact bytes at remoteBinary before launch.
const controllerRunnerBinary = remoteTarget
? input.runnerRemoteBinaryPath?.trim() || remotePiCompanion?.runnerBinary || (useBundledCursorImageAssets ? bundledRemoteRunnerBinary() : resolvePaperclipRunnerBinary())
? input.runnerRemoteBinaryPath?.trim() || remotePiCompanion?.runnerBinary || (useBundledRemoteImageAssets ? bundledRemoteRunnerBinary() : resolvePaperclipRunnerBinary())
: resolvePaperclipRunnerBinary();
const explicitRemoteCodex = input.runnerRemoteCodexPath?.trim() || null;
const remoteCodexNpmSpec = input.runnerRemoteCodexNpmSpec?.trim() || null;
@@ -11579,7 +11732,7 @@ async function createRunnerdBackendWithinSessionClaim(
remoteRuntimeRoot, remoteCodexBinary, runnerRemoteBinaryPath: input.runnerRemoteBinaryPath,
runnerRemoteCodexPath: input.runnerRemoteCodexPath, runnerRemoteCodexNpmSpec: input.runnerRemoteCodexNpmSpec,
model: input.execution.provider.kind === "codex" ? input.execution.provider.model : null,
reuseRetainedRunner: sandboxLeaseAcquisition?.outcome === "resumed", targetPlatformArtifactVerified: remotePiCompanion !== null,
reuseRetainedRunner: sandboxLeaseAcquisition?.outcome === "resumed", targetPlatformArtifactVerified: remotePiCompanion !== null || useBundledRemoteImageAssets,
trace: input.trace, onLog: input.onLog,
})
: null;
@@ -13246,7 +13399,7 @@ export function createRemoteNativeArtifactPreparation(input: {
runnerRemoteCodexNpmSpec?: string | null;
model?: string | null;
reuseRetainedRunner?: boolean;
/** Existing operator-imported Pi companion already verifies its target-platform artifact. */
/** The selected Pi companion or bundled provider image verifies its target-platform artifact. */
targetPlatformArtifactVerified?: boolean;
trace?: NativeRunTrace;
onLog?: (stream: "stdout" | "stderr", chunk: string) => Promise<void>;