UNPKG

@openai/agents-core

Version:

The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows.

152 lines • 5.58 kB
import { constants } from 'node:fs'; import { lstat, open, readdir, realpath, rm } from 'node:fs/promises'; import { join, relative, sep } from 'node:path'; import { UserError } from "../../../errors.mjs"; import { isHostPathWithinRoot, relativeHostPathEscapesRoot, } from "../../shared/hostPath.mjs"; const SNAPSHOT_FILE_READ_FLAGS = constants.O_RDONLY | constants.O_NOFOLLOW; const SNAPSHOT_FILE_WRITE_FLAGS = constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | constants.O_NOFOLLOW; export async function clearDirectory(destinationRoot) { await assertSafeSnapshotDestinationPath(destinationRoot, destinationRoot); const entries = await readdir(destinationRoot); await Promise.all(entries.map(async (entry) => { await rm(join(destinationRoot, entry), { recursive: true, force: true }); })); } export function shouldSkipSnapshotPath(relativePath, excludedLogicalPaths) { for (const excluded of excludedLogicalPaths) { if (excluded === '' || relativePath === excluded || relativePath.startsWith(`${excluded}/`)) { return true; } } return false; } export async function readStableSnapshotDirectoryEntries(sourceRoot, expectedSourceStats) { const sourceStats = await lstat(sourceRoot); if (!sourceStats.isDirectory() || (expectedSourceStats && !sameFilesystemEntry(sourceStats, expectedSourceStats))) { throw snapshotPathChangedError(sourceRoot); } const entries = await readdir(sourceRoot, { withFileTypes: true }); await assertStableSnapshotDirectory(sourceRoot, sourceStats); return entries; } async function assertStableSnapshotDirectory(sourceRoot, expectedSourceStats) { const sourceStats = await lstat(sourceRoot); if (!sourceStats.isDirectory() || !sameFilesystemEntry(sourceStats, expectedSourceStats)) { throw snapshotPathChangedError(sourceRoot); } } export async function readStableSnapshotFile(sourcePath, expectedSourceStats) { const sourceStats = await lstat(sourcePath); if (!sourceStats.isFile() || !sameFilesystemEntry(sourceStats, expectedSourceStats)) { throw snapshotPathChangedError(sourcePath); } let handle; try { handle = await open(sourcePath, SNAPSHOT_FILE_READ_FLAGS); } catch (error) { if (isPathChangedError(error)) { throw snapshotPathChangedError(sourcePath); } throw error; } try { const openedStats = await handle.stat(); if (!openedStats.isFile() || !sameFilesystemEntry(openedStats, sourceStats)) { throw snapshotPathChangedError(sourcePath); } return await handle.readFile(); } finally { await handle.close(); } } export async function writeStableSnapshotFile(destinationRoot, destinationPath, content, mode) { await assertSafeSnapshotDestinationPath(destinationRoot, destinationPath); let handle; try { handle = await open(destinationPath, SNAPSHOT_FILE_WRITE_FLAGS, mode); } catch (error) { if (isPathChangedError(error)) { throw snapshotPathChangedError(destinationPath); } throw error; } try { await handle.writeFile(content); if (mode !== undefined) { await handle.chmod(mode); } } finally { await handle.close(); } await assertSafeSnapshotDestinationPath(destinationRoot, destinationPath); } export async function assertSafeSnapshotDestinationPath(destinationRoot, destinationPath) { const rootStats = await lstat(destinationRoot).catch(() => undefined); if (!rootStats?.isDirectory() || rootStats.isSymbolicLink()) { throw snapshotPathChangedError(destinationRoot); } const rootRealPath = await realpath(destinationRoot).catch(() => { throw snapshotPathChangedError(destinationRoot); }); const relativeDestination = relative(destinationRoot, destinationPath); if (relativeHostPathEscapesRoot(relativeDestination)) { throw snapshotPathChangedError(destinationPath); } if (relativeDestination === '') { return; } let current = destinationRoot; for (const segment of relativeDestination.split(sep)) { if (!segment) { continue; } current = join(current, segment); const currentStats = await lstat(current).catch((error) => { if (error.code === 'ENOENT') { return undefined; } throw error; }); if (!currentStats) { return; } if (currentStats.isSymbolicLink()) { throw snapshotPathChangedError(current); } const currentRealPath = await realpath(current).catch(() => { throw snapshotPathChangedError(current); }); if (!isHostPathWithinRoot(rootRealPath, currentRealPath)) { throw snapshotPathChangedError(current); } } } function snapshotPathChangedError(path) { return new UserError(`Sandbox snapshot path changed while copying: ${path}`); } function isPathChangedError(error) { return (typeof error === 'object' && error !== null && 'code' in error && (error.code === 'ELOOP' || error.code === 'ENOENT' || error.code === 'ENOTDIR')); } function sameFilesystemEntry(left, right) { return left.dev === right.dev && left.ino === right.ino; } //# sourceMappingURL=snapshotFilesystem.mjs.map