// @generated by scripts/build-runtime.mjs; do not edit. // @ts-nocheck -- generated JavaScript uses a .ts extension for Pi's Jiti loader. import { agentDir, configuredSessionDir } from "./chunk-APZVBSM6.ts"; import { DEFAULT_SYNC_INCLUDE, canonicalSnapshotPathForConfig, customIncludePathsByLower, includeFromSelectionConfig, isConfiguredSnapshotPath, isDeniedPath, isPreservableUnmanagedSnapshotPath, normalizeExtraFiles, normalizeSyncFiles, posixJoin, safeJoin, selectionForSnapshot, snapshotSelectionInclude, syncIncludeSelection, toPosix } from "./chunk-YQ6UW7IF.ts"; // src/snapshot.ts import { createHash, randomUUID } from "node:crypto"; import fs from "node:fs/promises"; import os from "node:os"; import path2 from "node:path"; // src/snapshot-paths.ts import path from "node:path"; function expandHome(value) { if (value === "~") return process.env.HOME ?? value; if (value.startsWith("~/")) return path.join(process.env.HOME ?? "~", value.slice(2)); return value; } function sessionStorageRoot(root, configuredSessionDir2) { return configuredSessionDir2 ? path.resolve(expandHome(configuredSessionDir2)) : path.resolve(root, "sessions"); } // src/snapshot.ts var VERSION = 1; var TOP_LEVEL_FILES = DEFAULT_SYNC_INCLUDE.filter( (name) => name.includes(".") ); var TOP_LEVEL_DIRS = new Set(DEFAULT_SYNC_INCLUDE.filter((name) => !name.includes("."))); var SECRET_PATTERNS = [ /AWS_SECRET_ACCESS_KEY\s*[=:]\s*['"]?[A-Za-z0-9/+]{35,}/i, /(ANTHROPIC|OPENAI|GEMINI|GOOGLE|FIRECRAWL|GITHUB|CLOUDFLARE|R2|S3)_[A-Z0-9_]*(KEY|TOKEN|SECRET)\s*[=:]\s*['"]?[^\s'"]{12,}/i, /sk-ant-[A-Za-z0-9_-]{20,}/, /sk-[A-Za-z0-9]{20,}/, /gh[pousr]_[A-Za-z0-9_]{20,}/ ]; function selectTopLevelFileEntry(entries, fileName) { const exact = entries.find((entry) => entry.isFile() && entry.name === fileName); if (exact) return exact; const lower = fileName.toLowerCase(); return entries.filter((entry) => entry.isFile() && entry.name.toLowerCase() === lower).sort((left, right) => left.name.localeCompare(right.name))[0]; } function sha256(value) { return createHash("sha256").update(value).digest("hex"); } function isSafeSnapshotPath(relativePath) { if (relativePath.includes("\\")) return false; const normalized = toPosix(relativePath); return Boolean(normalized) && normalized !== "." && normalized !== ".." && !normalized.startsWith("../") && !path2.posix.isAbsolute(normalized) && path2.posix.normalize(normalized) === normalized && !isDeniedPath(normalized); } function snapshotsMatch(left, right) { const leftHashes = new Map(left.files.map((file) => [file.path, file.sha256])); const rightHashes = new Map(right.files.map((file) => [file.path, file.sha256])); return left.syncSessions === right.syncSessions && sameOptionalInclude(snapshotSelectionInclude(left), snapshotSelectionInclude(right)) && leftHashes.size === rightHashes.size && [...leftHashes].every(([filePath, hash]) => rightHashes.get(filePath) === hash); } function snapshotId() { return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${randomUUID().slice(0, 8)}`; } function regenerateSnapshotIdentity(snapshot) { return { ...snapshot, id: snapshotId(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), machine: os.hostname() }; } async function createSnapshot(profile, options = {}) { const include = effectiveInclude(options); const syncSessions = include.includes("sessions"); const files = await collectFiles(agentDir(), { include, sessionDir: options.sessionDir ?? await configuredSessionDir() }); return { version: VERSION, id: snapshotId(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), machine: os.hostname(), profile, syncSessions, selection: selectionForSnapshot(include), files }; } function effectiveInclude(options) { if (options.include) return options.include; return [ ...normalizeSyncFiles(options.syncFiles), ...normalizeExtraFiles(options.extraFiles), ...options.syncSessions ? ["sessions"] : [] ]; } async function collectFiles(root, options = {}) { const results = []; const entries = await fs.readdir(root, { withFileTypes: true }); const selection = syncIncludeSelection(effectiveInclude(options)); const selectedFiles = new Set(selection.builtIns); for (const entry of entries) { if (entry.isDirectory() && TOP_LEVEL_DIRS.has(entry.name) && selectedFiles.has(entry.name)) { await collectDirectory(results, root, entry.name); } } for (const fileName of TOP_LEVEL_FILES) { if (!selectedFiles.has(fileName)) continue; const entry = selectTopLevelFileEntry(entries, fileName); if (entry) await addFile(results, root, entry.name, fileName); } for (const relativePath of selection.custom) { await collectIncludedPath(results, root, relativePath); } if (selection.sessions) { try { await collectDirectory(results, sessionStorageRoot(root, options.sessionDir), "", { sessionsOnly: true, virtualPrefix: "sessions" }); } catch (error) { if (error.code !== "ENOENT") throw error; } } return results.sort((left, right) => left.path.localeCompare(right.path)); } async function collectIncludedPath(results, root, relativePath) { const absolutePath = safeJoin(root, relativePath); try { const stat = await fs.lstat(absolutePath); if (stat.isFile()) await addFile(results, root, relativePath); else if (stat.isDirectory()) await collectDirectory(results, root, relativePath); } catch (error) { if (error.code !== "ENOENT") throw error; if (!relativePath.includes("/")) { const entries = await fs.readdir(root, { withFileTypes: true }); const entry = selectTopLevelFileEntry(entries, relativePath); if (entry) await addFile(results, root, entry.name, relativePath); } } } async function collectDirectory(results, root, relativeDirectory, options = {}) { const absoluteDirectory = path2.join(root, relativeDirectory); for (const entry of await fs.readdir(absoluteDirectory, { withFileTypes: true })) { const relativePath = relativeDirectory ? posixJoin(relativeDirectory, entry.name) : entry.name; const snapshotPath = options.virtualPrefix ? posixJoin(options.virtualPrefix, relativePath) : relativePath; if (isDeniedPath(snapshotPath)) continue; if (entry.isDirectory()) { await collectDirectory(results, root, relativePath, options); } else if (entry.isFile() && (!options.sessionsOnly || isSessionFilePath(snapshotPath))) { await addFile(results, root, relativePath, snapshotPath); } } } async function addFile(results, root, relativePath, snapshotPath = relativePath) { if (!isSafeSnapshotPath(snapshotPath)) return; const absolutePath = safeJoin(root, relativePath); const content = await fs.readFile(absolutePath); results.push({ path: snapshotPath, contentBase64: content.toString("base64"), sha256: sha256(content) }); } function isSessionPath(relativePath) { return toPosix(relativePath).startsWith("sessions/"); } function isSessionFilePath(relativePath) { const normalized = toPosix(relativePath); return isSessionPath(normalized) && normalized.endsWith(".jsonl"); } function sessionSnapshotPathFromAbsolute(sessionFile, configuredSessionDir2) { const relativePath = toPosix( path2.relative(sessionStorageRoot(agentDir(), configuredSessionDir2), sessionFile) ); if (!relativePath || relativePath.startsWith("../") || path2.posix.isAbsolute(relativePath)) { return void 0; } const snapshotPath = posixJoin("sessions", relativePath); return isSessionFilePath(snapshotPath) ? snapshotPath : void 0; } function snapshotTarget(root, relativePath, configuredSessionDir2) { if (isSessionPath(relativePath)) { return safeJoin( sessionStorageRoot(root, configuredSessionDir2), relativePath.slice("sessions/".length) ); } return safeJoin(root, relativePath); } function snapshotIncludesSessions(snapshot) { return snapshot.syncSessions === true || snapshotSelectionInclude(snapshot)?.includes("sessions") === true || snapshot.files.some((file) => isSessionPath(file.path)); } function filterSnapshotForConfigPolicy(snapshot, config, options = {}) { const include = includeFromSelectionConfig(config); const includePaths = customIncludePathsByLower(include); const filtered = { ...snapshot, syncSessions: include.includes("sessions") ? snapshot.syncSessions : false, selection: selectionForSnapshot(include), files: canonicalizeSnapshotFilesForConfig(snapshot.files, config, includePaths) }; if (!options.regenerateId || snapshotsMatch(snapshot, filtered)) return filtered; return { ...filtered, id: snapshotId(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), machine: os.hostname() }; } function canonicalizeSnapshotFilesForConfig(files, config, includePaths) { const configuredFiles = []; const extraCandidates = /* @__PURE__ */ new Map(); for (const file of files) { const normalized = toPosix(file.path); if (!isSafeSnapshotPath(file.path) || !isConfiguredSnapshotPath(normalized, config)) { continue; } if (normalized.includes("/")) { configuredFiles.push(normalized === file.path ? file : { ...file, path: normalized }); continue; } const topLevelPath = canonicalSnapshotPathForConfig(normalized, includePaths); const candidate = { exact: normalized === topLevelPath, file: { ...file, path: topLevelPath }, originalPath: normalized }; const current = extraCandidates.get(topLevelPath.toLowerCase()); if (!current || isPreferredExtraCandidate(candidate, current)) { extraCandidates.set(topLevelPath.toLowerCase(), candidate); } } return [ ...configuredFiles, ...[...extraCandidates.values()].map((candidate) => candidate.file) ].sort((left, right) => left.path.localeCompare(right.path)); } function isPreferredExtraCandidate(left, right) { if (left.exact !== right.exact) return left.exact; return left.originalPath.localeCompare(right.originalPath) < 0; } function snapshotWithoutSessions(snapshot) { const files = snapshot.files.filter((file) => !isSessionPath(file.path)); const include = snapshotSelectionInclude(snapshot)?.filter((item) => item !== "sessions"); if (files.length === snapshot.files.length && snapshot.syncSessions !== true && include?.length === snapshot.selection?.include.length) { return snapshot; } return { ...snapshot, id: snapshotId(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), machine: os.hostname(), syncSessions: false, ...include ? { selection: selectionForSnapshot(include) } : {}, files }; } function scanSnapshot(snapshot) { const findings = []; for (const file of snapshot.files) { const content = Buffer.from(file.contentBase64, "base64"); if (content.includes(0)) continue; const text = content.toString("utf8"); for (const pattern of SECRET_PATTERNS) { if (pattern.test(text)) { findings.push(file.path); break; } } } return findings; } function mergeRemotePreservedFiles(local, remote, config) { const localPathNames = new Set(local.files.map((file) => file.path.toLowerCase())); const preservedPathNames = /* @__PURE__ */ new Set(); const preserved = remote.files.filter((file) => { const normalized = toPosix(file.path); const lower = normalized.toLowerCase(); if (localPathNames.has(lower) || preservedPathNames.has(lower) || !isSafeSnapshotPath(file.path) || isConfiguredSnapshotPath(normalized, config) || !isPreservableUnmanagedSnapshotPath(normalized)) { return false; } preservedPathNames.add(lower); return true; }); if (preserved.length === 0) return local; return { ...local, id: snapshotId(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), machine: os.hostname(), syncSessions: snapshotIncludesSessions(local) || snapshotIncludesSessions(remote), files: [...local.files, ...preserved].sort( (left, right) => left.path.localeCompare(right.path) ) }; } function mergeRemoteSessionFiles(local, remote) { const remoteSessions = remote.files.filter((file) => { const normalized = toPosix(file.path); return isSessionFilePath(normalized) && isSafeSnapshotPath(file.path); }); if (remoteSessions.length === 0 && !snapshotIncludesSessions(remote)) return local; const localInclude = snapshotSelectionInclude(local); return { ...local, id: snapshotId(), createdAt: (/* @__PURE__ */ new Date()).toISOString(), machine: os.hostname(), syncSessions: true, ...localInclude ? { selection: selectionForSnapshot( localInclude.includes("sessions") ? localInclude : [...localInclude, "sessions"] ) } : {}, files: [...local.files.filter((file) => !isSessionPath(file.path)), ...remoteSessions].sort( (left, right) => left.path.localeCompare(right.path) ) }; } function sameOptionalInclude(left, right) { if (!left || !right) return left === right; return left.length === right.length && left.every((item, index) => item === right[index]); } export { sessionStorageRoot, regenerateSnapshotIdentity, createSnapshot, collectFiles, isSessionPath, isSessionFilePath, sessionSnapshotPathFromAbsolute, snapshotTarget, snapshotIncludesSessions, filterSnapshotForConfigPolicy, snapshotWithoutSessions, scanSnapshot, mergeRemotePreservedFiles, mergeRemoteSessionFiles }; //# sourceMappingURL=chunk-EWX3TPLQ.ts.map