Files
PaperClipAI/server/src/services/native-runtime/native-workspace-best-effort.ts
T
DottaandPaperclip 14795136f5 fix(runtime): finalize and recover sandbox workspace exports safely (#14402)
Serialize native workspace finalization, validate streamed archives within bounded limits, and quietly recover unsafe exports from saved results. Preserve exact allocations for exhausted transient failures and provide export-only retry without rerunning the provider.

Consolidates #14314, #14315, #14329, and #14334 while preserving the already-merged finalization label changes.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-28 10:57:32 -05:00

42 lines
1.8 KiB
TypeScript

import { eq } from "drizzle-orm";
import { heartbeatRuns, type Db } from "@paperclipai/db";
import { classifyWorkspaceRestoreFailure } from "@paperclipai/adapter-utils/workspace-restore-merge";
import { appendHeartbeatRunEvent } from "../heartbeat-run-events.js";
import { logger } from "../../middleware/logger.js";
/** An unsafe export cannot invalidate an already accepted agent result. */
export async function restoreNativeWorkspaceBestEffort<T>(input: {
db: Db;
runId: string;
restore: () => Promise<T>;
assertOwnership?: () => Promise<void>;
}): Promise<T | undefined> {
try {
return await input.restore();
} catch (error) {
// Losing finalization ownership must never open the workspace barrier.
await input.assertOwnership?.();
if (classifyWorkspaceRestoreFailure(error) !== "restore_unsafe_archive") throw error;
// The provider salvages confined archive entries when possible. A source
// that itself escapes the workspace cannot be exported at all. Both cases
// intentionally allow lost remote files: unsafe persistence must not fail
// an accepted task result. This diagnostic stays in run logs, never the task.
try {
const [run] = await input.db.select({ companyId: heartbeatRuns.companyId, agentId: heartbeatRuns.agentId })
.from(heartbeatRuns).where(eq(heartbeatRuns.id, input.runId)).limit(1);
if (run) await appendHeartbeatRunEvent(input.db, {
...run,
runId: input.runId,
eventType: "workspace_export_omitted",
stream: "system",
level: "info",
message: "Unsafe workspace export omitted; continuing with the accepted result.",
payload: { reason: "restore_unsafe_archive" },
});
} catch {
logger.info({ runId: input.runId }, "Unsafe workspace export omitted; run diagnostic could not be persisted");
}
return undefined;
}
}