deepagentsdk 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/elements/index.cjs +478 -288
- package/dist/adapters/elements/index.cjs.map +1 -1
- package/dist/adapters/elements/index.d.cts +107 -172
- package/dist/adapters/elements/index.d.mts +107 -172
- package/dist/adapters/elements/index.mjs +471 -284
- package/dist/adapters/elements/index.mjs.map +1 -1
- package/dist/{types-4g9UvXal.d.mts → agent-D0bKkNI-.d.mts} +352 -3
- package/dist/{types-IulnvhFg.d.cts → agent-DwAj5emJ.d.cts} +352 -3
- package/dist/{chunk-CbDLau6x.cjs → chunk-C5azi7Hr.cjs} +33 -0
- package/dist/cli/index.cjs +12 -12
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.mjs +2 -2
- package/dist/cli/index.mjs.map +1 -1
- package/dist/{agent-Cuks-Idh.cjs → file-saver-BYPKakT4.cjs} +799 -205
- package/dist/file-saver-BYPKakT4.cjs.map +1 -0
- package/dist/{agent-CrH-He58.mjs → file-saver-Hj5so3dV.mjs} +793 -199
- package/dist/file-saver-Hj5so3dV.mjs.map +1 -0
- package/dist/index.cjs +83 -73
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -353
- package/dist/index.d.mts +5 -353
- package/dist/index.mjs +13 -3
- package/dist/index.mjs.map +1 -1
- package/dist/{load-B6CA5js_.mjs → load-BBYEnMwz.mjs} +1 -1
- package/dist/{load-B6CA5js_.mjs.map → load-BBYEnMwz.mjs.map} +1 -1
- package/dist/{load-94gjHorc.mjs → load-BDxe6Cet.mjs} +1 -1
- package/dist/{load-79a2H4m0.cjs → load-BrRAKlO6.cjs} +2 -2
- package/dist/{load-79a2H4m0.cjs.map → load-BrRAKlO6.cjs.map} +1 -1
- package/dist/load-DqllBbDc.cjs +4 -0
- package/package.json +1 -1
- package/dist/agent-CrH-He58.mjs.map +0 -1
- package/dist/agent-Cuks-Idh.cjs.map +0 -1
- package/dist/file-saver-BJCqMIb5.mjs +0 -655
- package/dist/file-saver-BJCqMIb5.mjs.map +0 -1
- package/dist/file-saver-C6O2LAvg.cjs +0 -679
- package/dist/file-saver-C6O2LAvg.cjs.map +0 -1
- package/dist/load-C2qVmZMp.cjs +0 -3
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"file-saver-BJCqMIb5.mjs","names":[],"sources":["../src/backends/sandbox.ts","../src/backends/local-sandbox.ts","../src/utils/model-parser.ts","../src/checkpointer/file-saver.ts"],"sourcesContent":["/**\n * BaseSandbox: Abstract base class for sandbox backends.\n *\n * Implements all BackendProtocol methods using shell commands executed via execute().\n * Subclasses only need to implement execute() and id.\n *\n * This pattern allows creating sandbox backends for different environments\n * (local, Modal, Runloop, Daytona, etc.) by only implementing the command\n * execution layer.\n */\n\nimport type {\n EditResult,\n ExecuteResponse,\n FileData,\n FileInfo,\n GrepMatch,\n SandboxBackendProtocol,\n WriteResult,\n} from \"../types\";\nimport {\n FILE_NOT_FOUND,\n SYSTEM_REMINDER_FILE_EMPTY,\n STRING_NOT_FOUND,\n} from \"../constants/errors\";\nimport { DEFAULT_READ_LIMIT } from \"../constants/limits\";\n\n/**\n * Encode string to base64 for safe shell transmission.\n */\nfunction toBase64(str: string): string {\n return Buffer.from(str, \"utf-8\").toString(\"base64\");\n}\n\n/**\n * Build a Node.js script command with embedded base64 arguments.\n * This avoids shell argument parsing issues by embedding values directly in the script.\n */\nfunction buildNodeScript(script: string, args: Record<string, string>): string {\n // Replace placeholders with actual values\n let result = script;\n for (const [key, value] of Object.entries(args)) {\n result = result.replace(new RegExp(`__${key}__`, \"g\"), value);\n }\n return `node -e '${result}'`;\n}\n\n/**\n * Abstract base class for sandbox backends.\n *\n * Implements all file operations using shell commands via execute().\n * Subclasses only need to implement execute() and id.\n *\n * @example Creating a custom sandbox backend\n * ```typescript\n * class MyCloudSandbox extends BaseSandbox {\n * readonly id = 'my-cloud-123';\n *\n * async execute(command: string): Promise<ExecuteResponse> {\n * // Call your cloud provider's API\n * const result = await myCloudApi.runCommand(command);\n * return {\n * output: result.stdout + result.stderr,\n * exitCode: result.exitCode,\n * truncated: false,\n * };\n * }\n * }\n * ```\n */\nexport abstract class BaseSandbox implements SandboxBackendProtocol {\n /**\n * Execute a shell command in the sandbox.\n * Must be implemented by subclasses.\n */\n abstract execute(command: string): Promise<ExecuteResponse>;\n\n /**\n * Unique identifier for this sandbox instance.\n * Must be implemented by subclasses.\n */\n abstract readonly id: string;\n\n /**\n * List files and directories in a path.\n */\n async lsInfo(path: string): Promise<FileInfo[]> {\n const pathB64 = toBase64(path);\n const script = `\nconst fs = require(\"fs\");\nconst path = require(\"path\");\n\nconst dirPath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\n\ntry {\n const entries = fs.readdirSync(dirPath, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dirPath, entry.name);\n try {\n const stat = fs.statSync(fullPath);\n console.log(JSON.stringify({\n path: entry.name,\n is_dir: entry.isDirectory(),\n size: stat.size,\n modified_at: stat.mtime.toISOString()\n }));\n } catch (e) {}\n }\n} catch (e) {}\n`;\n const result = await this.execute(buildNodeScript(script, { PATH: pathB64 }));\n\n const infos: FileInfo[] = [];\n for (const line of result.output.trim().split(\"\\n\")) {\n if (!line) continue;\n try {\n const data = JSON.parse(line);\n infos.push({\n path: data.path,\n is_dir: data.is_dir,\n size: data.size,\n modified_at: data.modified_at,\n });\n } catch {\n // Skip malformed lines\n }\n }\n return infos;\n }\n\n /**\n * Read file content with line numbers.\n */\n async read(\n filePath: string,\n offset: number = 0,\n limit: number = DEFAULT_READ_LIMIT\n ): Promise<string> {\n const pathB64 = toBase64(filePath);\n const emptyReminder = SYSTEM_REMINDER_FILE_EMPTY;\n const script = `\nconst fs = require(\"fs\");\nconst filePath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\nconst offset = __OFFSET__;\nconst limit = __LIMIT__;\n\nif (!fs.existsSync(filePath)) {\n console.error(\"Error: File not found\");\n process.exit(1);\n}\n\nconst stat = fs.statSync(filePath);\nif (stat.size === 0) {\n console.log(\"${emptyReminder}\");\n process.exit(0);\n}\n\nconst content = fs.readFileSync(filePath, \"utf-8\");\nconst lines = content.split(\"\\\\n\");\nconst selected = lines.slice(offset, offset + limit);\n\nfor (let i = 0; i < selected.length; i++) {\n const lineNum = (offset + i + 1).toString().padStart(6, \" \");\n console.log(lineNum + \"\\\\t\" + selected[i]);\n}\n`;\n const result = await this.execute(\n buildNodeScript(script, {\n PATH: pathB64,\n OFFSET: String(offset),\n LIMIT: String(limit),\n })\n );\n\n if (result.exitCode !== 0) {\n if (result.output.includes(\"Error: File not found\")) {\n return FILE_NOT_FOUND(filePath);\n }\n return result.output.trim();\n }\n\n return result.output.trimEnd();\n }\n\n /**\n * Read raw file data.\n */\n async readRaw(filePath: string): Promise<FileData> {\n const pathB64 = toBase64(filePath);\n const script = `\nconst fs = require(\"fs\");\nconst filePath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\n\nif (!fs.existsSync(filePath)) {\n console.error(\"Error: File not found\");\n process.exit(1);\n}\n\nconst stat = fs.statSync(filePath);\nconst content = fs.readFileSync(filePath, \"utf-8\");\n\nconsole.log(JSON.stringify({\n content: content.split(\"\\\\n\"),\n created_at: stat.birthtime.toISOString(),\n modified_at: stat.mtime.toISOString()\n}));\n`;\n const result = await this.execute(buildNodeScript(script, { PATH: pathB64 }));\n\n if (result.exitCode !== 0) {\n throw new Error(`File '${filePath}' not found`);\n }\n\n try {\n const data = JSON.parse(result.output.trim());\n return {\n content: data.content,\n created_at: data.created_at,\n modified_at: data.modified_at,\n };\n } catch {\n throw new Error(`Failed to parse file data for '${filePath}'`);\n }\n }\n\n /**\n * Write content to a new file.\n */\n async write(filePath: string, content: string): Promise<WriteResult> {\n const pathB64 = toBase64(filePath);\n const contentB64 = toBase64(content);\n const script = `\nconst fs = require(\"fs\");\nconst path = require(\"path\");\n\nconst filePath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\nconst content = Buffer.from(\"__CONTENT__\", \"base64\").toString(\"utf-8\");\n\nif (fs.existsSync(filePath)) {\n console.error(\"Error: File already exists\");\n process.exit(1);\n}\n\nconst dir = path.dirname(filePath);\nif (dir && dir !== \".\") {\n fs.mkdirSync(dir, { recursive: true });\n}\n\nfs.writeFileSync(filePath, content, \"utf-8\");\n`;\n const result = await this.execute(\n buildNodeScript(script, { PATH: pathB64, CONTENT: contentB64 })\n );\n\n if (result.exitCode !== 0) {\n if (result.output.includes(\"already exists\")) {\n return {\n success: false,\n error: `Cannot write to ${filePath} because it already exists. Read and then make an edit, or write to a new path.`,\n };\n }\n return { success: false, error: result.output.trim() || `Failed to write '${filePath}'` };\n }\n\n return { success: true, path: filePath };\n }\n\n /**\n * Edit a file by replacing string occurrences.\n */\n async edit(\n filePath: string,\n oldString: string,\n newString: string,\n replaceAll: boolean = false\n ): Promise<EditResult> {\n const pathB64 = toBase64(filePath);\n const oldB64 = toBase64(oldString);\n const newB64 = toBase64(newString);\n const script = `\nconst fs = require(\"fs\");\n\nconst filePath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\nconst oldStr = Buffer.from(\"__OLD__\", \"base64\").toString(\"utf-8\");\nconst newStr = Buffer.from(\"__NEW__\", \"base64\").toString(\"utf-8\");\nconst replaceAll = __REPLACE_ALL__;\n\nif (!fs.existsSync(filePath)) {\n console.error(\"Error: File not found\");\n process.exit(1);\n}\n\nlet content = fs.readFileSync(filePath, \"utf-8\");\nconst count = content.split(oldStr).length - 1;\n\nif (count === 0) {\n process.exit(2);\n}\nif (count > 1 && !replaceAll) {\n process.exit(3);\n}\n\nif (replaceAll) {\n content = content.split(oldStr).join(newStr);\n} else {\n content = content.replace(oldStr, newStr);\n}\n\nfs.writeFileSync(filePath, content, \"utf-8\");\nconsole.log(count);\n`;\n const result = await this.execute(\n buildNodeScript(script, {\n PATH: pathB64,\n OLD: oldB64,\n NEW: newB64,\n REPLACE_ALL: String(replaceAll),\n })\n );\n\n if (result.exitCode === 1) {\n return { success: false, error: FILE_NOT_FOUND(filePath) };\n }\n if (result.exitCode === 2) {\n return { success: false, error: STRING_NOT_FOUND(filePath, oldString) };\n }\n if (result.exitCode === 3) {\n return {\n success: false,\n error: `Error: String '${oldString}' appears multiple times. Use replaceAll=true to replace all occurrences.`,\n };\n }\n\n const count = parseInt(result.output.trim(), 10) || 1;\n return { success: true, path: filePath, occurrences: count };\n }\n\n /**\n * Search for pattern in files.\n */\n async grepRaw(\n pattern: string,\n path: string = \"/\",\n glob: string | null = null\n ): Promise<GrepMatch[] | string> {\n const patternB64 = toBase64(pattern);\n const pathB64 = toBase64(path);\n const globB64 = glob ? toBase64(glob) : toBase64(\"**/*\");\n const script = `\nconst fs = require(\"fs\");\nconst path = require(\"path\");\n\nconst pattern = Buffer.from(\"__PATTERN__\", \"base64\").toString(\"utf-8\");\nconst basePath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\nconst fileGlob = Buffer.from(\"__GLOB__\", \"base64\").toString(\"utf-8\");\n\nfunction walkDir(dir, baseDir) {\n const results = [];\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = path.relative(baseDir, fullPath);\n \n if (entry.isDirectory()) {\n results.push(...walkDir(fullPath, baseDir));\n } else {\n results.push(relativePath);\n }\n }\n } catch (e) {}\n return results;\n}\n\nfunction matchGlob(filepath, pattern) {\n if (!pattern || pattern === \"**/*\") return true;\n const regex = pattern\n .replace(/\\\\./g, \"\\\\\\\\.\")\n .replace(/\\\\*\\\\*/g, \"<<<GLOBSTAR>>>\")\n .replace(/\\\\*/g, \"[^/]*\")\n .replace(/<<<GLOBSTAR>>>/g, \".*\")\n .replace(/\\\\?/g, \".\");\n return new RegExp(\"^\" + regex + \"$\").test(filepath);\n}\n\nconst allFiles = walkDir(basePath, basePath);\nconst files = allFiles.filter(f => matchGlob(f, fileGlob)).sort();\n\nfor (const file of files) {\n try {\n const fullPath = path.join(basePath, file);\n const content = fs.readFileSync(fullPath, \"utf-8\");\n const lines = content.split(\"\\\\n\");\n \n for (let i = 0; i < lines.length; i++) {\n if (lines[i].includes(pattern)) {\n console.log(JSON.stringify({\n path: file,\n line: i + 1,\n text: lines[i]\n }));\n }\n }\n } catch (e) {}\n}\n`;\n const result = await this.execute(\n buildNodeScript(script, {\n PATTERN: patternB64,\n PATH: pathB64,\n GLOB: globB64,\n })\n );\n\n const matches: GrepMatch[] = [];\n for (const line of result.output.trim().split(\"\\n\")) {\n if (!line) continue;\n try {\n const data = JSON.parse(line);\n matches.push({\n path: data.path,\n line: data.line,\n text: data.text,\n });\n } catch {\n // Skip malformed lines\n }\n }\n return matches;\n }\n\n /**\n * Find files matching glob pattern.\n */\n async globInfo(pattern: string, path: string = \"/\"): Promise<FileInfo[]> {\n const pathB64 = toBase64(path);\n const patternB64 = toBase64(pattern);\n const script = `\nconst fs = require(\"fs\");\nconst path = require(\"path\");\n\nconst basePath = Buffer.from(\"__PATH__\", \"base64\").toString(\"utf-8\");\nconst pattern = Buffer.from(\"__PATTERN__\", \"base64\").toString(\"utf-8\");\n\nfunction walkDir(dir, baseDir) {\n const results = [];\n try {\n const entries = fs.readdirSync(dir, { withFileTypes: true });\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n const relativePath = path.relative(baseDir, fullPath);\n \n if (entry.isDirectory()) {\n results.push(...walkDir(fullPath, baseDir));\n } else {\n results.push(relativePath);\n }\n }\n } catch (e) {}\n return results;\n}\n\nfunction matchGlob(filepath, pattern) {\n const regex = pattern\n .replace(/\\\\./g, \"\\\\\\\\.\")\n .replace(/\\\\*\\\\*/g, \"<<<GLOBSTAR>>>\")\n .replace(/\\\\*/g, \"[^/]*\")\n .replace(/<<<GLOBSTAR>>>/g, \".*\")\n .replace(/\\\\?/g, \".\");\n return new RegExp(\"^\" + regex + \"$\").test(filepath);\n}\n\nconst allFiles = walkDir(basePath, basePath);\nconst matches = allFiles.filter(f => matchGlob(f, pattern)).sort();\n\nfor (const m of matches) {\n try {\n const fullPath = path.join(basePath, m);\n const stat = fs.statSync(fullPath);\n console.log(JSON.stringify({\n path: m,\n is_dir: stat.isDirectory(),\n size: stat.size,\n modified_at: stat.mtime.toISOString()\n }));\n } catch (e) {}\n}\n`;\n const result = await this.execute(\n buildNodeScript(script, { PATH: pathB64, PATTERN: patternB64 })\n );\n\n const infos: FileInfo[] = [];\n for (const line of result.output.trim().split(\"\\n\")) {\n if (!line) continue;\n try {\n const data = JSON.parse(line);\n infos.push({\n path: data.path,\n is_dir: data.is_dir,\n size: data.size,\n modified_at: data.modified_at,\n });\n } catch {\n // Skip malformed lines\n }\n }\n return infos;\n }\n}\n","/**\n * LocalSandbox: Execute commands locally using child_process.\n *\n * Useful for local development and testing without cloud sandboxes.\n * All file operations are inherited from BaseSandbox and executed\n * via shell commands in the local filesystem.\n */\n\nimport { spawn } from \"child_process\";\nimport type { ExecuteResponse } from \"../types\";\nimport { BaseSandbox } from \"./sandbox\";\n\n/**\n * Options for LocalSandbox.\n */\nexport interface LocalSandboxOptions {\n /**\n * Working directory for command execution.\n * All file paths in sandbox operations are relative to this directory.\n * @default process.cwd()\n */\n cwd?: string;\n\n /**\n * Timeout in milliseconds for command execution.\n * Commands that exceed this timeout will be terminated.\n * @default 30000 (30 seconds)\n */\n timeout?: number;\n\n /**\n * Additional environment variables to set for command execution.\n * These are merged with the current process environment.\n */\n env?: Record<string, string>;\n\n /**\n * Maximum output size in bytes before truncation.\n * @default 1048576 (1MB)\n */\n maxOutputSize?: number;\n}\n\n/**\n * Local sandbox that executes commands using Node.js child_process.\n *\n * All commands are executed in a bash shell with the specified working directory.\n * Inherits all file operations (read, write, edit, ls, grep, glob) from BaseSandbox.\n *\n * @example Basic usage\n * ```typescript\n * import { LocalSandbox } from 'deepagentsdk';\n *\n * const sandbox = new LocalSandbox({ cwd: './workspace' });\n *\n * // Execute commands\n * const result = await sandbox.execute('ls -la');\n * console.log(result.output);\n *\n * // File operations\n * await sandbox.write('./src/index.ts', 'console.log(\"hello\")');\n * const content = await sandbox.read('./src/index.ts');\n * ```\n *\n * @example With timeout and environment\n * ```typescript\n * const sandbox = new LocalSandbox({\n * cwd: './workspace',\n * timeout: 60000, // 60 seconds\n * env: {\n * NODE_ENV: 'development',\n * DEBUG: '*',\n * },\n * });\n * ```\n *\n * @example Error handling\n * ```typescript\n * const result = await sandbox.execute('npm test');\n * if (result.exitCode !== 0) {\n * console.error('Tests failed:', result.output);\n * }\n * ```\n */\nexport class LocalSandbox extends BaseSandbox {\n private readonly cwd: string;\n private readonly timeout: number;\n private readonly env: Record<string, string>;\n private readonly maxOutputSize: number;\n private readonly _id: string;\n\n /**\n * Create a new LocalSandbox instance.\n *\n * @param options - Configuration options for the sandbox\n */\n constructor(options: LocalSandboxOptions = {}) {\n super();\n this.cwd = options.cwd || process.cwd();\n this.timeout = options.timeout || 30000;\n this.env = options.env || {};\n this.maxOutputSize = options.maxOutputSize || 1024 * 1024; // 1MB\n this._id = `local-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n }\n\n /**\n * Unique identifier for this sandbox instance.\n * Format: `local-{timestamp}-{random}`\n */\n get id(): string {\n return this._id;\n }\n\n /**\n * Execute a shell command in the local filesystem.\n *\n * Commands are executed using bash with the configured working directory\n * and environment variables. Output is captured from both stdout and stderr.\n *\n * @param command - Shell command to execute\n * @returns ExecuteResponse with output, exit code, and truncation status\n *\n * @example\n * ```typescript\n * const result = await sandbox.execute('echo \"Hello\" && ls -la');\n * console.log(result.output);\n * console.log('Exit code:', result.exitCode);\n * ```\n */\n async execute(command: string): Promise<ExecuteResponse> {\n return new Promise((resolve) => {\n const child = spawn(\"bash\", [\"-c\", command], {\n cwd: this.cwd,\n env: { ...process.env, ...this.env },\n timeout: this.timeout,\n });\n\n let output = \"\";\n let truncated = false;\n\n child.stdout.on(\"data\", (data: Buffer) => {\n if (output.length < this.maxOutputSize) {\n output += data.toString();\n } else {\n truncated = true;\n }\n });\n\n child.stderr.on(\"data\", (data: Buffer) => {\n if (output.length < this.maxOutputSize) {\n output += data.toString();\n } else {\n truncated = true;\n }\n });\n\n child.on(\"close\", (code) => {\n resolve({\n output,\n exitCode: code,\n truncated,\n });\n });\n\n child.on(\"error\", (err) => {\n resolve({\n output: `Error: ${err.message}`,\n exitCode: 1,\n truncated: false,\n });\n });\n });\n }\n}\n\n","/**\n * Utility to parse model strings into LanguageModel instances.\n * Provides backward compatibility for CLI and other string-based model specifications.\n */\n\nimport { anthropic } from \"@ai-sdk/anthropic\";\nimport { openai } from \"@ai-sdk/openai\";\nimport type { LanguageModel } from \"ai\";\n\n/**\n * Parse a model string into a LanguageModel instance.\n *\n * Supports formats like:\n * - \"anthropic/claude-sonnet-4-20250514\"\n * - \"openai/gpt-4o\"\n * - \"claude-sonnet-4-20250514\" (defaults to Anthropic)\n *\n * @param modelString - The model string to parse\n * @returns A LanguageModel instance\n *\n * @example\n * ```typescript\n * const model = parseModelString(\"anthropic/claude-sonnet-4-20250514\");\n * const agent = createDeepAgent({ model });\n * ```\n */\nexport function parseModelString(modelString: string): LanguageModel {\n const [provider, modelName] = modelString.split(\"/\");\n\n if (provider === \"anthropic\") {\n return anthropic(modelName || \"claude-sonnet-4-20250514\");\n } else if (provider === \"openai\") {\n return openai(modelName || \"gpt-5-mini\") as any;\n }\n\n // Default to anthropic if no provider specified\n return anthropic(modelString);\n}\n","/**\n * File-based checkpoint saver for local development.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { Checkpoint, BaseCheckpointSaver } from \"./types\";\n\n/**\n * Options for FileSaver.\n */\nexport interface FileSaverOptions {\n /** Directory to store checkpoint files */\n dir: string;\n}\n\n/**\n * File-based checkpoint saver.\n * \n * Stores checkpoints as JSON files in a directory. Each thread gets\n * its own file named `{threadId}.json`.\n * \n * @example\n * ```typescript\n * const saver = new FileSaver({ dir: './.checkpoints' });\n * const agent = createDeepAgent({\n * model: anthropic('claude-sonnet-4-20250514'),\n * checkpointer: saver,\n * });\n * ```\n */\nexport class FileSaver implements BaseCheckpointSaver {\n private dir: string;\n\n constructor(options: FileSaverOptions) {\n this.dir = options.dir;\n \n // Ensure directory exists\n if (!existsSync(this.dir)) {\n mkdirSync(this.dir, { recursive: true });\n }\n }\n\n private getFilePath(threadId: string): string {\n // Sanitize threadId to be safe for filenames\n const safeId = threadId.replace(/[^a-zA-Z0-9_-]/g, '_');\n return join(this.dir, `${safeId}.json`);\n }\n\n async save(checkpoint: Checkpoint): Promise<void> {\n const filePath = this.getFilePath(checkpoint.threadId);\n const data = {\n ...checkpoint,\n updatedAt: new Date().toISOString(),\n };\n writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n }\n\n async load(threadId: string): Promise<Checkpoint | undefined> {\n const filePath = this.getFilePath(threadId);\n \n if (!existsSync(filePath)) {\n return undefined;\n }\n \n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as Checkpoint;\n } catch {\n return undefined;\n }\n }\n\n async list(): Promise<string[]> {\n if (!existsSync(this.dir)) {\n return [];\n }\n \n const files = readdirSync(this.dir);\n return files\n .filter(f => f.endsWith('.json'))\n .map(f => f.replace('.json', ''));\n }\n\n async delete(threadId: string): Promise<void> {\n const filePath = this.getFilePath(threadId);\n \n if (existsSync(filePath)) {\n unlinkSync(filePath);\n }\n }\n\n async exists(threadId: string): Promise<boolean> {\n const filePath = this.getFilePath(threadId);\n return existsSync(filePath);\n }\n}\n\n"],"mappings":"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"}
|