mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-25 17:45:53 +01:00
Introduce company-scoped task, agent, user and project files, recoverable trash, object-backed repository checkpoints, and a shared 180-second lifecycle for sandbox execution. Wire file browsing and save status into the owner surfaces. This is an implementation checkpoint; staging acceptance and the complete merge gate remain outstanding.
64 lines
1.8 KiB
TypeScript
64 lines
1.8 KiB
TypeScript
/** Durable Paperclip files; CLI homes and caches are deliberately not scopes. */
|
|
export const WORK_FOLDER_SCOPES = ["task", "agent", "user", "project"] as const;
|
|
export type WorkFolderScope = (typeof WORK_FOLDER_SCOPES)[number];
|
|
export const WORK_FOLDER_SYNC_INTERVAL_MS = 180_000;
|
|
|
|
export interface WorkFolderOwner {
|
|
companyId: string;
|
|
scope: WorkFolderScope;
|
|
ownerId: string;
|
|
}
|
|
|
|
export interface WorkFile {
|
|
id: string;
|
|
path: string;
|
|
kind: "file" | "directory";
|
|
byteSize: number;
|
|
sha256: string | null;
|
|
executable: boolean;
|
|
contentType: string;
|
|
deletedAt: string | null;
|
|
updatedAt: string;
|
|
}
|
|
|
|
export interface WorkFolderListing {
|
|
id: string;
|
|
owner: WorkFolderOwner;
|
|
files: WorkFile[];
|
|
nextCursor: string | null;
|
|
}
|
|
|
|
export interface WorkFolderSyncStatus {
|
|
runId: string;
|
|
state: "starting" | "saved" | "saving" | "failed";
|
|
lastSavedAt: string | null;
|
|
error: string | null;
|
|
refreshRequested: boolean;
|
|
active: boolean;
|
|
}
|
|
|
|
export interface SandboxWorkFolderManifest {
|
|
version: 1;
|
|
companyId: string;
|
|
runId: string;
|
|
taskId: string | null;
|
|
agentId: string;
|
|
responsibleUserId: string | null;
|
|
projectId: string | null;
|
|
leaseId: string;
|
|
sandboxKey: string;
|
|
home: string;
|
|
finalCheckpointAt?: string;
|
|
folders: Record<WorkFolderScope, string | null>;
|
|
repositories: Array<{ bindingId: string; workspaceId: string; name: string; primary: boolean }>;
|
|
}
|
|
|
|
/** Reject ambiguous paths instead of normalizing traversal into a valid path. */
|
|
export function validateWorkFilePath(value: string): string {
|
|
if (!value || value.length > 1024 || /[\\\x00-\x1f\x7f]/.test(value)
|
|
|| value.split("/").some((part) => !part || part === "." || part === ".." || part === ".paperclip-runtime")) {
|
|
throw new Error("Invalid work file path");
|
|
}
|
|
return value;
|
|
}
|