UNPKG

@openai/agents-core

Version:

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

160 lines • 6.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearDirectory = clearDirectory; exports.shouldSkipSnapshotPath = shouldSkipSnapshotPath; exports.readStableSnapshotDirectoryEntries = readStableSnapshotDirectoryEntries; exports.readStableSnapshotFile = readStableSnapshotFile; exports.writeStableSnapshotFile = writeStableSnapshotFile; exports.assertSafeSnapshotDestinationPath = assertSafeSnapshotDestinationPath; const node_fs_1 = require("node:fs"); const promises_1 = require("node:fs/promises"); const node_path_1 = require("node:path"); const errors_1 = require("../../../errors.js"); const hostPath_1 = require("../../shared/hostPath.js"); const SNAPSHOT_FILE_READ_FLAGS = node_fs_1.constants.O_RDONLY | node_fs_1.constants.O_NOFOLLOW; const SNAPSHOT_FILE_WRITE_FLAGS = node_fs_1.constants.O_WRONLY | node_fs_1.constants.O_CREAT | node_fs_1.constants.O_TRUNC | node_fs_1.constants.O_NOFOLLOW; async function clearDirectory(destinationRoot) { await assertSafeSnapshotDestinationPath(destinationRoot, destinationRoot); const entries = await (0, promises_1.readdir)(destinationRoot); await Promise.all(entries.map(async (entry) => { await (0, promises_1.rm)((0, node_path_1.join)(destinationRoot, entry), { recursive: true, force: true }); })); } function shouldSkipSnapshotPath(relativePath, excludedLogicalPaths) { for (const excluded of excludedLogicalPaths) { if (excluded === '' || relativePath === excluded || relativePath.startsWith(`${excluded}/`)) { return true; } } return false; } async function readStableSnapshotDirectoryEntries(sourceRoot, expectedSourceStats) { const sourceStats = await (0, promises_1.lstat)(sourceRoot); if (!sourceStats.isDirectory() || (expectedSourceStats && !sameFilesystemEntry(sourceStats, expectedSourceStats))) { throw snapshotPathChangedError(sourceRoot); } const entries = await (0, promises_1.readdir)(sourceRoot, { withFileTypes: true }); await assertStableSnapshotDirectory(sourceRoot, sourceStats); return entries; } async function assertStableSnapshotDirectory(sourceRoot, expectedSourceStats) { const sourceStats = await (0, promises_1.lstat)(sourceRoot); if (!sourceStats.isDirectory() || !sameFilesystemEntry(sourceStats, expectedSourceStats)) { throw snapshotPathChangedError(sourceRoot); } } async function readStableSnapshotFile(sourcePath, expectedSourceStats) { const sourceStats = await (0, promises_1.lstat)(sourcePath); if (!sourceStats.isFile() || !sameFilesystemEntry(sourceStats, expectedSourceStats)) { throw snapshotPathChangedError(sourcePath); } let handle; try { handle = await (0, promises_1.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(); } } async function writeStableSnapshotFile(destinationRoot, destinationPath, content, mode) { await assertSafeSnapshotDestinationPath(destinationRoot, destinationPath); let handle; try { handle = await (0, promises_1.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); } async function assertSafeSnapshotDestinationPath(destinationRoot, destinationPath) { const rootStats = await (0, promises_1.lstat)(destinationRoot).catch(() => undefined); if (!rootStats?.isDirectory() || rootStats.isSymbolicLink()) { throw snapshotPathChangedError(destinationRoot); } const rootRealPath = await (0, promises_1.realpath)(destinationRoot).catch(() => { throw snapshotPathChangedError(destinationRoot); }); const relativeDestination = (0, node_path_1.relative)(destinationRoot, destinationPath); if ((0, hostPath_1.relativeHostPathEscapesRoot)(relativeDestination)) { throw snapshotPathChangedError(destinationPath); } if (relativeDestination === '') { return; } let current = destinationRoot; for (const segment of relativeDestination.split(node_path_1.sep)) { if (!segment) { continue; } current = (0, node_path_1.join)(current, segment); const currentStats = await (0, promises_1.lstat)(current).catch((error) => { if (error.code === 'ENOENT') { return undefined; } throw error; }); if (!currentStats) { return; } if (currentStats.isSymbolicLink()) { throw snapshotPathChangedError(current); } const currentRealPath = await (0, promises_1.realpath)(current).catch(() => { throw snapshotPathChangedError(current); }); if (!(0, hostPath_1.isHostPathWithinRoot)(rootRealPath, currentRealPath)) { throw snapshotPathChangedError(current); } } } function snapshotPathChangedError(path) { return new errors_1.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.js.map