@langchain/daytona 0.1.0 → 0.1.2
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/index.cjs +90 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -12
- package/dist/index.d.ts +57 -12
- package/dist/index.js +91 -13
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.cjs
CHANGED
|
@@ -86,6 +86,13 @@ function getAuthCredentials(options, target) {
|
|
|
86
86
|
//#endregion
|
|
87
87
|
//#region src/types.ts
|
|
88
88
|
/**
|
|
89
|
+
* Type definitions for the Daytona Sandbox backend.
|
|
90
|
+
*
|
|
91
|
+
* This module contains all type definitions for the @langchain/daytona package,
|
|
92
|
+
* including options and error types.
|
|
93
|
+
*/
|
|
94
|
+
const DAYTONA_SANDBOX_ERROR_SYMBOL = Symbol.for("daytona.sandbox.error");
|
|
95
|
+
/**
|
|
89
96
|
* Custom error class for Daytona Sandbox operations.
|
|
90
97
|
*
|
|
91
98
|
* Provides structured error information including:
|
|
@@ -113,7 +120,9 @@ function getAuthCredentials(options, target) {
|
|
|
113
120
|
* }
|
|
114
121
|
* ```
|
|
115
122
|
*/
|
|
116
|
-
var DaytonaSandboxError = class DaytonaSandboxError extends
|
|
123
|
+
var DaytonaSandboxError = class DaytonaSandboxError extends deepagents.SandboxError {
|
|
124
|
+
/** Symbol for identifying sandbox error instances */
|
|
125
|
+
[DAYTONA_SANDBOX_ERROR_SYMBOL] = true;
|
|
117
126
|
/** Error name for instanceof checks and logging */
|
|
118
127
|
name = "DaytonaSandboxError";
|
|
119
128
|
/**
|
|
@@ -124,11 +133,20 @@ var DaytonaSandboxError = class DaytonaSandboxError extends Error {
|
|
|
124
133
|
* @param cause - Original error that caused this error (for debugging)
|
|
125
134
|
*/
|
|
126
135
|
constructor(message, code, cause) {
|
|
127
|
-
super(message);
|
|
136
|
+
super(message, code, cause);
|
|
128
137
|
this.code = code;
|
|
129
138
|
this.cause = cause;
|
|
130
139
|
Object.setPrototypeOf(this, DaytonaSandboxError.prototype);
|
|
131
140
|
}
|
|
141
|
+
/**
|
|
142
|
+
* Checks if the error is an instance of DaytonaSandboxError.
|
|
143
|
+
*
|
|
144
|
+
* @param error - The error to check
|
|
145
|
+
* @returns True if the error is an instance of DaytonaSandboxError, false otherwise
|
|
146
|
+
*/
|
|
147
|
+
static isInstance(error) {
|
|
148
|
+
return typeof error === "object" && error !== null && error[DAYTONA_SANDBOX_ERROR_SYMBOL] === true;
|
|
149
|
+
}
|
|
132
150
|
};
|
|
133
151
|
|
|
134
152
|
//#endregion
|
|
@@ -215,11 +233,26 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
215
233
|
* const daytonaSdk = sandbox.sandbox; // Access the raw SDK
|
|
216
234
|
* ```
|
|
217
235
|
*/
|
|
218
|
-
get
|
|
236
|
+
get instance() {
|
|
219
237
|
if (!this.#sandbox) throw new DaytonaSandboxError("Sandbox not initialized. Call initialize() or use DaytonaSandbox.create()", "NOT_INITIALIZED");
|
|
220
238
|
return this.#sandbox;
|
|
221
239
|
}
|
|
222
240
|
/**
|
|
241
|
+
* Get the underlying Daytona client instance.
|
|
242
|
+
*
|
|
243
|
+
* @throws {DaytonaSandboxError} If the client is not initialized
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```typescript
|
|
247
|
+
* const sandbox = await DaytonaSandbox.create();
|
|
248
|
+
* const daytonaClient = sandbox.client; // Access the raw Daytona client
|
|
249
|
+
* ```
|
|
250
|
+
*/
|
|
251
|
+
get client() {
|
|
252
|
+
if (!this.#daytona) throw new DaytonaSandboxError("Daytona client not initialized. Call initialize() or use DaytonaSandbox.create()", "NOT_INITIALIZED");
|
|
253
|
+
return this.#daytona;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
223
256
|
* Check if the sandbox is initialized and running.
|
|
224
257
|
*/
|
|
225
258
|
get isRunning() {
|
|
@@ -336,7 +369,7 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
336
369
|
* ```
|
|
337
370
|
*/
|
|
338
371
|
async execute(command) {
|
|
339
|
-
const sandbox = this.
|
|
372
|
+
const sandbox = this.instance;
|
|
340
373
|
try {
|
|
341
374
|
const response = await sandbox.process.executeCommand(command, void 0, void 0, this.#timeout);
|
|
342
375
|
return {
|
|
@@ -368,7 +401,7 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
368
401
|
* ```
|
|
369
402
|
*/
|
|
370
403
|
async uploadFiles(files) {
|
|
371
|
-
const sandbox = this.
|
|
404
|
+
const sandbox = this.instance;
|
|
372
405
|
const results = [];
|
|
373
406
|
for (const [path, content] of files) try {
|
|
374
407
|
const parentDir = path.substring(0, path.lastIndexOf("/"));
|
|
@@ -409,7 +442,7 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
409
442
|
* ```
|
|
410
443
|
*/
|
|
411
444
|
async downloadFiles(paths) {
|
|
412
|
-
const sandbox = this.
|
|
445
|
+
const sandbox = this.instance;
|
|
413
446
|
const results = [];
|
|
414
447
|
for (const path of paths) try {
|
|
415
448
|
const buffer = await sandbox.fs.downloadFile(path);
|
|
@@ -504,7 +537,7 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
504
537
|
* ```
|
|
505
538
|
*/
|
|
506
539
|
async getWorkDir() {
|
|
507
|
-
return await this.
|
|
540
|
+
return await this.instance.getWorkDir() ?? "/home/daytona";
|
|
508
541
|
}
|
|
509
542
|
/**
|
|
510
543
|
* Get the user's home directory path inside the sandbox.
|
|
@@ -518,7 +551,7 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
518
551
|
* ```
|
|
519
552
|
*/
|
|
520
553
|
async getUserHomeDir() {
|
|
521
|
-
return await this.
|
|
554
|
+
return await this.instance.getUserHomeDir() ?? "/home/daytona";
|
|
522
555
|
}
|
|
523
556
|
/**
|
|
524
557
|
* Set the sandbox from an existing Daytona Sandbox instance.
|
|
@@ -568,6 +601,41 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
568
601
|
return sandbox;
|
|
569
602
|
}
|
|
570
603
|
/**
|
|
604
|
+
* Delete all sandboxes matching the given labels.
|
|
605
|
+
*
|
|
606
|
+
* This is useful for cleaning up stale sandboxes from previous test runs
|
|
607
|
+
* or CI pipelines that may not have shut down cleanly.
|
|
608
|
+
*
|
|
609
|
+
* @param labels - Label key-value pairs to filter sandboxes
|
|
610
|
+
* @param options - Optional auth configuration
|
|
611
|
+
* @returns The number of sandboxes that were deleted
|
|
612
|
+
*
|
|
613
|
+
* @example
|
|
614
|
+
* ```typescript
|
|
615
|
+
* // Clean up all integration-test sandboxes
|
|
616
|
+
* const deleted = await DaytonaSandbox.deleteAll({
|
|
617
|
+
* purpose: "integration-test",
|
|
618
|
+
* package: "@langchain/daytona",
|
|
619
|
+
* });
|
|
620
|
+
* console.log(`Deleted ${deleted} stale sandboxes`);
|
|
621
|
+
* ```
|
|
622
|
+
*/
|
|
623
|
+
static async deleteAll(labels, options) {
|
|
624
|
+
let credentials;
|
|
625
|
+
try {
|
|
626
|
+
credentials = getAuthCredentials(options?.auth, options?.target);
|
|
627
|
+
} catch (error) {
|
|
628
|
+
throw new DaytonaSandboxError("Failed to authenticate with Daytona. Check your API key configuration.", "AUTHENTICATION_FAILED", error instanceof Error ? error : void 0);
|
|
629
|
+
}
|
|
630
|
+
const daytona = new _daytonaio_sdk.Daytona({
|
|
631
|
+
apiKey: credentials.apiKey,
|
|
632
|
+
apiUrl: credentials.apiUrl,
|
|
633
|
+
target: credentials.target
|
|
634
|
+
});
|
|
635
|
+
const { items } = await daytona.list(labels);
|
|
636
|
+
return (await Promise.all(items.map((sandbox) => daytona.delete(sandbox).then(() => true).catch(() => false)))).filter(Boolean).length;
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
571
639
|
* Connect to an existing sandbox by ID.
|
|
572
640
|
*
|
|
573
641
|
* This allows you to resume working with a sandbox that was created
|
|
@@ -584,7 +652,7 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
584
652
|
* const result = await sandbox.execute("ls -la");
|
|
585
653
|
* ```
|
|
586
654
|
*/
|
|
587
|
-
static async
|
|
655
|
+
static async fromId(id, options) {
|
|
588
656
|
let credentials;
|
|
589
657
|
try {
|
|
590
658
|
credentials = getAuthCredentials(options?.auth, options?.target);
|
|
@@ -597,14 +665,24 @@ var DaytonaSandbox = class DaytonaSandbox extends deepagents.BaseSandbox {
|
|
|
597
665
|
apiUrl: credentials.apiUrl,
|
|
598
666
|
target: credentials.target
|
|
599
667
|
});
|
|
600
|
-
const existingSandbox = await daytona.get(
|
|
668
|
+
const existingSandbox = await daytona.get(id);
|
|
601
669
|
const daytonaSandbox = new DaytonaSandbox(options);
|
|
602
|
-
daytonaSandbox.#setFromExisting(daytona, existingSandbox,
|
|
670
|
+
daytonaSandbox.#setFromExisting(daytona, existingSandbox, id);
|
|
603
671
|
return daytonaSandbox;
|
|
604
672
|
} catch (error) {
|
|
605
|
-
throw new DaytonaSandboxError(`Sandbox not found: ${
|
|
673
|
+
throw new DaytonaSandboxError(`Sandbox not found: ${id}`, "SANDBOX_NOT_FOUND", error instanceof Error ? error : void 0);
|
|
606
674
|
}
|
|
607
675
|
}
|
|
676
|
+
/**
|
|
677
|
+
* Get a running sandbox by name from a deployed app.
|
|
678
|
+
*
|
|
679
|
+
* @param name - The name of the sandbox
|
|
680
|
+
* @param options - Optional auth configuration
|
|
681
|
+
* @returns A connected sandbox instance
|
|
682
|
+
*/
|
|
683
|
+
static async fromName(name, options) {
|
|
684
|
+
return DaytonaSandbox.fromId(name, options);
|
|
685
|
+
}
|
|
608
686
|
};
|
|
609
687
|
/**
|
|
610
688
|
* Create an async factory function that creates a new Daytona Sandbox per invocation.
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["BaseSandbox","#id","#sandbox","#options","#timeout","#daytona","Daytona","#uploadInitialFiles","#mapError","#setFromExisting"],"sources":["../src/auth.ts","../src/types.ts","../src/sandbox.ts"],"sourcesContent":["/**\n * Authentication utilities for Daytona Sandbox.\n *\n * This module provides authentication credential resolution for the Daytona SDK.\n *\n * @packageDocumentation\n */\n\nimport type { DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Authentication credentials for Daytona API.\n */\nexport interface DaytonaCredentials {\n /** Daytona API key */\n apiKey: string;\n\n /** Daytona API URL */\n apiUrl: string;\n\n /** Target region */\n target?: string;\n}\n\n/** Default Daytona API URL */\nconst DEFAULT_API_URL = \"https://app.daytona.io/api\";\n\n/**\n * Get the API key for Daytona API.\n *\n * Authentication is resolved in the following priority order:\n *\n * 1. **Explicit API key**: If `options.apiKey` is provided, it is used directly.\n * 2. **DAYTONA_API_KEY**: Environment variable for Daytona API key.\n *\n * If no API key is found, an error is thrown with setup instructions.\n *\n * ## Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API key string\n * @throws {Error} If no API key is available\n *\n * @example\n * ```typescript\n * // With explicit API key\n * const apiKey = getAuthApiKey({ apiKey: \"my-api-key\" });\n *\n * // Using environment variables (auto-detected)\n * const apiKey = getAuthApiKey();\n *\n * // From DaytonaSandboxOptions\n * const options: DaytonaSandboxOptions = {\n * auth: { apiKey: \"my-api-key\" }\n * };\n * const apiKey = getAuthApiKey(options.auth);\n * ```\n */\nexport function getAuthApiKey(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API key in options\n if (options?.apiKey) {\n return options.apiKey;\n }\n\n // Priority 2: DAYTONA_API_KEY environment variable\n const apiKey = process.env.DAYTONA_API_KEY;\n if (apiKey) {\n return apiKey;\n }\n\n // No API key found - throw descriptive error\n throw new Error(\n \"Daytona authentication required. Provide an API key using one of these methods:\\n\\n\" +\n \"1. Set DAYTONA_API_KEY environment variable:\\n\" +\n \" Get your API key from https://app.daytona.io\\n\" +\n \" Run: export DAYTONA_API_KEY=your_api_key_here\\n\\n\" +\n \"2. Pass API key directly in options:\\n\" +\n \" new DaytonaSandbox({ auth: { apiKey: '...' } })\",\n );\n}\n\n/**\n * Get the API URL for Daytona API.\n *\n * URL is resolved in the following priority order:\n *\n * 1. **Explicit API URL**: If `options.apiUrl` is provided, it is used directly.\n * 2. **DAYTONA_API_URL**: Environment variable for Daytona API URL.\n * 3. **Default**: Uses the default Daytona API URL.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API URL string\n */\nexport function getAuthApiUrl(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API URL in options\n if (options?.apiUrl) {\n return options.apiUrl;\n }\n\n // Priority 2: DAYTONA_API_URL environment variable\n const apiUrl = process.env.DAYTONA_API_URL;\n if (apiUrl) {\n return apiUrl;\n }\n\n // Priority 3: Default URL\n return DEFAULT_API_URL;\n}\n\n/**\n * Get authentication credentials for Daytona API.\n *\n * This function returns the credentials needed for the Daytona SDK.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @param target - Optional target region\n * @returns Complete authentication credentials\n * @throws {Error} If no API key is available\n */\nexport function getAuthCredentials(\n options?: DaytonaSandboxOptions[\"auth\"],\n target?: string,\n): DaytonaCredentials {\n return {\n apiKey: getAuthApiKey(options),\n apiUrl: getAuthApiUrl(options),\n target: target ?? process.env.DAYTONA_TARGET,\n };\n}\n","/**\n * Type definitions for the Daytona Sandbox backend.\n *\n * This module contains all type definitions for the @langchain/daytona package,\n * including options and error types.\n */\n\n/**\n * Supported target regions for Daytona sandboxes.\n *\n * - `us`: United States\n * - `eu`: Europe\n */\nexport type DaytonaSandboxTarget = \"us\" | \"eu\";\n\n/**\n * Configuration options for creating a Daytona Sandbox.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * timeout: 300, // 5 minutes\n * target: \"us\",\n * };\n * ```\n */\nexport interface DaytonaSandboxOptions {\n /**\n * Primary language for code execution in the sandbox.\n *\n * Determines the runtime environment and code execution tooling.\n *\n * @default \"typescript\"\n */\n language?: \"typescript\" | \"python\" | \"javascript\";\n\n /**\n * Custom environment variables to set in the sandbox.\n *\n * These variables will be available to all commands and code executed\n * in the sandbox.\n *\n * @example\n * ```typescript\n * envVars: {\n * NODE_ENV: \"development\",\n * API_KEY: \"secret\"\n * }\n * ```\n */\n envVars?: Record<string, string>;\n\n /**\n * Resource allocation for the sandbox.\n *\n * When specifying resources, you must also specify an `image`.\n * Resources cannot be customized when using the default snapshot-based sandbox.\n *\n * @example\n * ```typescript\n * resources: { cpu: 2, memory: 4, disk: 20 }\n * ```\n */\n resources?: {\n /** Number of CPUs to allocate */\n cpu?: number;\n /** Amount of memory in GiB */\n memory?: number;\n /** Amount of disk space in GiB */\n disk?: number;\n };\n\n /**\n * Custom Docker image to use for the sandbox.\n *\n * When specified, creates a sandbox from this image instead of the default snapshot.\n * This is required when you want to customize resources.\n *\n * @example \"node:20\" or \"python:3.12\"\n */\n image?: string;\n\n /**\n * Snapshot name to use for the sandbox.\n *\n * When specified, creates a sandbox from this snapshot.\n * Cannot be used together with `image`.\n */\n snapshot?: string;\n\n /**\n * Target region where the sandbox will be created.\n *\n * @default \"us\"\n */\n target?: DaytonaSandboxTarget;\n\n /**\n * Auto-stop interval in minutes.\n *\n * The sandbox will automatically stop after being idle for this duration.\n * Set to 0 to disable auto-stop.\n *\n * @default 15\n */\n autoStopInterval?: number;\n\n /**\n * Default timeout for command execution in seconds.\n *\n * @default 300 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Custom labels to attach to the sandbox.\n *\n * Labels can be used for organizing and filtering sandboxes.\n */\n labels?: Record<string, string>;\n\n /**\n * Initial files to create in the sandbox after initialization.\n *\n * A map of file paths to their contents. Files will be created\n * in the sandbox filesystem before any commands are executed.\n * Parent directories are created automatically.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * initialFiles: {\n * \"/app/index.js\": \"console.log('Hello')\",\n * \"/app/package.json\": '{\"name\": \"test\"}',\n * },\n * };\n * ```\n */\n initialFiles?: Record<string, string>;\n\n /**\n * Authentication configuration for Daytona API.\n *\n * ### Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * Or pass the API key directly in this auth configuration.\n */\n auth?: {\n /**\n * Daytona API key.\n * If not provided, reads from `DAYTONA_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Daytona API URL.\n * If not provided, reads from `DAYTONA_API_URL` environment variable\n * or uses the default Daytona API URL.\n *\n * @default \"https://app.daytona.io/api\"\n */\n apiUrl?: string;\n };\n}\n\n/**\n * Error codes for Daytona Sandbox operations.\n *\n * Used to identify specific error conditions and handle them appropriately.\n */\nexport type DaytonaSandboxErrorCode =\n /** Sandbox has not been initialized - call initialize() first */\n | \"NOT_INITIALIZED\"\n /** Sandbox is already initialized - cannot initialize twice */\n | \"ALREADY_INITIALIZED\"\n /** Authentication failed - check API key configuration */\n | \"AUTHENTICATION_FAILED\"\n /** Failed to create sandbox - check options and quotas */\n | \"SANDBOX_CREATION_FAILED\"\n /** Sandbox not found - may have been deleted or expired */\n | \"SANDBOX_NOT_FOUND\"\n /** Sandbox is not in started state */\n | \"SANDBOX_NOT_STARTED\"\n /** Command execution timed out */\n | \"COMMAND_TIMEOUT\"\n /** Command execution failed */\n | \"COMMAND_FAILED\"\n /** File operation (read/write) failed */\n | \"FILE_OPERATION_FAILED\"\n /** Resource limits exceeded (CPU, memory, storage) */\n | \"RESOURCE_LIMIT_EXCEEDED\";\n\n/**\n * Custom error class for Daytona Sandbox operations.\n *\n * Provides structured error information including:\n * - Human-readable message\n * - Error code for programmatic handling\n * - Original cause for debugging\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"some command\");\n * } catch (error) {\n * if (error instanceof DaytonaSandboxError) {\n * switch (error.code) {\n * case \"NOT_INITIALIZED\":\n * await sandbox.initialize();\n * break;\n * case \"COMMAND_TIMEOUT\":\n * console.error(\"Command took too long\");\n * break;\n * default:\n * throw error;\n * }\n * }\n * }\n * ```\n */\nexport class DaytonaSandboxError extends Error {\n /** Error name for instanceof checks and logging */\n override readonly name = \"DaytonaSandboxError\";\n\n /**\n * Creates a new DaytonaSandboxError.\n *\n * @param message - Human-readable error description\n * @param code - Structured error code for programmatic handling\n * @param cause - Original error that caused this error (for debugging)\n */\n constructor(\n message: string,\n public readonly code: DaytonaSandboxErrorCode,\n public override readonly cause?: Error,\n ) {\n super(message);\n // Maintain proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, DaytonaSandboxError.prototype);\n }\n}\n","/* eslint-disable no-instanceof/no-instanceof */\n/**\n * Daytona Sandbox implementation of the SandboxBackendProtocol.\n *\n * This module provides a Daytona Sandbox backend for deepagents, enabling agents\n * to execute commands, read/write files, and manage isolated sandbox environments\n * using Daytona's infrastructure.\n *\n * @packageDocumentation\n */\n\nimport { Daytona, type Sandbox } from \"@daytonaio/sdk\";\nimport {\n BaseSandbox,\n type ExecuteResponse,\n type FileDownloadResponse,\n type FileOperationError,\n type FileUploadResponse,\n type BackendFactory,\n} from \"deepagents\";\n\nimport { getAuthCredentials } from \"./auth.js\";\nimport { DaytonaSandboxError, type DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Daytona Sandbox backend for deepagents.\n *\n * Extends `BaseSandbox` to provide command execution, file operations, and\n * sandbox lifecycle management using Daytona's SDK.\n *\n * ## Basic Usage\n *\n * ```typescript\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * timeout: 300,\n * });\n *\n * try {\n * // Execute commands\n * const result = await sandbox.execute(\"node --version\");\n * console.log(result.output);\n * } finally {\n * // Always cleanup\n * await sandbox.close();\n * }\n * ```\n *\n * ## Using with DeepAgent\n *\n * ```typescript\n * import { createDeepAgent } from \"deepagents\";\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * const sandbox = await DaytonaSandbox.create();\n *\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant with sandbox access.\",\n * backend: sandbox,\n * });\n * ```\n */\nexport class DaytonaSandbox extends BaseSandbox {\n /** Private reference to the Daytona client */\n #daytona: Daytona | null = null;\n\n /** Private reference to the underlying Daytona Sandbox instance */\n #sandbox: Sandbox | null = null;\n\n /** Configuration options for this sandbox */\n #options: DaytonaSandboxOptions;\n\n /** Unique identifier for this sandbox instance */\n #id: string;\n\n /** Default timeout for command execution in seconds */\n #timeout: number;\n\n /**\n * Get the unique identifier for this sandbox.\n *\n * Before initialization, returns a temporary ID.\n * After initialization, returns the actual Daytona sandbox ID.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * Get the underlying Daytona Sandbox instance.\n *\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create();\n * const daytonaSdk = sandbox.sandbox; // Access the raw SDK\n * ```\n */\n get sandbox(): Sandbox {\n if (!this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox not initialized. Call initialize() or use DaytonaSandbox.create()\",\n \"NOT_INITIALIZED\",\n );\n }\n return this.#sandbox;\n }\n\n /**\n * Check if the sandbox is initialized and running.\n */\n get isRunning(): boolean {\n return this.#sandbox !== null;\n }\n\n /**\n * Create a new DaytonaSandbox instance.\n *\n * Note: This only creates the instance. Call `initialize()` to actually\n * create the Daytona Sandbox, or use the static `DaytonaSandbox.create()` method.\n *\n * @param options - Configuration options for the sandbox\n *\n * @example\n * ```typescript\n * // Two-step initialization\n * const sandbox = new DaytonaSandbox({ language: \"typescript\" });\n * await sandbox.initialize();\n *\n * // Or use the factory method\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n * ```\n */\n constructor(options: DaytonaSandboxOptions = {}) {\n super();\n\n // Set defaults\n this.#options = {\n language: \"typescript\",\n timeout: 300,\n ...options,\n };\n\n this.#timeout = this.#options.timeout ?? 300;\n\n // Generate temporary ID until initialized\n this.#id = `daytona-sandbox-${Date.now()}`;\n }\n\n /**\n * Initialize the sandbox by creating a new Daytona Sandbox instance.\n *\n * This method authenticates with Daytona and provisions a new sandbox.\n * After initialization, the `id` property will reflect the actual sandbox ID.\n *\n * @throws {DaytonaSandboxError} If already initialized (`ALREADY_INITIALIZED`)\n * @throws {DaytonaSandboxError} If authentication fails (`AUTHENTICATION_FAILED`)\n * @throws {DaytonaSandboxError} If sandbox creation fails (`SANDBOX_CREATION_FAILED`)\n *\n * @example\n * ```typescript\n * const sandbox = new DaytonaSandbox();\n * await sandbox.initialize();\n * console.log(`Sandbox ID: ${sandbox.id}`);\n * ```\n */\n async initialize(): Promise<void> {\n // Prevent double initialization\n if (this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox is already initialized. Each DaytonaSandbox instance can only be initialized once.\",\n \"ALREADY_INITIALIZED\",\n );\n }\n\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(\n this.#options.auth,\n this.#options.target,\n );\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n // Create Daytona client\n this.#daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n // Determine if we're creating from image or snapshot\n if (this.#options.image) {\n // Create from image (allows custom resources)\n const createOptions: {\n image: string;\n language?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n resources?: { cpu?: number; memory?: number; disk?: number };\n } = {\n image: this.#options.image,\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n if (this.#options.resources) {\n createOptions.resources = this.#options.resources;\n }\n\n // Create the sandbox from image\n this.#sandbox = await this.#daytona.create(createOptions);\n } else {\n // Create from snapshot (default, simpler approach)\n const createOptions: {\n language?: string;\n snapshot?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n } = {\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.snapshot) {\n createOptions.snapshot = this.#options.snapshot;\n }\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n // Create the sandbox from snapshot\n this.#sandbox = await this.#daytona.create(createOptions);\n }\n\n // Update ID to the actual sandbox ID\n this.#id = this.#sandbox.id;\n\n // Upload initial files if provided\n if (this.#options.initialFiles) {\n await this.#uploadInitialFiles(this.#options.initialFiles);\n }\n } catch (error) {\n throw new DaytonaSandboxError(\n `Failed to create Daytona Sandbox: ${error instanceof Error ? error.message : String(error)}`,\n \"SANDBOX_CREATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload initial files to the sandbox.\n *\n * @param files - A map of file paths to their string contents\n */\n async #uploadInitialFiles(files: Record<string, string>): Promise<void> {\n const encoder = new TextEncoder();\n const fileEntries: Array<[string, Uint8Array]> = Object.entries(files).map(\n ([path, content]) => [path, encoder.encode(content)],\n );\n\n const results = await this.uploadFiles(fileEntries);\n\n // Check for any errors during upload\n const errors = results.filter((r) => r.error !== null);\n if (errors.length > 0) {\n const errorPaths = errors.map((e) => `${e.path}: ${e.error}`).join(\", \");\n throw new DaytonaSandboxError(\n `Failed to upload initial files: ${errorPaths}`,\n \"FILE_OPERATION_FAILED\",\n );\n }\n }\n\n /**\n * Execute a command in the sandbox.\n *\n * Commands are run using the sandbox's shell.\n *\n * @param command - The shell command to execute\n * @returns Execution result with output, exit code, and truncation flag\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const result = await sandbox.execute(\"echo 'Hello World'\");\n * console.log(result.output); // \"Hello World\\n\"\n * console.log(result.exitCode); // 0\n * ```\n */\n async execute(command: string): Promise<ExecuteResponse> {\n const sandbox = this.sandbox; // Throws if not initialized\n\n try {\n const response = await sandbox.process.executeCommand(\n command,\n undefined,\n undefined,\n this.#timeout,\n );\n\n return {\n output: response.result ?? \"\",\n exitCode: response.exitCode ?? 0,\n truncated: false,\n };\n } catch (error) {\n // Check for timeout\n if (error instanceof Error && error.message.includes(\"timeout\")) {\n throw new DaytonaSandboxError(\n `Command timed out: ${command}`,\n \"COMMAND_TIMEOUT\",\n error,\n );\n }\n\n throw new DaytonaSandboxError(\n `Command execution failed: ${error instanceof Error ? error.message : String(error)}`,\n \"COMMAND_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload files to the sandbox.\n *\n * Files are written to the sandbox filesystem. Parent directories are\n * created automatically if they don't exist.\n *\n * @param files - Array of [path, content] tuples to upload\n * @returns Upload result for each file, with success or error status\n *\n * @example\n * ```typescript\n * const encoder = new TextEncoder();\n * const results = await sandbox.uploadFiles([\n * [\"src/index.js\", encoder.encode(\"console.log('Hello')\")],\n * [\"package.json\", encoder.encode('{\"name\": \"test\"}')],\n * ]);\n * ```\n */\n async uploadFiles(\n files: Array<[string, Uint8Array]>,\n ): Promise<FileUploadResponse[]> {\n const sandbox = this.sandbox; // Throws if not initialized\n const results: FileUploadResponse[] = [];\n\n for (const [path, content] of files) {\n try {\n // Ensure parent directory exists\n const parentDir = path.substring(0, path.lastIndexOf(\"/\"));\n if (parentDir) {\n await sandbox.fs.createFolder(parentDir, \"755\");\n }\n\n // Upload the file content\n const buffer = Buffer.from(content);\n await sandbox.fs.uploadFile(buffer, path);\n results.push({ path, error: null });\n } catch (error) {\n results.push({ path, error: this.#mapError(error) });\n }\n }\n\n return results;\n }\n\n /**\n * Download files from the sandbox.\n *\n * Each file is read individually, allowing partial success when some\n * files exist and others don't.\n *\n * @param paths - Array of file paths to download\n * @returns Download result for each file, with content or error\n *\n * @example\n * ```typescript\n * const results = await sandbox.downloadFiles([\"src/index.js\", \"missing.txt\"]);\n * for (const result of results) {\n * if (result.content) {\n * console.log(new TextDecoder().decode(result.content));\n * } else {\n * console.error(`Error: ${result.error}`);\n * }\n * }\n * ```\n */\n async downloadFiles(paths: string[]): Promise<FileDownloadResponse[]> {\n const sandbox = this.sandbox; // Throws if not initialized\n const results: FileDownloadResponse[] = [];\n\n for (const path of paths) {\n try {\n const buffer = await sandbox.fs.downloadFile(path);\n results.push({\n path,\n content: new Uint8Array(buffer),\n error: null,\n });\n } catch (error) {\n results.push({\n path,\n content: null,\n error: this.#mapError(error),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Close the sandbox and release all resources.\n *\n * After closing, the sandbox cannot be used again. The sandbox is deleted\n * from Daytona's infrastructure.\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"npm run build\");\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\n async close(): Promise<void> {\n if (this.#sandbox) {\n try {\n await this.#sandbox.delete();\n } finally {\n this.#sandbox = null;\n this.#daytona = null;\n }\n }\n }\n\n /**\n * Stop the sandbox without deleting it.\n *\n * The sandbox can be restarted later using `start()`.\n *\n * @example\n * ```typescript\n * await sandbox.stop();\n * // Later...\n * await sandbox.start();\n * ```\n */\n async stop(): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.stop();\n }\n }\n\n /**\n * Start a stopped sandbox.\n *\n * @param timeout - Maximum time to wait in seconds (default: 60)\n *\n * @example\n * ```typescript\n * await sandbox.start();\n * console.log(\"Sandbox is now running\");\n * ```\n */\n async start(timeout: number = 60): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.start(timeout);\n }\n }\n\n /**\n * Forcefully terminate and delete the sandbox.\n *\n * Use this when you need to immediately stop the sandbox.\n *\n * @example\n * ```typescript\n * await sandbox.kill();\n * ```\n */\n async kill(): Promise<void> {\n await this.close();\n }\n\n /**\n * Get the working directory path inside the sandbox.\n *\n * @returns The absolute path to the sandbox working directory\n *\n * @example\n * ```typescript\n * const workDir = await sandbox.getWorkDir();\n * console.log(`Working directory: ${workDir}`);\n * ```\n */\n async getWorkDir(): Promise<string> {\n const sandbox = this.sandbox;\n const workDir = await sandbox.getWorkDir();\n return workDir ?? \"/home/daytona\";\n }\n\n /**\n * Get the user's home directory path inside the sandbox.\n *\n * @returns The absolute path to the user's home directory\n *\n * @example\n * ```typescript\n * const homeDir = await sandbox.getUserHomeDir();\n * console.log(`Home directory: ${homeDir}`);\n * ```\n */\n async getUserHomeDir(): Promise<string> {\n const sandbox = this.sandbox;\n const homeDir = await sandbox.getUserHomeDir();\n return homeDir ?? \"/home/daytona\";\n }\n\n /**\n * Set the sandbox from an existing Daytona Sandbox instance.\n * Used internally by the static `connect()` method.\n */\n #setFromExisting(\n daytona: Daytona,\n existingSandbox: Sandbox,\n sandboxId: string,\n ): void {\n this.#daytona = daytona;\n this.#sandbox = existingSandbox;\n this.#id = sandboxId;\n }\n\n /**\n * Map Daytona SDK errors to standardized FileOperationError codes.\n *\n * @param error - The error from the Daytona SDK\n * @returns A standardized error code\n */\n #mapError(error: unknown): FileOperationError {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n if (msg.includes(\"not found\") || msg.includes(\"enoent\")) {\n return \"file_not_found\";\n }\n if (msg.includes(\"permission\") || msg.includes(\"eacces\")) {\n return \"permission_denied\";\n }\n if (msg.includes(\"directory\") || msg.includes(\"eisdir\")) {\n return \"is_directory\";\n }\n }\n\n return \"invalid_path\";\n }\n\n // ============================================================================\n // Static Factory Methods\n // ============================================================================\n\n /**\n * Create and initialize a new DaytonaSandbox in one step.\n *\n * This is the recommended way to create a sandbox. It combines\n * construction and initialization into a single async operation.\n *\n * @param options - Configuration options for the sandbox\n * @returns An initialized and ready-to-use sandbox\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * cpu: 2,\n * memory: 4,\n * });\n * ```\n */\n static async create(\n options?: DaytonaSandboxOptions,\n ): Promise<DaytonaSandbox> {\n const sandbox = new DaytonaSandbox(options);\n await sandbox.initialize();\n return sandbox;\n }\n\n /**\n * Connect to an existing sandbox by ID.\n *\n * This allows you to resume working with a sandbox that was created\n * earlier or that is still running.\n *\n * @param sandboxId - The ID of the sandbox to connect to\n * @param options - Optional auth configuration (for API key)\n * @returns A connected sandbox instance\n *\n * @example\n * ```typescript\n * // Resume a sandbox from a stored ID\n * const sandbox = await DaytonaSandbox.connect(\"sandbox-abc123\");\n * const result = await sandbox.execute(\"ls -la\");\n * ```\n */\n static async connect(\n sandboxId: string,\n options?: Pick<DaytonaSandboxOptions, \"auth\" | \"target\" | \"timeout\">,\n ): Promise<DaytonaSandbox> {\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(options?.auth, options?.target);\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n const daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n const existingSandbox = await daytona.get(sandboxId);\n\n const daytonaSandbox = new DaytonaSandbox(options);\n // Set the existing sandbox directly (bypass initialize)\n daytonaSandbox.#setFromExisting(daytona, existingSandbox, sandboxId);\n\n return daytonaSandbox;\n } catch (error) {\n throw new DaytonaSandboxError(\n `Sandbox not found: ${sandboxId}`,\n \"SANDBOX_NOT_FOUND\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Async factory function type for creating Daytona Sandbox instances.\n *\n * This is similar to BackendFactory but supports async creation,\n * which is required for Daytona Sandbox since initialization is async.\n */\nexport type AsyncDaytonaSandboxFactory = () => Promise<DaytonaSandbox>;\n\n/**\n * Create an async factory function that creates a new Daytona Sandbox per invocation.\n *\n * Each call to the factory will create and initialize a new sandbox.\n * This is useful when you want fresh, isolated environments for each\n * agent invocation.\n *\n * **Important**: This returns an async factory. For use with middleware that\n * requires synchronous BackendFactory, use `createDaytonaSandboxFactoryFromSandbox()`\n * with a pre-created sandbox instead.\n *\n * @param options - Optional configuration for sandbox creation\n * @returns An async factory function that creates new sandboxes\n *\n * @example\n * ```typescript\n * import { DaytonaSandbox, createDaytonaSandboxFactory } from \"@langchain/daytona\";\n *\n * // Create a factory for new sandboxes\n * const factory = createDaytonaSandboxFactory({ language: \"typescript\" });\n *\n * // Each call creates a new sandbox\n * const sandbox1 = await factory();\n * const sandbox2 = await factory();\n *\n * try {\n * // Use sandboxes...\n * } finally {\n * await sandbox1.close();\n * await sandbox2.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactory(\n options?: DaytonaSandboxOptions,\n): AsyncDaytonaSandboxFactory {\n return async () => {\n return await DaytonaSandbox.create(options);\n };\n}\n\n/**\n * Create a backend factory that reuses an existing Daytona Sandbox.\n *\n * This allows multiple agent invocations to share the same sandbox,\n * avoiding the startup overhead of creating new sandboxes.\n *\n * Important: You are responsible for managing the sandbox lifecycle\n * (calling `close()` when done).\n *\n * @param sandbox - An existing DaytonaSandbox instance (must be initialized)\n * @returns A BackendFactory that returns the provided sandbox\n *\n * @example\n * ```typescript\n * import { createDeepAgent, createFilesystemMiddleware } from \"deepagents\";\n * import { DaytonaSandbox, createDaytonaSandboxFactoryFromSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n *\n * try {\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant.\",\n * middlewares: [\n * createFilesystemMiddleware({\n * backend: createDaytonaSandboxFactoryFromSandbox(sandbox),\n * }),\n * ],\n * });\n *\n * await agent.invoke({ messages: [...] });\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactoryFromSandbox(\n sandbox: DaytonaSandbox,\n): BackendFactory {\n return () => sandbox;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["SandboxError","BaseSandbox","#id","#sandbox","#daytona","#options","#timeout","Daytona","#uploadInitialFiles","#mapError","#setFromExisting"],"sources":["../src/auth.ts","../src/types.ts","../src/sandbox.ts"],"sourcesContent":["/**\n * Authentication utilities for Daytona Sandbox.\n *\n * This module provides authentication credential resolution for the Daytona SDK.\n *\n * @packageDocumentation\n */\n\nimport type { DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Authentication credentials for Daytona API.\n */\nexport interface DaytonaCredentials {\n /** Daytona API key */\n apiKey: string;\n\n /** Daytona API URL */\n apiUrl: string;\n\n /** Target region */\n target?: string;\n}\n\n/** Default Daytona API URL */\nconst DEFAULT_API_URL = \"https://app.daytona.io/api\";\n\n/**\n * Get the API key for Daytona API.\n *\n * Authentication is resolved in the following priority order:\n *\n * 1. **Explicit API key**: If `options.apiKey` is provided, it is used directly.\n * 2. **DAYTONA_API_KEY**: Environment variable for Daytona API key.\n *\n * If no API key is found, an error is thrown with setup instructions.\n *\n * ## Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API key string\n * @throws {Error} If no API key is available\n *\n * @example\n * ```typescript\n * // With explicit API key\n * const apiKey = getAuthApiKey({ apiKey: \"my-api-key\" });\n *\n * // Using environment variables (auto-detected)\n * const apiKey = getAuthApiKey();\n *\n * // From DaytonaSandboxOptions\n * const options: DaytonaSandboxOptions = {\n * auth: { apiKey: \"my-api-key\" }\n * };\n * const apiKey = getAuthApiKey(options.auth);\n * ```\n */\nexport function getAuthApiKey(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API key in options\n if (options?.apiKey) {\n return options.apiKey;\n }\n\n // Priority 2: DAYTONA_API_KEY environment variable\n const apiKey = process.env.DAYTONA_API_KEY;\n if (apiKey) {\n return apiKey;\n }\n\n // No API key found - throw descriptive error\n throw new Error(\n \"Daytona authentication required. Provide an API key using one of these methods:\\n\\n\" +\n \"1. Set DAYTONA_API_KEY environment variable:\\n\" +\n \" Get your API key from https://app.daytona.io\\n\" +\n \" Run: export DAYTONA_API_KEY=your_api_key_here\\n\\n\" +\n \"2. Pass API key directly in options:\\n\" +\n \" new DaytonaSandbox({ auth: { apiKey: '...' } })\",\n );\n}\n\n/**\n * Get the API URL for Daytona API.\n *\n * URL is resolved in the following priority order:\n *\n * 1. **Explicit API URL**: If `options.apiUrl` is provided, it is used directly.\n * 2. **DAYTONA_API_URL**: Environment variable for Daytona API URL.\n * 3. **Default**: Uses the default Daytona API URL.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API URL string\n */\nexport function getAuthApiUrl(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API URL in options\n if (options?.apiUrl) {\n return options.apiUrl;\n }\n\n // Priority 2: DAYTONA_API_URL environment variable\n const apiUrl = process.env.DAYTONA_API_URL;\n if (apiUrl) {\n return apiUrl;\n }\n\n // Priority 3: Default URL\n return DEFAULT_API_URL;\n}\n\n/**\n * Get authentication credentials for Daytona API.\n *\n * This function returns the credentials needed for the Daytona SDK.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @param target - Optional target region\n * @returns Complete authentication credentials\n * @throws {Error} If no API key is available\n */\nexport function getAuthCredentials(\n options?: DaytonaSandboxOptions[\"auth\"],\n target?: string,\n): DaytonaCredentials {\n return {\n apiKey: getAuthApiKey(options),\n apiUrl: getAuthApiUrl(options),\n target: target ?? process.env.DAYTONA_TARGET,\n };\n}\n","/**\n * Type definitions for the Daytona Sandbox backend.\n *\n * This module contains all type definitions for the @langchain/daytona package,\n * including options and error types.\n */\n\nimport { type SandboxErrorCode, SandboxError } from \"deepagents\";\n\n/**\n * Supported target regions for Daytona sandboxes.\n *\n * - `us`: United States\n * - `eu`: Europe\n */\nexport type DaytonaSandboxTarget = \"us\" | \"eu\";\n\n/**\n * Configuration options for creating a Daytona Sandbox.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * timeout: 300, // 5 minutes\n * target: \"us\",\n * };\n * ```\n */\nexport interface DaytonaSandboxOptions {\n /**\n * Primary language for code execution in the sandbox.\n *\n * Determines the runtime environment and code execution tooling.\n *\n * @default \"typescript\"\n */\n language?: \"typescript\" | \"python\" | \"javascript\";\n\n /**\n * Custom environment variables to set in the sandbox.\n *\n * These variables will be available to all commands and code executed\n * in the sandbox.\n *\n * @example\n * ```typescript\n * envVars: {\n * NODE_ENV: \"development\",\n * API_KEY: \"secret\"\n * }\n * ```\n */\n envVars?: Record<string, string>;\n\n /**\n * Resource allocation for the sandbox.\n *\n * When specifying resources, you must also specify an `image`.\n * Resources cannot be customized when using the default snapshot-based sandbox.\n *\n * @example\n * ```typescript\n * resources: { cpu: 2, memory: 4, disk: 20 }\n * ```\n */\n resources?: {\n /** Number of CPUs to allocate */\n cpu?: number;\n /** Amount of memory in GiB */\n memory?: number;\n /** Amount of disk space in GiB */\n disk?: number;\n };\n\n /**\n * Custom Docker image to use for the sandbox.\n *\n * When specified, creates a sandbox from this image instead of the default snapshot.\n * This is required when you want to customize resources.\n *\n * @example \"node:20\" or \"python:3.12\"\n */\n image?: string;\n\n /**\n * Snapshot name to use for the sandbox.\n *\n * When specified, creates a sandbox from this snapshot.\n * Cannot be used together with `image`.\n */\n snapshot?: string;\n\n /**\n * Target region where the sandbox will be created.\n *\n * @default \"us\"\n */\n target?: DaytonaSandboxTarget;\n\n /**\n * Auto-stop interval in minutes.\n *\n * The sandbox will automatically stop after being idle for this duration.\n * Set to 0 to disable auto-stop.\n *\n * @default 15\n */\n autoStopInterval?: number;\n\n /**\n * Default timeout for command execution in seconds.\n *\n * @default 300 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Custom labels to attach to the sandbox.\n *\n * Labels can be used for organizing and filtering sandboxes.\n */\n labels?: Record<string, string>;\n\n /**\n * Initial files to create in the sandbox after initialization.\n *\n * A map of file paths to their contents. Files will be created\n * in the sandbox filesystem before any commands are executed.\n * Parent directories are created automatically.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * initialFiles: {\n * \"/app/index.js\": \"console.log('Hello')\",\n * \"/app/package.json\": '{\"name\": \"test\"}',\n * },\n * };\n * ```\n */\n initialFiles?: Record<string, string>;\n\n /**\n * Authentication configuration for Daytona API.\n *\n * ### Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * Or pass the API key directly in this auth configuration.\n */\n auth?: {\n /**\n * Daytona API key.\n * If not provided, reads from `DAYTONA_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Daytona API URL.\n * If not provided, reads from `DAYTONA_API_URL` environment variable\n * or uses the default Daytona API URL.\n *\n * @default \"https://app.daytona.io/api\"\n */\n apiUrl?: string;\n };\n}\n\n/**\n * Error codes for Daytona Sandbox operations.\n *\n * Used to identify specific error conditions and handle them appropriately.\n */\nexport type DaytonaSandboxErrorCode =\n | SandboxErrorCode\n /** Authentication failed - check API key configuration */\n | \"AUTHENTICATION_FAILED\"\n /** Failed to create sandbox - check options and quotas */\n | \"SANDBOX_CREATION_FAILED\"\n /** Sandbox not found - may have been deleted or expired */\n | \"SANDBOX_NOT_FOUND\"\n /** Sandbox is not in started state */\n | \"SANDBOX_NOT_STARTED\"\n /** Resource limits exceeded (CPU, memory, storage) */\n | \"RESOURCE_LIMIT_EXCEEDED\";\n\nconst DAYTONA_SANDBOX_ERROR_SYMBOL = Symbol.for(\"daytona.sandbox.error\");\n\n/**\n * Custom error class for Daytona Sandbox operations.\n *\n * Provides structured error information including:\n * - Human-readable message\n * - Error code for programmatic handling\n * - Original cause for debugging\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"some command\");\n * } catch (error) {\n * if (error instanceof DaytonaSandboxError) {\n * switch (error.code) {\n * case \"NOT_INITIALIZED\":\n * await sandbox.initialize();\n * break;\n * case \"COMMAND_TIMEOUT\":\n * console.error(\"Command took too long\");\n * break;\n * default:\n * throw error;\n * }\n * }\n * }\n * ```\n */\nexport class DaytonaSandboxError extends SandboxError {\n /** Symbol for identifying sandbox error instances */\n [DAYTONA_SANDBOX_ERROR_SYMBOL] = true as const;\n\n /** Error name for instanceof checks and logging */\n override readonly name = \"DaytonaSandboxError\";\n\n /**\n * Creates a new DaytonaSandboxError.\n *\n * @param message - Human-readable error description\n * @param code - Structured error code for programmatic handling\n * @param cause - Original error that caused this error (for debugging)\n */\n constructor(\n message: string,\n public readonly code: DaytonaSandboxErrorCode,\n public override readonly cause?: Error,\n ) {\n super(message, code as SandboxErrorCode, cause);\n // Maintain proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, DaytonaSandboxError.prototype);\n }\n\n /**\n * Checks if the error is an instance of DaytonaSandboxError.\n *\n * @param error - The error to check\n * @returns True if the error is an instance of DaytonaSandboxError, false otherwise\n */\n static isInstance(error: unknown): error is DaytonaSandboxError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as Record<symbol, unknown>)[DAYTONA_SANDBOX_ERROR_SYMBOL] === true\n );\n }\n}\n","/* eslint-disable no-instanceof/no-instanceof */\n/**\n * Daytona Sandbox implementation of the SandboxBackendProtocol.\n *\n * This module provides a Daytona Sandbox backend for deepagents, enabling agents\n * to execute commands, read/write files, and manage isolated sandbox environments\n * using Daytona's infrastructure.\n *\n * @packageDocumentation\n */\n\nimport { Daytona, type Sandbox } from \"@daytonaio/sdk\";\nimport {\n BaseSandbox,\n type ExecuteResponse,\n type FileDownloadResponse,\n type FileOperationError,\n type FileUploadResponse,\n type BackendFactory,\n} from \"deepagents\";\n\nimport { getAuthCredentials } from \"./auth.js\";\nimport { DaytonaSandboxError, type DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Daytona Sandbox backend for deepagents.\n *\n * Extends `BaseSandbox` to provide command execution, file operations, and\n * sandbox lifecycle management using Daytona's SDK.\n *\n * ## Basic Usage\n *\n * ```typescript\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * timeout: 300,\n * });\n *\n * try {\n * // Execute commands\n * const result = await sandbox.execute(\"node --version\");\n * console.log(result.output);\n * } finally {\n * // Always cleanup\n * await sandbox.close();\n * }\n * ```\n *\n * ## Using with DeepAgent\n *\n * ```typescript\n * import { createDeepAgent } from \"deepagents\";\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * const sandbox = await DaytonaSandbox.create();\n *\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant with sandbox access.\",\n * backend: sandbox,\n * });\n * ```\n */\nexport class DaytonaSandbox extends BaseSandbox {\n /** Private reference to the Daytona client */\n #daytona: Daytona | null = null;\n\n /** Private reference to the underlying Daytona Sandbox instance */\n #sandbox: Sandbox | null = null;\n\n /** Configuration options for this sandbox */\n #options: DaytonaSandboxOptions;\n\n /** Unique identifier for this sandbox instance */\n #id: string;\n\n /** Default timeout for command execution in seconds */\n #timeout: number;\n\n /**\n * Get the unique identifier for this sandbox.\n *\n * Before initialization, returns a temporary ID.\n * After initialization, returns the actual Daytona sandbox ID.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * Get the underlying Daytona Sandbox instance.\n *\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create();\n * const daytonaSdk = sandbox.sandbox; // Access the raw SDK\n * ```\n */\n get instance(): Sandbox {\n if (!this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox not initialized. Call initialize() or use DaytonaSandbox.create()\",\n \"NOT_INITIALIZED\",\n );\n }\n return this.#sandbox;\n }\n\n /**\n * Get the underlying Daytona client instance.\n *\n * @throws {DaytonaSandboxError} If the client is not initialized\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create();\n * const daytonaClient = sandbox.client; // Access the raw Daytona client\n * ```\n */\n get client(): Daytona {\n if (!this.#daytona) {\n throw new DaytonaSandboxError(\n \"Daytona client not initialized. Call initialize() or use DaytonaSandbox.create()\",\n \"NOT_INITIALIZED\",\n );\n }\n return this.#daytona;\n }\n\n /**\n * Check if the sandbox is initialized and running.\n */\n get isRunning(): boolean {\n return this.#sandbox !== null;\n }\n\n /**\n * Create a new DaytonaSandbox instance.\n *\n * Note: This only creates the instance. Call `initialize()` to actually\n * create the Daytona Sandbox, or use the static `DaytonaSandbox.create()` method.\n *\n * @param options - Configuration options for the sandbox\n *\n * @example\n * ```typescript\n * // Two-step initialization\n * const sandbox = new DaytonaSandbox({ language: \"typescript\" });\n * await sandbox.initialize();\n *\n * // Or use the factory method\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n * ```\n */\n constructor(options: DaytonaSandboxOptions = {}) {\n super();\n\n // Set defaults\n this.#options = {\n language: \"typescript\",\n timeout: 300,\n ...options,\n };\n\n this.#timeout = this.#options.timeout ?? 300;\n\n // Generate temporary ID until initialized\n this.#id = `daytona-sandbox-${Date.now()}`;\n }\n\n /**\n * Initialize the sandbox by creating a new Daytona Sandbox instance.\n *\n * This method authenticates with Daytona and provisions a new sandbox.\n * After initialization, the `id` property will reflect the actual sandbox ID.\n *\n * @throws {DaytonaSandboxError} If already initialized (`ALREADY_INITIALIZED`)\n * @throws {DaytonaSandboxError} If authentication fails (`AUTHENTICATION_FAILED`)\n * @throws {DaytonaSandboxError} If sandbox creation fails (`SANDBOX_CREATION_FAILED`)\n *\n * @example\n * ```typescript\n * const sandbox = new DaytonaSandbox();\n * await sandbox.initialize();\n * console.log(`Sandbox ID: ${sandbox.id}`);\n * ```\n */\n async initialize(): Promise<void> {\n // Prevent double initialization\n if (this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox is already initialized. Each DaytonaSandbox instance can only be initialized once.\",\n \"ALREADY_INITIALIZED\",\n );\n }\n\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(\n this.#options.auth,\n this.#options.target,\n );\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n // Create Daytona client\n this.#daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n // Determine if we're creating from image or snapshot\n if (this.#options.image) {\n // Create from image (allows custom resources)\n const createOptions: {\n image: string;\n language?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n resources?: { cpu?: number; memory?: number; disk?: number };\n } = {\n image: this.#options.image,\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n if (this.#options.resources) {\n createOptions.resources = this.#options.resources;\n }\n\n // Create the sandbox from image\n this.#sandbox = await this.#daytona.create(createOptions);\n } else {\n // Create from snapshot (default, simpler approach)\n const createOptions: {\n language?: string;\n snapshot?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n } = {\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.snapshot) {\n createOptions.snapshot = this.#options.snapshot;\n }\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n // Create the sandbox from snapshot\n this.#sandbox = await this.#daytona.create(createOptions);\n }\n\n // Update ID to the actual sandbox ID\n this.#id = this.#sandbox.id;\n\n // Upload initial files if provided\n if (this.#options.initialFiles) {\n await this.#uploadInitialFiles(this.#options.initialFiles);\n }\n } catch (error) {\n throw new DaytonaSandboxError(\n `Failed to create Daytona Sandbox: ${error instanceof Error ? error.message : String(error)}`,\n \"SANDBOX_CREATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload initial files to the sandbox.\n *\n * @param files - A map of file paths to their string contents\n */\n async #uploadInitialFiles(files: Record<string, string>): Promise<void> {\n const encoder = new TextEncoder();\n const fileEntries: Array<[string, Uint8Array]> = Object.entries(files).map(\n ([path, content]) => [path, encoder.encode(content)],\n );\n\n const results = await this.uploadFiles(fileEntries);\n\n // Check for any errors during upload\n const errors = results.filter((r) => r.error !== null);\n if (errors.length > 0) {\n const errorPaths = errors.map((e) => `${e.path}: ${e.error}`).join(\", \");\n throw new DaytonaSandboxError(\n `Failed to upload initial files: ${errorPaths}`,\n \"FILE_OPERATION_FAILED\",\n );\n }\n }\n\n /**\n * Execute a command in the sandbox.\n *\n * Commands are run using the sandbox's shell.\n *\n * @param command - The shell command to execute\n * @returns Execution result with output, exit code, and truncation flag\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const result = await sandbox.execute(\"echo 'Hello World'\");\n * console.log(result.output); // \"Hello World\\n\"\n * console.log(result.exitCode); // 0\n * ```\n */\n async execute(command: string): Promise<ExecuteResponse> {\n const sandbox = this.instance; // Throws if not initialized\n\n try {\n const response = await sandbox.process.executeCommand(\n command,\n undefined,\n undefined,\n this.#timeout,\n );\n\n return {\n output: response.result ?? \"\",\n exitCode: response.exitCode ?? 0,\n truncated: false,\n };\n } catch (error) {\n // Check for timeout\n if (error instanceof Error && error.message.includes(\"timeout\")) {\n throw new DaytonaSandboxError(\n `Command timed out: ${command}`,\n \"COMMAND_TIMEOUT\",\n error,\n );\n }\n\n throw new DaytonaSandboxError(\n `Command execution failed: ${error instanceof Error ? error.message : String(error)}`,\n \"COMMAND_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload files to the sandbox.\n *\n * Files are written to the sandbox filesystem. Parent directories are\n * created automatically if they don't exist.\n *\n * @param files - Array of [path, content] tuples to upload\n * @returns Upload result for each file, with success or error status\n *\n * @example\n * ```typescript\n * const encoder = new TextEncoder();\n * const results = await sandbox.uploadFiles([\n * [\"src/index.js\", encoder.encode(\"console.log('Hello')\")],\n * [\"package.json\", encoder.encode('{\"name\": \"test\"}')],\n * ]);\n * ```\n */\n async uploadFiles(\n files: Array<[string, Uint8Array]>,\n ): Promise<FileUploadResponse[]> {\n const sandbox = this.instance; // Throws if not initialized\n const results: FileUploadResponse[] = [];\n\n for (const [path, content] of files) {\n try {\n // Ensure parent directory exists\n const parentDir = path.substring(0, path.lastIndexOf(\"/\"));\n if (parentDir) {\n await sandbox.fs.createFolder(parentDir, \"755\");\n }\n\n // Upload the file content\n const buffer = Buffer.from(content);\n await sandbox.fs.uploadFile(buffer, path);\n results.push({ path, error: null });\n } catch (error) {\n results.push({ path, error: this.#mapError(error) });\n }\n }\n\n return results;\n }\n\n /**\n * Download files from the sandbox.\n *\n * Each file is read individually, allowing partial success when some\n * files exist and others don't.\n *\n * @param paths - Array of file paths to download\n * @returns Download result for each file, with content or error\n *\n * @example\n * ```typescript\n * const results = await sandbox.downloadFiles([\"src/index.js\", \"missing.txt\"]);\n * for (const result of results) {\n * if (result.content) {\n * console.log(new TextDecoder().decode(result.content));\n * } else {\n * console.error(`Error: ${result.error}`);\n * }\n * }\n * ```\n */\n async downloadFiles(paths: string[]): Promise<FileDownloadResponse[]> {\n const sandbox = this.instance; // Throws if not initialized\n const results: FileDownloadResponse[] = [];\n\n for (const path of paths) {\n try {\n const buffer = await sandbox.fs.downloadFile(path);\n results.push({\n path,\n content: new Uint8Array(buffer),\n error: null,\n });\n } catch (error) {\n results.push({\n path,\n content: null,\n error: this.#mapError(error),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Close the sandbox and release all resources.\n *\n * After closing, the sandbox cannot be used again. The sandbox is deleted\n * from Daytona's infrastructure.\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"npm run build\");\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\n async close(): Promise<void> {\n if (this.#sandbox) {\n try {\n await this.#sandbox.delete();\n } finally {\n this.#sandbox = null;\n this.#daytona = null;\n }\n }\n }\n\n /**\n * Stop the sandbox without deleting it.\n *\n * The sandbox can be restarted later using `start()`.\n *\n * @example\n * ```typescript\n * await sandbox.stop();\n * // Later...\n * await sandbox.start();\n * ```\n */\n async stop(): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.stop();\n }\n }\n\n /**\n * Start a stopped sandbox.\n *\n * @param timeout - Maximum time to wait in seconds (default: 60)\n *\n * @example\n * ```typescript\n * await sandbox.start();\n * console.log(\"Sandbox is now running\");\n * ```\n */\n async start(timeout: number = 60): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.start(timeout);\n }\n }\n\n /**\n * Forcefully terminate and delete the sandbox.\n *\n * Use this when you need to immediately stop the sandbox.\n *\n * @example\n * ```typescript\n * await sandbox.kill();\n * ```\n */\n async kill(): Promise<void> {\n await this.close();\n }\n\n /**\n * Get the working directory path inside the sandbox.\n *\n * @returns The absolute path to the sandbox working directory\n *\n * @example\n * ```typescript\n * const workDir = await sandbox.getWorkDir();\n * console.log(`Working directory: ${workDir}`);\n * ```\n */\n async getWorkDir(): Promise<string> {\n const sandbox = this.instance;\n const workDir = await sandbox.getWorkDir();\n return workDir ?? \"/home/daytona\";\n }\n\n /**\n * Get the user's home directory path inside the sandbox.\n *\n * @returns The absolute path to the user's home directory\n *\n * @example\n * ```typescript\n * const homeDir = await sandbox.getUserHomeDir();\n * console.log(`Home directory: ${homeDir}`);\n * ```\n */\n async getUserHomeDir(): Promise<string> {\n const sandbox = this.instance;\n const homeDir = await sandbox.getUserHomeDir();\n return homeDir ?? \"/home/daytona\";\n }\n\n /**\n * Set the sandbox from an existing Daytona Sandbox instance.\n * Used internally by the static `connect()` method.\n */\n #setFromExisting(\n daytona: Daytona,\n existingSandbox: Sandbox,\n sandboxId: string,\n ): void {\n this.#daytona = daytona;\n this.#sandbox = existingSandbox;\n this.#id = sandboxId;\n }\n\n /**\n * Map Daytona SDK errors to standardized FileOperationError codes.\n *\n * @param error - The error from the Daytona SDK\n * @returns A standardized error code\n */\n #mapError(error: unknown): FileOperationError {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n if (msg.includes(\"not found\") || msg.includes(\"enoent\")) {\n return \"file_not_found\";\n }\n if (msg.includes(\"permission\") || msg.includes(\"eacces\")) {\n return \"permission_denied\";\n }\n if (msg.includes(\"directory\") || msg.includes(\"eisdir\")) {\n return \"is_directory\";\n }\n }\n\n return \"invalid_path\";\n }\n\n /**\n * Create and initialize a new DaytonaSandbox in one step.\n *\n * This is the recommended way to create a sandbox. It combines\n * construction and initialization into a single async operation.\n *\n * @param options - Configuration options for the sandbox\n * @returns An initialized and ready-to-use sandbox\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * cpu: 2,\n * memory: 4,\n * });\n * ```\n */\n static async create(\n options?: DaytonaSandboxOptions,\n ): Promise<DaytonaSandbox> {\n const sandbox = new DaytonaSandbox(options);\n await sandbox.initialize();\n return sandbox;\n }\n\n /**\n * Delete all sandboxes matching the given labels.\n *\n * This is useful for cleaning up stale sandboxes from previous test runs\n * or CI pipelines that may not have shut down cleanly.\n *\n * @param labels - Label key-value pairs to filter sandboxes\n * @param options - Optional auth configuration\n * @returns The number of sandboxes that were deleted\n *\n * @example\n * ```typescript\n * // Clean up all integration-test sandboxes\n * const deleted = await DaytonaSandbox.deleteAll({\n * purpose: \"integration-test\",\n * package: \"@langchain/daytona\",\n * });\n * console.log(`Deleted ${deleted} stale sandboxes`);\n * ```\n */\n static async deleteAll(\n labels: Record<string, string>,\n options?: Pick<DaytonaSandboxOptions, \"auth\" | \"target\">,\n ): Promise<number> {\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(options?.auth, options?.target);\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n const daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n const { items } = await daytona.list(labels);\n\n const results = await Promise.all(\n items.map((sandbox) =>\n daytona\n .delete(sandbox)\n .then(() => true)\n .catch(() => false),\n ),\n );\n\n return results.filter(Boolean).length;\n }\n\n /**\n * Connect to an existing sandbox by ID.\n *\n * This allows you to resume working with a sandbox that was created\n * earlier or that is still running.\n *\n * @param sandboxId - The ID of the sandbox to connect to\n * @param options - Optional auth configuration (for API key)\n * @returns A connected sandbox instance\n *\n * @example\n * ```typescript\n * // Resume a sandbox from a stored ID\n * const sandbox = await DaytonaSandbox.connect(\"sandbox-abc123\");\n * const result = await sandbox.execute(\"ls -la\");\n * ```\n */\n static async fromId(\n id: string,\n options?: Pick<DaytonaSandboxOptions, \"auth\" | \"target\" | \"timeout\">,\n ): Promise<DaytonaSandbox> {\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(options?.auth, options?.target);\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n const daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n const existingSandbox = await daytona.get(id);\n\n const daytonaSandbox = new DaytonaSandbox(options);\n // Set the existing sandbox directly (bypass initialize)\n daytonaSandbox.#setFromExisting(daytona, existingSandbox, id);\n\n return daytonaSandbox;\n } catch (error) {\n throw new DaytonaSandboxError(\n `Sandbox not found: ${id}`,\n \"SANDBOX_NOT_FOUND\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Get a running sandbox by name from a deployed app.\n *\n * @param name - The name of the sandbox\n * @param options - Optional auth configuration\n * @returns A connected sandbox instance\n */\n static async fromName(\n name: string,\n options?: Pick<DaytonaSandboxOptions, \"auth\">,\n ): Promise<DaytonaSandbox> {\n return DaytonaSandbox.fromId(name, options);\n }\n}\n\n/**\n * Async factory function type for creating Daytona Sandbox instances.\n *\n * This is similar to BackendFactory but supports async creation,\n * which is required for Daytona Sandbox since initialization is async.\n */\nexport type AsyncDaytonaSandboxFactory = () => Promise<DaytonaSandbox>;\n\n/**\n * Create an async factory function that creates a new Daytona Sandbox per invocation.\n *\n * Each call to the factory will create and initialize a new sandbox.\n * This is useful when you want fresh, isolated environments for each\n * agent invocation.\n *\n * **Important**: This returns an async factory. For use with middleware that\n * requires synchronous BackendFactory, use `createDaytonaSandboxFactoryFromSandbox()`\n * with a pre-created sandbox instead.\n *\n * @param options - Optional configuration for sandbox creation\n * @returns An async factory function that creates new sandboxes\n *\n * @example\n * ```typescript\n * import { DaytonaSandbox, createDaytonaSandboxFactory } from \"@langchain/daytona\";\n *\n * // Create a factory for new sandboxes\n * const factory = createDaytonaSandboxFactory({ language: \"typescript\" });\n *\n * // Each call creates a new sandbox\n * const sandbox1 = await factory();\n * const sandbox2 = await factory();\n *\n * try {\n * // Use sandboxes...\n * } finally {\n * await sandbox1.close();\n * await sandbox2.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactory(\n options?: DaytonaSandboxOptions,\n): AsyncDaytonaSandboxFactory {\n return async () => {\n return await DaytonaSandbox.create(options);\n };\n}\n\n/**\n * Create a backend factory that reuses an existing Daytona Sandbox.\n *\n * This allows multiple agent invocations to share the same sandbox,\n * avoiding the startup overhead of creating new sandboxes.\n *\n * Important: You are responsible for managing the sandbox lifecycle\n * (calling `close()` when done).\n *\n * @param sandbox - An existing DaytonaSandbox instance (must be initialized)\n * @returns A BackendFactory that returns the provided sandbox\n *\n * @example\n * ```typescript\n * import { createDeepAgent, createFilesystemMiddleware } from \"deepagents\";\n * import { DaytonaSandbox, createDaytonaSandboxFactoryFromSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n *\n * try {\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant.\",\n * middlewares: [\n * createFilesystemMiddleware({\n * backend: createDaytonaSandboxFactoryFromSandbox(sandbox),\n * }),\n * ],\n * });\n *\n * await agent.invoke({ messages: [...] });\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactoryFromSandbox(\n sandbox: DaytonaSandbox,\n): BackendFactory {\n return () => sandbox;\n}\n"],"mappings":"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"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import { Sandbox } from "@daytonaio/sdk";
|
|
2
|
-
import { BackendFactory, BaseSandbox, ExecuteResponse, FileDownloadResponse, FileUploadResponse } from "deepagents";
|
|
1
|
+
import { Daytona, Sandbox } from "@daytonaio/sdk";
|
|
2
|
+
import { BackendFactory, BaseSandbox, ExecuteResponse, FileDownloadResponse, FileUploadResponse, SandboxError, SandboxErrorCode } from "deepagents";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Type definitions for the Daytona Sandbox backend.
|
|
7
|
-
*
|
|
8
|
-
* This module contains all type definitions for the @langchain/daytona package,
|
|
9
|
-
* including options and error types.
|
|
10
|
-
*/
|
|
11
5
|
/**
|
|
12
6
|
* Supported target regions for Daytona sandboxes.
|
|
13
7
|
*
|
|
@@ -162,7 +156,8 @@ interface DaytonaSandboxOptions {
|
|
|
162
156
|
*
|
|
163
157
|
* Used to identify specific error conditions and handle them appropriately.
|
|
164
158
|
*/
|
|
165
|
-
type DaytonaSandboxErrorCode =
|
|
159
|
+
type DaytonaSandboxErrorCode = SandboxErrorCode /** Authentication failed - check API key configuration */ | "AUTHENTICATION_FAILED" /** Failed to create sandbox - check options and quotas */ | "SANDBOX_CREATION_FAILED" /** Sandbox not found - may have been deleted or expired */ | "SANDBOX_NOT_FOUND" /** Sandbox is not in started state */ | "SANDBOX_NOT_STARTED" /** Resource limits exceeded (CPU, memory, storage) */ | "RESOURCE_LIMIT_EXCEEDED";
|
|
160
|
+
declare const DAYTONA_SANDBOX_ERROR_SYMBOL: unique symbol;
|
|
166
161
|
/**
|
|
167
162
|
* Custom error class for Daytona Sandbox operations.
|
|
168
163
|
*
|
|
@@ -191,9 +186,11 @@ type DaytonaSandboxErrorCode = /** Sandbox has not been initialized - call initi
|
|
|
191
186
|
* }
|
|
192
187
|
* ```
|
|
193
188
|
*/
|
|
194
|
-
declare class DaytonaSandboxError extends
|
|
189
|
+
declare class DaytonaSandboxError extends SandboxError {
|
|
195
190
|
readonly code: DaytonaSandboxErrorCode;
|
|
196
191
|
readonly cause?: Error | undefined;
|
|
192
|
+
/** Symbol for identifying sandbox error instances */
|
|
193
|
+
[DAYTONA_SANDBOX_ERROR_SYMBOL]: true;
|
|
197
194
|
/** Error name for instanceof checks and logging */
|
|
198
195
|
readonly name = "DaytonaSandboxError";
|
|
199
196
|
/**
|
|
@@ -204,6 +201,13 @@ declare class DaytonaSandboxError extends Error {
|
|
|
204
201
|
* @param cause - Original error that caused this error (for debugging)
|
|
205
202
|
*/
|
|
206
203
|
constructor(message: string, code: DaytonaSandboxErrorCode, cause?: Error | undefined);
|
|
204
|
+
/**
|
|
205
|
+
* Checks if the error is an instance of DaytonaSandboxError.
|
|
206
|
+
*
|
|
207
|
+
* @param error - The error to check
|
|
208
|
+
* @returns True if the error is an instance of DaytonaSandboxError, false otherwise
|
|
209
|
+
*/
|
|
210
|
+
static isInstance(error: unknown): error is DaytonaSandboxError;
|
|
207
211
|
}
|
|
208
212
|
//#endregion
|
|
209
213
|
//#region src/sandbox.d.ts
|
|
@@ -269,7 +273,19 @@ declare class DaytonaSandbox extends BaseSandbox {
|
|
|
269
273
|
* const daytonaSdk = sandbox.sandbox; // Access the raw SDK
|
|
270
274
|
* ```
|
|
271
275
|
*/
|
|
272
|
-
get
|
|
276
|
+
get instance(): Sandbox;
|
|
277
|
+
/**
|
|
278
|
+
* Get the underlying Daytona client instance.
|
|
279
|
+
*
|
|
280
|
+
* @throws {DaytonaSandboxError} If the client is not initialized
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* const sandbox = await DaytonaSandbox.create();
|
|
285
|
+
* const daytonaClient = sandbox.client; // Access the raw Daytona client
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
get client(): Daytona;
|
|
273
289
|
/**
|
|
274
290
|
* Check if the sandbox is initialized and running.
|
|
275
291
|
*/
|
|
@@ -464,6 +480,27 @@ declare class DaytonaSandbox extends BaseSandbox {
|
|
|
464
480
|
* ```
|
|
465
481
|
*/
|
|
466
482
|
static create(options?: DaytonaSandboxOptions): Promise<DaytonaSandbox>;
|
|
483
|
+
/**
|
|
484
|
+
* Delete all sandboxes matching the given labels.
|
|
485
|
+
*
|
|
486
|
+
* This is useful for cleaning up stale sandboxes from previous test runs
|
|
487
|
+
* or CI pipelines that may not have shut down cleanly.
|
|
488
|
+
*
|
|
489
|
+
* @param labels - Label key-value pairs to filter sandboxes
|
|
490
|
+
* @param options - Optional auth configuration
|
|
491
|
+
* @returns The number of sandboxes that were deleted
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```typescript
|
|
495
|
+
* // Clean up all integration-test sandboxes
|
|
496
|
+
* const deleted = await DaytonaSandbox.deleteAll({
|
|
497
|
+
* purpose: "integration-test",
|
|
498
|
+
* package: "@langchain/daytona",
|
|
499
|
+
* });
|
|
500
|
+
* console.log(`Deleted ${deleted} stale sandboxes`);
|
|
501
|
+
* ```
|
|
502
|
+
*/
|
|
503
|
+
static deleteAll(labels: Record<string, string>, options?: Pick<DaytonaSandboxOptions, "auth" | "target">): Promise<number>;
|
|
467
504
|
/**
|
|
468
505
|
* Connect to an existing sandbox by ID.
|
|
469
506
|
*
|
|
@@ -481,7 +518,15 @@ declare class DaytonaSandbox extends BaseSandbox {
|
|
|
481
518
|
* const result = await sandbox.execute("ls -la");
|
|
482
519
|
* ```
|
|
483
520
|
*/
|
|
484
|
-
static
|
|
521
|
+
static fromId(id: string, options?: Pick<DaytonaSandboxOptions, "auth" | "target" | "timeout">): Promise<DaytonaSandbox>;
|
|
522
|
+
/**
|
|
523
|
+
* Get a running sandbox by name from a deployed app.
|
|
524
|
+
*
|
|
525
|
+
* @param name - The name of the sandbox
|
|
526
|
+
* @param options - Optional auth configuration
|
|
527
|
+
* @returns A connected sandbox instance
|
|
528
|
+
*/
|
|
529
|
+
static fromName(name: string, options?: Pick<DaytonaSandboxOptions, "auth">): Promise<DaytonaSandbox>;
|
|
485
530
|
}
|
|
486
531
|
/**
|
|
487
532
|
* Async factory function type for creating Daytona Sandbox instances.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,7 @@
|
|
|
1
|
-
import { Sandbox } from "@daytonaio/sdk";
|
|
2
|
-
import { BackendFactory, BaseSandbox, ExecuteResponse, FileDownloadResponse, FileUploadResponse } from "deepagents";
|
|
1
|
+
import { Daytona, Sandbox } from "@daytonaio/sdk";
|
|
2
|
+
import { BackendFactory, BaseSandbox, ExecuteResponse, FileDownloadResponse, FileUploadResponse, SandboxError, SandboxErrorCode } from "deepagents";
|
|
3
3
|
|
|
4
4
|
//#region src/types.d.ts
|
|
5
|
-
/**
|
|
6
|
-
* Type definitions for the Daytona Sandbox backend.
|
|
7
|
-
*
|
|
8
|
-
* This module contains all type definitions for the @langchain/daytona package,
|
|
9
|
-
* including options and error types.
|
|
10
|
-
*/
|
|
11
5
|
/**
|
|
12
6
|
* Supported target regions for Daytona sandboxes.
|
|
13
7
|
*
|
|
@@ -162,7 +156,8 @@ interface DaytonaSandboxOptions {
|
|
|
162
156
|
*
|
|
163
157
|
* Used to identify specific error conditions and handle them appropriately.
|
|
164
158
|
*/
|
|
165
|
-
type DaytonaSandboxErrorCode =
|
|
159
|
+
type DaytonaSandboxErrorCode = SandboxErrorCode /** Authentication failed - check API key configuration */ | "AUTHENTICATION_FAILED" /** Failed to create sandbox - check options and quotas */ | "SANDBOX_CREATION_FAILED" /** Sandbox not found - may have been deleted or expired */ | "SANDBOX_NOT_FOUND" /** Sandbox is not in started state */ | "SANDBOX_NOT_STARTED" /** Resource limits exceeded (CPU, memory, storage) */ | "RESOURCE_LIMIT_EXCEEDED";
|
|
160
|
+
declare const DAYTONA_SANDBOX_ERROR_SYMBOL: unique symbol;
|
|
166
161
|
/**
|
|
167
162
|
* Custom error class for Daytona Sandbox operations.
|
|
168
163
|
*
|
|
@@ -191,9 +186,11 @@ type DaytonaSandboxErrorCode = /** Sandbox has not been initialized - call initi
|
|
|
191
186
|
* }
|
|
192
187
|
* ```
|
|
193
188
|
*/
|
|
194
|
-
declare class DaytonaSandboxError extends
|
|
189
|
+
declare class DaytonaSandboxError extends SandboxError {
|
|
195
190
|
readonly code: DaytonaSandboxErrorCode;
|
|
196
191
|
readonly cause?: Error | undefined;
|
|
192
|
+
/** Symbol for identifying sandbox error instances */
|
|
193
|
+
[DAYTONA_SANDBOX_ERROR_SYMBOL]: true;
|
|
197
194
|
/** Error name for instanceof checks and logging */
|
|
198
195
|
readonly name = "DaytonaSandboxError";
|
|
199
196
|
/**
|
|
@@ -204,6 +201,13 @@ declare class DaytonaSandboxError extends Error {
|
|
|
204
201
|
* @param cause - Original error that caused this error (for debugging)
|
|
205
202
|
*/
|
|
206
203
|
constructor(message: string, code: DaytonaSandboxErrorCode, cause?: Error | undefined);
|
|
204
|
+
/**
|
|
205
|
+
* Checks if the error is an instance of DaytonaSandboxError.
|
|
206
|
+
*
|
|
207
|
+
* @param error - The error to check
|
|
208
|
+
* @returns True if the error is an instance of DaytonaSandboxError, false otherwise
|
|
209
|
+
*/
|
|
210
|
+
static isInstance(error: unknown): error is DaytonaSandboxError;
|
|
207
211
|
}
|
|
208
212
|
//#endregion
|
|
209
213
|
//#region src/sandbox.d.ts
|
|
@@ -269,7 +273,19 @@ declare class DaytonaSandbox extends BaseSandbox {
|
|
|
269
273
|
* const daytonaSdk = sandbox.sandbox; // Access the raw SDK
|
|
270
274
|
* ```
|
|
271
275
|
*/
|
|
272
|
-
get
|
|
276
|
+
get instance(): Sandbox;
|
|
277
|
+
/**
|
|
278
|
+
* Get the underlying Daytona client instance.
|
|
279
|
+
*
|
|
280
|
+
* @throws {DaytonaSandboxError} If the client is not initialized
|
|
281
|
+
*
|
|
282
|
+
* @example
|
|
283
|
+
* ```typescript
|
|
284
|
+
* const sandbox = await DaytonaSandbox.create();
|
|
285
|
+
* const daytonaClient = sandbox.client; // Access the raw Daytona client
|
|
286
|
+
* ```
|
|
287
|
+
*/
|
|
288
|
+
get client(): Daytona;
|
|
273
289
|
/**
|
|
274
290
|
* Check if the sandbox is initialized and running.
|
|
275
291
|
*/
|
|
@@ -464,6 +480,27 @@ declare class DaytonaSandbox extends BaseSandbox {
|
|
|
464
480
|
* ```
|
|
465
481
|
*/
|
|
466
482
|
static create(options?: DaytonaSandboxOptions): Promise<DaytonaSandbox>;
|
|
483
|
+
/**
|
|
484
|
+
* Delete all sandboxes matching the given labels.
|
|
485
|
+
*
|
|
486
|
+
* This is useful for cleaning up stale sandboxes from previous test runs
|
|
487
|
+
* or CI pipelines that may not have shut down cleanly.
|
|
488
|
+
*
|
|
489
|
+
* @param labels - Label key-value pairs to filter sandboxes
|
|
490
|
+
* @param options - Optional auth configuration
|
|
491
|
+
* @returns The number of sandboxes that were deleted
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```typescript
|
|
495
|
+
* // Clean up all integration-test sandboxes
|
|
496
|
+
* const deleted = await DaytonaSandbox.deleteAll({
|
|
497
|
+
* purpose: "integration-test",
|
|
498
|
+
* package: "@langchain/daytona",
|
|
499
|
+
* });
|
|
500
|
+
* console.log(`Deleted ${deleted} stale sandboxes`);
|
|
501
|
+
* ```
|
|
502
|
+
*/
|
|
503
|
+
static deleteAll(labels: Record<string, string>, options?: Pick<DaytonaSandboxOptions, "auth" | "target">): Promise<number>;
|
|
467
504
|
/**
|
|
468
505
|
* Connect to an existing sandbox by ID.
|
|
469
506
|
*
|
|
@@ -481,7 +518,15 @@ declare class DaytonaSandbox extends BaseSandbox {
|
|
|
481
518
|
* const result = await sandbox.execute("ls -la");
|
|
482
519
|
* ```
|
|
483
520
|
*/
|
|
484
|
-
static
|
|
521
|
+
static fromId(id: string, options?: Pick<DaytonaSandboxOptions, "auth" | "target" | "timeout">): Promise<DaytonaSandbox>;
|
|
522
|
+
/**
|
|
523
|
+
* Get a running sandbox by name from a deployed app.
|
|
524
|
+
*
|
|
525
|
+
* @param name - The name of the sandbox
|
|
526
|
+
* @param options - Optional auth configuration
|
|
527
|
+
* @returns A connected sandbox instance
|
|
528
|
+
*/
|
|
529
|
+
static fromName(name: string, options?: Pick<DaytonaSandboxOptions, "auth">): Promise<DaytonaSandbox>;
|
|
485
530
|
}
|
|
486
531
|
/**
|
|
487
532
|
* Async factory function type for creating Daytona Sandbox instances.
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Daytona } from "@daytonaio/sdk";
|
|
2
|
-
import { BaseSandbox } from "deepagents";
|
|
2
|
+
import { BaseSandbox, SandboxError } from "deepagents";
|
|
3
3
|
|
|
4
4
|
//#region src/auth.ts
|
|
5
5
|
/** Default Daytona API URL */
|
|
@@ -85,6 +85,13 @@ function getAuthCredentials(options, target) {
|
|
|
85
85
|
//#endregion
|
|
86
86
|
//#region src/types.ts
|
|
87
87
|
/**
|
|
88
|
+
* Type definitions for the Daytona Sandbox backend.
|
|
89
|
+
*
|
|
90
|
+
* This module contains all type definitions for the @langchain/daytona package,
|
|
91
|
+
* including options and error types.
|
|
92
|
+
*/
|
|
93
|
+
const DAYTONA_SANDBOX_ERROR_SYMBOL = Symbol.for("daytona.sandbox.error");
|
|
94
|
+
/**
|
|
88
95
|
* Custom error class for Daytona Sandbox operations.
|
|
89
96
|
*
|
|
90
97
|
* Provides structured error information including:
|
|
@@ -112,7 +119,9 @@ function getAuthCredentials(options, target) {
|
|
|
112
119
|
* }
|
|
113
120
|
* ```
|
|
114
121
|
*/
|
|
115
|
-
var DaytonaSandboxError = class DaytonaSandboxError extends
|
|
122
|
+
var DaytonaSandboxError = class DaytonaSandboxError extends SandboxError {
|
|
123
|
+
/** Symbol for identifying sandbox error instances */
|
|
124
|
+
[DAYTONA_SANDBOX_ERROR_SYMBOL] = true;
|
|
116
125
|
/** Error name for instanceof checks and logging */
|
|
117
126
|
name = "DaytonaSandboxError";
|
|
118
127
|
/**
|
|
@@ -123,11 +132,20 @@ var DaytonaSandboxError = class DaytonaSandboxError extends Error {
|
|
|
123
132
|
* @param cause - Original error that caused this error (for debugging)
|
|
124
133
|
*/
|
|
125
134
|
constructor(message, code, cause) {
|
|
126
|
-
super(message);
|
|
135
|
+
super(message, code, cause);
|
|
127
136
|
this.code = code;
|
|
128
137
|
this.cause = cause;
|
|
129
138
|
Object.setPrototypeOf(this, DaytonaSandboxError.prototype);
|
|
130
139
|
}
|
|
140
|
+
/**
|
|
141
|
+
* Checks if the error is an instance of DaytonaSandboxError.
|
|
142
|
+
*
|
|
143
|
+
* @param error - The error to check
|
|
144
|
+
* @returns True if the error is an instance of DaytonaSandboxError, false otherwise
|
|
145
|
+
*/
|
|
146
|
+
static isInstance(error) {
|
|
147
|
+
return typeof error === "object" && error !== null && error[DAYTONA_SANDBOX_ERROR_SYMBOL] === true;
|
|
148
|
+
}
|
|
131
149
|
};
|
|
132
150
|
|
|
133
151
|
//#endregion
|
|
@@ -214,11 +232,26 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
214
232
|
* const daytonaSdk = sandbox.sandbox; // Access the raw SDK
|
|
215
233
|
* ```
|
|
216
234
|
*/
|
|
217
|
-
get
|
|
235
|
+
get instance() {
|
|
218
236
|
if (!this.#sandbox) throw new DaytonaSandboxError("Sandbox not initialized. Call initialize() or use DaytonaSandbox.create()", "NOT_INITIALIZED");
|
|
219
237
|
return this.#sandbox;
|
|
220
238
|
}
|
|
221
239
|
/**
|
|
240
|
+
* Get the underlying Daytona client instance.
|
|
241
|
+
*
|
|
242
|
+
* @throws {DaytonaSandboxError} If the client is not initialized
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```typescript
|
|
246
|
+
* const sandbox = await DaytonaSandbox.create();
|
|
247
|
+
* const daytonaClient = sandbox.client; // Access the raw Daytona client
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
get client() {
|
|
251
|
+
if (!this.#daytona) throw new DaytonaSandboxError("Daytona client not initialized. Call initialize() or use DaytonaSandbox.create()", "NOT_INITIALIZED");
|
|
252
|
+
return this.#daytona;
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
222
255
|
* Check if the sandbox is initialized and running.
|
|
223
256
|
*/
|
|
224
257
|
get isRunning() {
|
|
@@ -335,7 +368,7 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
335
368
|
* ```
|
|
336
369
|
*/
|
|
337
370
|
async execute(command) {
|
|
338
|
-
const sandbox = this.
|
|
371
|
+
const sandbox = this.instance;
|
|
339
372
|
try {
|
|
340
373
|
const response = await sandbox.process.executeCommand(command, void 0, void 0, this.#timeout);
|
|
341
374
|
return {
|
|
@@ -367,7 +400,7 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
367
400
|
* ```
|
|
368
401
|
*/
|
|
369
402
|
async uploadFiles(files) {
|
|
370
|
-
const sandbox = this.
|
|
403
|
+
const sandbox = this.instance;
|
|
371
404
|
const results = [];
|
|
372
405
|
for (const [path, content] of files) try {
|
|
373
406
|
const parentDir = path.substring(0, path.lastIndexOf("/"));
|
|
@@ -408,7 +441,7 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
408
441
|
* ```
|
|
409
442
|
*/
|
|
410
443
|
async downloadFiles(paths) {
|
|
411
|
-
const sandbox = this.
|
|
444
|
+
const sandbox = this.instance;
|
|
412
445
|
const results = [];
|
|
413
446
|
for (const path of paths) try {
|
|
414
447
|
const buffer = await sandbox.fs.downloadFile(path);
|
|
@@ -503,7 +536,7 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
503
536
|
* ```
|
|
504
537
|
*/
|
|
505
538
|
async getWorkDir() {
|
|
506
|
-
return await this.
|
|
539
|
+
return await this.instance.getWorkDir() ?? "/home/daytona";
|
|
507
540
|
}
|
|
508
541
|
/**
|
|
509
542
|
* Get the user's home directory path inside the sandbox.
|
|
@@ -517,7 +550,7 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
517
550
|
* ```
|
|
518
551
|
*/
|
|
519
552
|
async getUserHomeDir() {
|
|
520
|
-
return await this.
|
|
553
|
+
return await this.instance.getUserHomeDir() ?? "/home/daytona";
|
|
521
554
|
}
|
|
522
555
|
/**
|
|
523
556
|
* Set the sandbox from an existing Daytona Sandbox instance.
|
|
@@ -567,6 +600,41 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
567
600
|
return sandbox;
|
|
568
601
|
}
|
|
569
602
|
/**
|
|
603
|
+
* Delete all sandboxes matching the given labels.
|
|
604
|
+
*
|
|
605
|
+
* This is useful for cleaning up stale sandboxes from previous test runs
|
|
606
|
+
* or CI pipelines that may not have shut down cleanly.
|
|
607
|
+
*
|
|
608
|
+
* @param labels - Label key-value pairs to filter sandboxes
|
|
609
|
+
* @param options - Optional auth configuration
|
|
610
|
+
* @returns The number of sandboxes that were deleted
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* ```typescript
|
|
614
|
+
* // Clean up all integration-test sandboxes
|
|
615
|
+
* const deleted = await DaytonaSandbox.deleteAll({
|
|
616
|
+
* purpose: "integration-test",
|
|
617
|
+
* package: "@langchain/daytona",
|
|
618
|
+
* });
|
|
619
|
+
* console.log(`Deleted ${deleted} stale sandboxes`);
|
|
620
|
+
* ```
|
|
621
|
+
*/
|
|
622
|
+
static async deleteAll(labels, options) {
|
|
623
|
+
let credentials;
|
|
624
|
+
try {
|
|
625
|
+
credentials = getAuthCredentials(options?.auth, options?.target);
|
|
626
|
+
} catch (error) {
|
|
627
|
+
throw new DaytonaSandboxError("Failed to authenticate with Daytona. Check your API key configuration.", "AUTHENTICATION_FAILED", error instanceof Error ? error : void 0);
|
|
628
|
+
}
|
|
629
|
+
const daytona = new Daytona({
|
|
630
|
+
apiKey: credentials.apiKey,
|
|
631
|
+
apiUrl: credentials.apiUrl,
|
|
632
|
+
target: credentials.target
|
|
633
|
+
});
|
|
634
|
+
const { items } = await daytona.list(labels);
|
|
635
|
+
return (await Promise.all(items.map((sandbox) => daytona.delete(sandbox).then(() => true).catch(() => false)))).filter(Boolean).length;
|
|
636
|
+
}
|
|
637
|
+
/**
|
|
570
638
|
* Connect to an existing sandbox by ID.
|
|
571
639
|
*
|
|
572
640
|
* This allows you to resume working with a sandbox that was created
|
|
@@ -583,7 +651,7 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
583
651
|
* const result = await sandbox.execute("ls -la");
|
|
584
652
|
* ```
|
|
585
653
|
*/
|
|
586
|
-
static async
|
|
654
|
+
static async fromId(id, options) {
|
|
587
655
|
let credentials;
|
|
588
656
|
try {
|
|
589
657
|
credentials = getAuthCredentials(options?.auth, options?.target);
|
|
@@ -596,14 +664,24 @@ var DaytonaSandbox = class DaytonaSandbox extends BaseSandbox {
|
|
|
596
664
|
apiUrl: credentials.apiUrl,
|
|
597
665
|
target: credentials.target
|
|
598
666
|
});
|
|
599
|
-
const existingSandbox = await daytona.get(
|
|
667
|
+
const existingSandbox = await daytona.get(id);
|
|
600
668
|
const daytonaSandbox = new DaytonaSandbox(options);
|
|
601
|
-
daytonaSandbox.#setFromExisting(daytona, existingSandbox,
|
|
669
|
+
daytonaSandbox.#setFromExisting(daytona, existingSandbox, id);
|
|
602
670
|
return daytonaSandbox;
|
|
603
671
|
} catch (error) {
|
|
604
|
-
throw new DaytonaSandboxError(`Sandbox not found: ${
|
|
672
|
+
throw new DaytonaSandboxError(`Sandbox not found: ${id}`, "SANDBOX_NOT_FOUND", error instanceof Error ? error : void 0);
|
|
605
673
|
}
|
|
606
674
|
}
|
|
675
|
+
/**
|
|
676
|
+
* Get a running sandbox by name from a deployed app.
|
|
677
|
+
*
|
|
678
|
+
* @param name - The name of the sandbox
|
|
679
|
+
* @param options - Optional auth configuration
|
|
680
|
+
* @returns A connected sandbox instance
|
|
681
|
+
*/
|
|
682
|
+
static async fromName(name, options) {
|
|
683
|
+
return DaytonaSandbox.fromId(name, options);
|
|
684
|
+
}
|
|
607
685
|
};
|
|
608
686
|
/**
|
|
609
687
|
* Create an async factory function that creates a new Daytona Sandbox per invocation.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["#id","#sandbox","#options","#timeout","#daytona","#uploadInitialFiles","#mapError","#setFromExisting"],"sources":["../src/auth.ts","../src/types.ts","../src/sandbox.ts"],"sourcesContent":["/**\n * Authentication utilities for Daytona Sandbox.\n *\n * This module provides authentication credential resolution for the Daytona SDK.\n *\n * @packageDocumentation\n */\n\nimport type { DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Authentication credentials for Daytona API.\n */\nexport interface DaytonaCredentials {\n /** Daytona API key */\n apiKey: string;\n\n /** Daytona API URL */\n apiUrl: string;\n\n /** Target region */\n target?: string;\n}\n\n/** Default Daytona API URL */\nconst DEFAULT_API_URL = \"https://app.daytona.io/api\";\n\n/**\n * Get the API key for Daytona API.\n *\n * Authentication is resolved in the following priority order:\n *\n * 1. **Explicit API key**: If `options.apiKey` is provided, it is used directly.\n * 2. **DAYTONA_API_KEY**: Environment variable for Daytona API key.\n *\n * If no API key is found, an error is thrown with setup instructions.\n *\n * ## Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API key string\n * @throws {Error} If no API key is available\n *\n * @example\n * ```typescript\n * // With explicit API key\n * const apiKey = getAuthApiKey({ apiKey: \"my-api-key\" });\n *\n * // Using environment variables (auto-detected)\n * const apiKey = getAuthApiKey();\n *\n * // From DaytonaSandboxOptions\n * const options: DaytonaSandboxOptions = {\n * auth: { apiKey: \"my-api-key\" }\n * };\n * const apiKey = getAuthApiKey(options.auth);\n * ```\n */\nexport function getAuthApiKey(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API key in options\n if (options?.apiKey) {\n return options.apiKey;\n }\n\n // Priority 2: DAYTONA_API_KEY environment variable\n const apiKey = process.env.DAYTONA_API_KEY;\n if (apiKey) {\n return apiKey;\n }\n\n // No API key found - throw descriptive error\n throw new Error(\n \"Daytona authentication required. Provide an API key using one of these methods:\\n\\n\" +\n \"1. Set DAYTONA_API_KEY environment variable:\\n\" +\n \" Get your API key from https://app.daytona.io\\n\" +\n \" Run: export DAYTONA_API_KEY=your_api_key_here\\n\\n\" +\n \"2. Pass API key directly in options:\\n\" +\n \" new DaytonaSandbox({ auth: { apiKey: '...' } })\",\n );\n}\n\n/**\n * Get the API URL for Daytona API.\n *\n * URL is resolved in the following priority order:\n *\n * 1. **Explicit API URL**: If `options.apiUrl` is provided, it is used directly.\n * 2. **DAYTONA_API_URL**: Environment variable for Daytona API URL.\n * 3. **Default**: Uses the default Daytona API URL.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API URL string\n */\nexport function getAuthApiUrl(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API URL in options\n if (options?.apiUrl) {\n return options.apiUrl;\n }\n\n // Priority 2: DAYTONA_API_URL environment variable\n const apiUrl = process.env.DAYTONA_API_URL;\n if (apiUrl) {\n return apiUrl;\n }\n\n // Priority 3: Default URL\n return DEFAULT_API_URL;\n}\n\n/**\n * Get authentication credentials for Daytona API.\n *\n * This function returns the credentials needed for the Daytona SDK.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @param target - Optional target region\n * @returns Complete authentication credentials\n * @throws {Error} If no API key is available\n */\nexport function getAuthCredentials(\n options?: DaytonaSandboxOptions[\"auth\"],\n target?: string,\n): DaytonaCredentials {\n return {\n apiKey: getAuthApiKey(options),\n apiUrl: getAuthApiUrl(options),\n target: target ?? process.env.DAYTONA_TARGET,\n };\n}\n","/**\n * Type definitions for the Daytona Sandbox backend.\n *\n * This module contains all type definitions for the @langchain/daytona package,\n * including options and error types.\n */\n\n/**\n * Supported target regions for Daytona sandboxes.\n *\n * - `us`: United States\n * - `eu`: Europe\n */\nexport type DaytonaSandboxTarget = \"us\" | \"eu\";\n\n/**\n * Configuration options for creating a Daytona Sandbox.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * timeout: 300, // 5 minutes\n * target: \"us\",\n * };\n * ```\n */\nexport interface DaytonaSandboxOptions {\n /**\n * Primary language for code execution in the sandbox.\n *\n * Determines the runtime environment and code execution tooling.\n *\n * @default \"typescript\"\n */\n language?: \"typescript\" | \"python\" | \"javascript\";\n\n /**\n * Custom environment variables to set in the sandbox.\n *\n * These variables will be available to all commands and code executed\n * in the sandbox.\n *\n * @example\n * ```typescript\n * envVars: {\n * NODE_ENV: \"development\",\n * API_KEY: \"secret\"\n * }\n * ```\n */\n envVars?: Record<string, string>;\n\n /**\n * Resource allocation for the sandbox.\n *\n * When specifying resources, you must also specify an `image`.\n * Resources cannot be customized when using the default snapshot-based sandbox.\n *\n * @example\n * ```typescript\n * resources: { cpu: 2, memory: 4, disk: 20 }\n * ```\n */\n resources?: {\n /** Number of CPUs to allocate */\n cpu?: number;\n /** Amount of memory in GiB */\n memory?: number;\n /** Amount of disk space in GiB */\n disk?: number;\n };\n\n /**\n * Custom Docker image to use for the sandbox.\n *\n * When specified, creates a sandbox from this image instead of the default snapshot.\n * This is required when you want to customize resources.\n *\n * @example \"node:20\" or \"python:3.12\"\n */\n image?: string;\n\n /**\n * Snapshot name to use for the sandbox.\n *\n * When specified, creates a sandbox from this snapshot.\n * Cannot be used together with `image`.\n */\n snapshot?: string;\n\n /**\n * Target region where the sandbox will be created.\n *\n * @default \"us\"\n */\n target?: DaytonaSandboxTarget;\n\n /**\n * Auto-stop interval in minutes.\n *\n * The sandbox will automatically stop after being idle for this duration.\n * Set to 0 to disable auto-stop.\n *\n * @default 15\n */\n autoStopInterval?: number;\n\n /**\n * Default timeout for command execution in seconds.\n *\n * @default 300 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Custom labels to attach to the sandbox.\n *\n * Labels can be used for organizing and filtering sandboxes.\n */\n labels?: Record<string, string>;\n\n /**\n * Initial files to create in the sandbox after initialization.\n *\n * A map of file paths to their contents. Files will be created\n * in the sandbox filesystem before any commands are executed.\n * Parent directories are created automatically.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * initialFiles: {\n * \"/app/index.js\": \"console.log('Hello')\",\n * \"/app/package.json\": '{\"name\": \"test\"}',\n * },\n * };\n * ```\n */\n initialFiles?: Record<string, string>;\n\n /**\n * Authentication configuration for Daytona API.\n *\n * ### Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * Or pass the API key directly in this auth configuration.\n */\n auth?: {\n /**\n * Daytona API key.\n * If not provided, reads from `DAYTONA_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Daytona API URL.\n * If not provided, reads from `DAYTONA_API_URL` environment variable\n * or uses the default Daytona API URL.\n *\n * @default \"https://app.daytona.io/api\"\n */\n apiUrl?: string;\n };\n}\n\n/**\n * Error codes for Daytona Sandbox operations.\n *\n * Used to identify specific error conditions and handle them appropriately.\n */\nexport type DaytonaSandboxErrorCode =\n /** Sandbox has not been initialized - call initialize() first */\n | \"NOT_INITIALIZED\"\n /** Sandbox is already initialized - cannot initialize twice */\n | \"ALREADY_INITIALIZED\"\n /** Authentication failed - check API key configuration */\n | \"AUTHENTICATION_FAILED\"\n /** Failed to create sandbox - check options and quotas */\n | \"SANDBOX_CREATION_FAILED\"\n /** Sandbox not found - may have been deleted or expired */\n | \"SANDBOX_NOT_FOUND\"\n /** Sandbox is not in started state */\n | \"SANDBOX_NOT_STARTED\"\n /** Command execution timed out */\n | \"COMMAND_TIMEOUT\"\n /** Command execution failed */\n | \"COMMAND_FAILED\"\n /** File operation (read/write) failed */\n | \"FILE_OPERATION_FAILED\"\n /** Resource limits exceeded (CPU, memory, storage) */\n | \"RESOURCE_LIMIT_EXCEEDED\";\n\n/**\n * Custom error class for Daytona Sandbox operations.\n *\n * Provides structured error information including:\n * - Human-readable message\n * - Error code for programmatic handling\n * - Original cause for debugging\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"some command\");\n * } catch (error) {\n * if (error instanceof DaytonaSandboxError) {\n * switch (error.code) {\n * case \"NOT_INITIALIZED\":\n * await sandbox.initialize();\n * break;\n * case \"COMMAND_TIMEOUT\":\n * console.error(\"Command took too long\");\n * break;\n * default:\n * throw error;\n * }\n * }\n * }\n * ```\n */\nexport class DaytonaSandboxError extends Error {\n /** Error name for instanceof checks and logging */\n override readonly name = \"DaytonaSandboxError\";\n\n /**\n * Creates a new DaytonaSandboxError.\n *\n * @param message - Human-readable error description\n * @param code - Structured error code for programmatic handling\n * @param cause - Original error that caused this error (for debugging)\n */\n constructor(\n message: string,\n public readonly code: DaytonaSandboxErrorCode,\n public override readonly cause?: Error,\n ) {\n super(message);\n // Maintain proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, DaytonaSandboxError.prototype);\n }\n}\n","/* eslint-disable no-instanceof/no-instanceof */\n/**\n * Daytona Sandbox implementation of the SandboxBackendProtocol.\n *\n * This module provides a Daytona Sandbox backend for deepagents, enabling agents\n * to execute commands, read/write files, and manage isolated sandbox environments\n * using Daytona's infrastructure.\n *\n * @packageDocumentation\n */\n\nimport { Daytona, type Sandbox } from \"@daytonaio/sdk\";\nimport {\n BaseSandbox,\n type ExecuteResponse,\n type FileDownloadResponse,\n type FileOperationError,\n type FileUploadResponse,\n type BackendFactory,\n} from \"deepagents\";\n\nimport { getAuthCredentials } from \"./auth.js\";\nimport { DaytonaSandboxError, type DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Daytona Sandbox backend for deepagents.\n *\n * Extends `BaseSandbox` to provide command execution, file operations, and\n * sandbox lifecycle management using Daytona's SDK.\n *\n * ## Basic Usage\n *\n * ```typescript\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * timeout: 300,\n * });\n *\n * try {\n * // Execute commands\n * const result = await sandbox.execute(\"node --version\");\n * console.log(result.output);\n * } finally {\n * // Always cleanup\n * await sandbox.close();\n * }\n * ```\n *\n * ## Using with DeepAgent\n *\n * ```typescript\n * import { createDeepAgent } from \"deepagents\";\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * const sandbox = await DaytonaSandbox.create();\n *\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant with sandbox access.\",\n * backend: sandbox,\n * });\n * ```\n */\nexport class DaytonaSandbox extends BaseSandbox {\n /** Private reference to the Daytona client */\n #daytona: Daytona | null = null;\n\n /** Private reference to the underlying Daytona Sandbox instance */\n #sandbox: Sandbox | null = null;\n\n /** Configuration options for this sandbox */\n #options: DaytonaSandboxOptions;\n\n /** Unique identifier for this sandbox instance */\n #id: string;\n\n /** Default timeout for command execution in seconds */\n #timeout: number;\n\n /**\n * Get the unique identifier for this sandbox.\n *\n * Before initialization, returns a temporary ID.\n * After initialization, returns the actual Daytona sandbox ID.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * Get the underlying Daytona Sandbox instance.\n *\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create();\n * const daytonaSdk = sandbox.sandbox; // Access the raw SDK\n * ```\n */\n get sandbox(): Sandbox {\n if (!this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox not initialized. Call initialize() or use DaytonaSandbox.create()\",\n \"NOT_INITIALIZED\",\n );\n }\n return this.#sandbox;\n }\n\n /**\n * Check if the sandbox is initialized and running.\n */\n get isRunning(): boolean {\n return this.#sandbox !== null;\n }\n\n /**\n * Create a new DaytonaSandbox instance.\n *\n * Note: This only creates the instance. Call `initialize()` to actually\n * create the Daytona Sandbox, or use the static `DaytonaSandbox.create()` method.\n *\n * @param options - Configuration options for the sandbox\n *\n * @example\n * ```typescript\n * // Two-step initialization\n * const sandbox = new DaytonaSandbox({ language: \"typescript\" });\n * await sandbox.initialize();\n *\n * // Or use the factory method\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n * ```\n */\n constructor(options: DaytonaSandboxOptions = {}) {\n super();\n\n // Set defaults\n this.#options = {\n language: \"typescript\",\n timeout: 300,\n ...options,\n };\n\n this.#timeout = this.#options.timeout ?? 300;\n\n // Generate temporary ID until initialized\n this.#id = `daytona-sandbox-${Date.now()}`;\n }\n\n /**\n * Initialize the sandbox by creating a new Daytona Sandbox instance.\n *\n * This method authenticates with Daytona and provisions a new sandbox.\n * After initialization, the `id` property will reflect the actual sandbox ID.\n *\n * @throws {DaytonaSandboxError} If already initialized (`ALREADY_INITIALIZED`)\n * @throws {DaytonaSandboxError} If authentication fails (`AUTHENTICATION_FAILED`)\n * @throws {DaytonaSandboxError} If sandbox creation fails (`SANDBOX_CREATION_FAILED`)\n *\n * @example\n * ```typescript\n * const sandbox = new DaytonaSandbox();\n * await sandbox.initialize();\n * console.log(`Sandbox ID: ${sandbox.id}`);\n * ```\n */\n async initialize(): Promise<void> {\n // Prevent double initialization\n if (this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox is already initialized. Each DaytonaSandbox instance can only be initialized once.\",\n \"ALREADY_INITIALIZED\",\n );\n }\n\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(\n this.#options.auth,\n this.#options.target,\n );\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n // Create Daytona client\n this.#daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n // Determine if we're creating from image or snapshot\n if (this.#options.image) {\n // Create from image (allows custom resources)\n const createOptions: {\n image: string;\n language?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n resources?: { cpu?: number; memory?: number; disk?: number };\n } = {\n image: this.#options.image,\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n if (this.#options.resources) {\n createOptions.resources = this.#options.resources;\n }\n\n // Create the sandbox from image\n this.#sandbox = await this.#daytona.create(createOptions);\n } else {\n // Create from snapshot (default, simpler approach)\n const createOptions: {\n language?: string;\n snapshot?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n } = {\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.snapshot) {\n createOptions.snapshot = this.#options.snapshot;\n }\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n // Create the sandbox from snapshot\n this.#sandbox = await this.#daytona.create(createOptions);\n }\n\n // Update ID to the actual sandbox ID\n this.#id = this.#sandbox.id;\n\n // Upload initial files if provided\n if (this.#options.initialFiles) {\n await this.#uploadInitialFiles(this.#options.initialFiles);\n }\n } catch (error) {\n throw new DaytonaSandboxError(\n `Failed to create Daytona Sandbox: ${error instanceof Error ? error.message : String(error)}`,\n \"SANDBOX_CREATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload initial files to the sandbox.\n *\n * @param files - A map of file paths to their string contents\n */\n async #uploadInitialFiles(files: Record<string, string>): Promise<void> {\n const encoder = new TextEncoder();\n const fileEntries: Array<[string, Uint8Array]> = Object.entries(files).map(\n ([path, content]) => [path, encoder.encode(content)],\n );\n\n const results = await this.uploadFiles(fileEntries);\n\n // Check for any errors during upload\n const errors = results.filter((r) => r.error !== null);\n if (errors.length > 0) {\n const errorPaths = errors.map((e) => `${e.path}: ${e.error}`).join(\", \");\n throw new DaytonaSandboxError(\n `Failed to upload initial files: ${errorPaths}`,\n \"FILE_OPERATION_FAILED\",\n );\n }\n }\n\n /**\n * Execute a command in the sandbox.\n *\n * Commands are run using the sandbox's shell.\n *\n * @param command - The shell command to execute\n * @returns Execution result with output, exit code, and truncation flag\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const result = await sandbox.execute(\"echo 'Hello World'\");\n * console.log(result.output); // \"Hello World\\n\"\n * console.log(result.exitCode); // 0\n * ```\n */\n async execute(command: string): Promise<ExecuteResponse> {\n const sandbox = this.sandbox; // Throws if not initialized\n\n try {\n const response = await sandbox.process.executeCommand(\n command,\n undefined,\n undefined,\n this.#timeout,\n );\n\n return {\n output: response.result ?? \"\",\n exitCode: response.exitCode ?? 0,\n truncated: false,\n };\n } catch (error) {\n // Check for timeout\n if (error instanceof Error && error.message.includes(\"timeout\")) {\n throw new DaytonaSandboxError(\n `Command timed out: ${command}`,\n \"COMMAND_TIMEOUT\",\n error,\n );\n }\n\n throw new DaytonaSandboxError(\n `Command execution failed: ${error instanceof Error ? error.message : String(error)}`,\n \"COMMAND_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload files to the sandbox.\n *\n * Files are written to the sandbox filesystem. Parent directories are\n * created automatically if they don't exist.\n *\n * @param files - Array of [path, content] tuples to upload\n * @returns Upload result for each file, with success or error status\n *\n * @example\n * ```typescript\n * const encoder = new TextEncoder();\n * const results = await sandbox.uploadFiles([\n * [\"src/index.js\", encoder.encode(\"console.log('Hello')\")],\n * [\"package.json\", encoder.encode('{\"name\": \"test\"}')],\n * ]);\n * ```\n */\n async uploadFiles(\n files: Array<[string, Uint8Array]>,\n ): Promise<FileUploadResponse[]> {\n const sandbox = this.sandbox; // Throws if not initialized\n const results: FileUploadResponse[] = [];\n\n for (const [path, content] of files) {\n try {\n // Ensure parent directory exists\n const parentDir = path.substring(0, path.lastIndexOf(\"/\"));\n if (parentDir) {\n await sandbox.fs.createFolder(parentDir, \"755\");\n }\n\n // Upload the file content\n const buffer = Buffer.from(content);\n await sandbox.fs.uploadFile(buffer, path);\n results.push({ path, error: null });\n } catch (error) {\n results.push({ path, error: this.#mapError(error) });\n }\n }\n\n return results;\n }\n\n /**\n * Download files from the sandbox.\n *\n * Each file is read individually, allowing partial success when some\n * files exist and others don't.\n *\n * @param paths - Array of file paths to download\n * @returns Download result for each file, with content or error\n *\n * @example\n * ```typescript\n * const results = await sandbox.downloadFiles([\"src/index.js\", \"missing.txt\"]);\n * for (const result of results) {\n * if (result.content) {\n * console.log(new TextDecoder().decode(result.content));\n * } else {\n * console.error(`Error: ${result.error}`);\n * }\n * }\n * ```\n */\n async downloadFiles(paths: string[]): Promise<FileDownloadResponse[]> {\n const sandbox = this.sandbox; // Throws if not initialized\n const results: FileDownloadResponse[] = [];\n\n for (const path of paths) {\n try {\n const buffer = await sandbox.fs.downloadFile(path);\n results.push({\n path,\n content: new Uint8Array(buffer),\n error: null,\n });\n } catch (error) {\n results.push({\n path,\n content: null,\n error: this.#mapError(error),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Close the sandbox and release all resources.\n *\n * After closing, the sandbox cannot be used again. The sandbox is deleted\n * from Daytona's infrastructure.\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"npm run build\");\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\n async close(): Promise<void> {\n if (this.#sandbox) {\n try {\n await this.#sandbox.delete();\n } finally {\n this.#sandbox = null;\n this.#daytona = null;\n }\n }\n }\n\n /**\n * Stop the sandbox without deleting it.\n *\n * The sandbox can be restarted later using `start()`.\n *\n * @example\n * ```typescript\n * await sandbox.stop();\n * // Later...\n * await sandbox.start();\n * ```\n */\n async stop(): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.stop();\n }\n }\n\n /**\n * Start a stopped sandbox.\n *\n * @param timeout - Maximum time to wait in seconds (default: 60)\n *\n * @example\n * ```typescript\n * await sandbox.start();\n * console.log(\"Sandbox is now running\");\n * ```\n */\n async start(timeout: number = 60): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.start(timeout);\n }\n }\n\n /**\n * Forcefully terminate and delete the sandbox.\n *\n * Use this when you need to immediately stop the sandbox.\n *\n * @example\n * ```typescript\n * await sandbox.kill();\n * ```\n */\n async kill(): Promise<void> {\n await this.close();\n }\n\n /**\n * Get the working directory path inside the sandbox.\n *\n * @returns The absolute path to the sandbox working directory\n *\n * @example\n * ```typescript\n * const workDir = await sandbox.getWorkDir();\n * console.log(`Working directory: ${workDir}`);\n * ```\n */\n async getWorkDir(): Promise<string> {\n const sandbox = this.sandbox;\n const workDir = await sandbox.getWorkDir();\n return workDir ?? \"/home/daytona\";\n }\n\n /**\n * Get the user's home directory path inside the sandbox.\n *\n * @returns The absolute path to the user's home directory\n *\n * @example\n * ```typescript\n * const homeDir = await sandbox.getUserHomeDir();\n * console.log(`Home directory: ${homeDir}`);\n * ```\n */\n async getUserHomeDir(): Promise<string> {\n const sandbox = this.sandbox;\n const homeDir = await sandbox.getUserHomeDir();\n return homeDir ?? \"/home/daytona\";\n }\n\n /**\n * Set the sandbox from an existing Daytona Sandbox instance.\n * Used internally by the static `connect()` method.\n */\n #setFromExisting(\n daytona: Daytona,\n existingSandbox: Sandbox,\n sandboxId: string,\n ): void {\n this.#daytona = daytona;\n this.#sandbox = existingSandbox;\n this.#id = sandboxId;\n }\n\n /**\n * Map Daytona SDK errors to standardized FileOperationError codes.\n *\n * @param error - The error from the Daytona SDK\n * @returns A standardized error code\n */\n #mapError(error: unknown): FileOperationError {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n if (msg.includes(\"not found\") || msg.includes(\"enoent\")) {\n return \"file_not_found\";\n }\n if (msg.includes(\"permission\") || msg.includes(\"eacces\")) {\n return \"permission_denied\";\n }\n if (msg.includes(\"directory\") || msg.includes(\"eisdir\")) {\n return \"is_directory\";\n }\n }\n\n return \"invalid_path\";\n }\n\n // ============================================================================\n // Static Factory Methods\n // ============================================================================\n\n /**\n * Create and initialize a new DaytonaSandbox in one step.\n *\n * This is the recommended way to create a sandbox. It combines\n * construction and initialization into a single async operation.\n *\n * @param options - Configuration options for the sandbox\n * @returns An initialized and ready-to-use sandbox\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * cpu: 2,\n * memory: 4,\n * });\n * ```\n */\n static async create(\n options?: DaytonaSandboxOptions,\n ): Promise<DaytonaSandbox> {\n const sandbox = new DaytonaSandbox(options);\n await sandbox.initialize();\n return sandbox;\n }\n\n /**\n * Connect to an existing sandbox by ID.\n *\n * This allows you to resume working with a sandbox that was created\n * earlier or that is still running.\n *\n * @param sandboxId - The ID of the sandbox to connect to\n * @param options - Optional auth configuration (for API key)\n * @returns A connected sandbox instance\n *\n * @example\n * ```typescript\n * // Resume a sandbox from a stored ID\n * const sandbox = await DaytonaSandbox.connect(\"sandbox-abc123\");\n * const result = await sandbox.execute(\"ls -la\");\n * ```\n */\n static async connect(\n sandboxId: string,\n options?: Pick<DaytonaSandboxOptions, \"auth\" | \"target\" | \"timeout\">,\n ): Promise<DaytonaSandbox> {\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(options?.auth, options?.target);\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n const daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n const existingSandbox = await daytona.get(sandboxId);\n\n const daytonaSandbox = new DaytonaSandbox(options);\n // Set the existing sandbox directly (bypass initialize)\n daytonaSandbox.#setFromExisting(daytona, existingSandbox, sandboxId);\n\n return daytonaSandbox;\n } catch (error) {\n throw new DaytonaSandboxError(\n `Sandbox not found: ${sandboxId}`,\n \"SANDBOX_NOT_FOUND\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Async factory function type for creating Daytona Sandbox instances.\n *\n * This is similar to BackendFactory but supports async creation,\n * which is required for Daytona Sandbox since initialization is async.\n */\nexport type AsyncDaytonaSandboxFactory = () => Promise<DaytonaSandbox>;\n\n/**\n * Create an async factory function that creates a new Daytona Sandbox per invocation.\n *\n * Each call to the factory will create and initialize a new sandbox.\n * This is useful when you want fresh, isolated environments for each\n * agent invocation.\n *\n * **Important**: This returns an async factory. For use with middleware that\n * requires synchronous BackendFactory, use `createDaytonaSandboxFactoryFromSandbox()`\n * with a pre-created sandbox instead.\n *\n * @param options - Optional configuration for sandbox creation\n * @returns An async factory function that creates new sandboxes\n *\n * @example\n * ```typescript\n * import { DaytonaSandbox, createDaytonaSandboxFactory } from \"@langchain/daytona\";\n *\n * // Create a factory for new sandboxes\n * const factory = createDaytonaSandboxFactory({ language: \"typescript\" });\n *\n * // Each call creates a new sandbox\n * const sandbox1 = await factory();\n * const sandbox2 = await factory();\n *\n * try {\n * // Use sandboxes...\n * } finally {\n * await sandbox1.close();\n * await sandbox2.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactory(\n options?: DaytonaSandboxOptions,\n): AsyncDaytonaSandboxFactory {\n return async () => {\n return await DaytonaSandbox.create(options);\n };\n}\n\n/**\n * Create a backend factory that reuses an existing Daytona Sandbox.\n *\n * This allows multiple agent invocations to share the same sandbox,\n * avoiding the startup overhead of creating new sandboxes.\n *\n * Important: You are responsible for managing the sandbox lifecycle\n * (calling `close()` when done).\n *\n * @param sandbox - An existing DaytonaSandbox instance (must be initialized)\n * @returns A BackendFactory that returns the provided sandbox\n *\n * @example\n * ```typescript\n * import { createDeepAgent, createFilesystemMiddleware } from \"deepagents\";\n * import { DaytonaSandbox, createDaytonaSandboxFactoryFromSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n *\n * try {\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant.\",\n * middlewares: [\n * createFilesystemMiddleware({\n * backend: createDaytonaSandboxFactoryFromSandbox(sandbox),\n * }),\n * ],\n * });\n *\n * await agent.invoke({ messages: [...] });\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactoryFromSandbox(\n sandbox: DaytonaSandbox,\n): BackendFactory {\n return () => sandbox;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["#id","#sandbox","#daytona","#options","#timeout","#uploadInitialFiles","#mapError","#setFromExisting"],"sources":["../src/auth.ts","../src/types.ts","../src/sandbox.ts"],"sourcesContent":["/**\n * Authentication utilities for Daytona Sandbox.\n *\n * This module provides authentication credential resolution for the Daytona SDK.\n *\n * @packageDocumentation\n */\n\nimport type { DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Authentication credentials for Daytona API.\n */\nexport interface DaytonaCredentials {\n /** Daytona API key */\n apiKey: string;\n\n /** Daytona API URL */\n apiUrl: string;\n\n /** Target region */\n target?: string;\n}\n\n/** Default Daytona API URL */\nconst DEFAULT_API_URL = \"https://app.daytona.io/api\";\n\n/**\n * Get the API key for Daytona API.\n *\n * Authentication is resolved in the following priority order:\n *\n * 1. **Explicit API key**: If `options.apiKey` is provided, it is used directly.\n * 2. **DAYTONA_API_KEY**: Environment variable for Daytona API key.\n *\n * If no API key is found, an error is thrown with setup instructions.\n *\n * ## Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API key string\n * @throws {Error} If no API key is available\n *\n * @example\n * ```typescript\n * // With explicit API key\n * const apiKey = getAuthApiKey({ apiKey: \"my-api-key\" });\n *\n * // Using environment variables (auto-detected)\n * const apiKey = getAuthApiKey();\n *\n * // From DaytonaSandboxOptions\n * const options: DaytonaSandboxOptions = {\n * auth: { apiKey: \"my-api-key\" }\n * };\n * const apiKey = getAuthApiKey(options.auth);\n * ```\n */\nexport function getAuthApiKey(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API key in options\n if (options?.apiKey) {\n return options.apiKey;\n }\n\n // Priority 2: DAYTONA_API_KEY environment variable\n const apiKey = process.env.DAYTONA_API_KEY;\n if (apiKey) {\n return apiKey;\n }\n\n // No API key found - throw descriptive error\n throw new Error(\n \"Daytona authentication required. Provide an API key using one of these methods:\\n\\n\" +\n \"1. Set DAYTONA_API_KEY environment variable:\\n\" +\n \" Get your API key from https://app.daytona.io\\n\" +\n \" Run: export DAYTONA_API_KEY=your_api_key_here\\n\\n\" +\n \"2. Pass API key directly in options:\\n\" +\n \" new DaytonaSandbox({ auth: { apiKey: '...' } })\",\n );\n}\n\n/**\n * Get the API URL for Daytona API.\n *\n * URL is resolved in the following priority order:\n *\n * 1. **Explicit API URL**: If `options.apiUrl` is provided, it is used directly.\n * 2. **DAYTONA_API_URL**: Environment variable for Daytona API URL.\n * 3. **Default**: Uses the default Daytona API URL.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @returns The API URL string\n */\nexport function getAuthApiUrl(options?: DaytonaSandboxOptions[\"auth\"]): string {\n // Priority 1: Explicit API URL in options\n if (options?.apiUrl) {\n return options.apiUrl;\n }\n\n // Priority 2: DAYTONA_API_URL environment variable\n const apiUrl = process.env.DAYTONA_API_URL;\n if (apiUrl) {\n return apiUrl;\n }\n\n // Priority 3: Default URL\n return DEFAULT_API_URL;\n}\n\n/**\n * Get authentication credentials for Daytona API.\n *\n * This function returns the credentials needed for the Daytona SDK.\n *\n * @param options - Optional authentication configuration from DaytonaSandboxOptions\n * @param target - Optional target region\n * @returns Complete authentication credentials\n * @throws {Error} If no API key is available\n */\nexport function getAuthCredentials(\n options?: DaytonaSandboxOptions[\"auth\"],\n target?: string,\n): DaytonaCredentials {\n return {\n apiKey: getAuthApiKey(options),\n apiUrl: getAuthApiUrl(options),\n target: target ?? process.env.DAYTONA_TARGET,\n };\n}\n","/**\n * Type definitions for the Daytona Sandbox backend.\n *\n * This module contains all type definitions for the @langchain/daytona package,\n * including options and error types.\n */\n\nimport { type SandboxErrorCode, SandboxError } from \"deepagents\";\n\n/**\n * Supported target regions for Daytona sandboxes.\n *\n * - `us`: United States\n * - `eu`: Europe\n */\nexport type DaytonaSandboxTarget = \"us\" | \"eu\";\n\n/**\n * Configuration options for creating a Daytona Sandbox.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * timeout: 300, // 5 minutes\n * target: \"us\",\n * };\n * ```\n */\nexport interface DaytonaSandboxOptions {\n /**\n * Primary language for code execution in the sandbox.\n *\n * Determines the runtime environment and code execution tooling.\n *\n * @default \"typescript\"\n */\n language?: \"typescript\" | \"python\" | \"javascript\";\n\n /**\n * Custom environment variables to set in the sandbox.\n *\n * These variables will be available to all commands and code executed\n * in the sandbox.\n *\n * @example\n * ```typescript\n * envVars: {\n * NODE_ENV: \"development\",\n * API_KEY: \"secret\"\n * }\n * ```\n */\n envVars?: Record<string, string>;\n\n /**\n * Resource allocation for the sandbox.\n *\n * When specifying resources, you must also specify an `image`.\n * Resources cannot be customized when using the default snapshot-based sandbox.\n *\n * @example\n * ```typescript\n * resources: { cpu: 2, memory: 4, disk: 20 }\n * ```\n */\n resources?: {\n /** Number of CPUs to allocate */\n cpu?: number;\n /** Amount of memory in GiB */\n memory?: number;\n /** Amount of disk space in GiB */\n disk?: number;\n };\n\n /**\n * Custom Docker image to use for the sandbox.\n *\n * When specified, creates a sandbox from this image instead of the default snapshot.\n * This is required when you want to customize resources.\n *\n * @example \"node:20\" or \"python:3.12\"\n */\n image?: string;\n\n /**\n * Snapshot name to use for the sandbox.\n *\n * When specified, creates a sandbox from this snapshot.\n * Cannot be used together with `image`.\n */\n snapshot?: string;\n\n /**\n * Target region where the sandbox will be created.\n *\n * @default \"us\"\n */\n target?: DaytonaSandboxTarget;\n\n /**\n * Auto-stop interval in minutes.\n *\n * The sandbox will automatically stop after being idle for this duration.\n * Set to 0 to disable auto-stop.\n *\n * @default 15\n */\n autoStopInterval?: number;\n\n /**\n * Default timeout for command execution in seconds.\n *\n * @default 300 (5 minutes)\n */\n timeout?: number;\n\n /**\n * Custom labels to attach to the sandbox.\n *\n * Labels can be used for organizing and filtering sandboxes.\n */\n labels?: Record<string, string>;\n\n /**\n * Initial files to create in the sandbox after initialization.\n *\n * A map of file paths to their contents. Files will be created\n * in the sandbox filesystem before any commands are executed.\n * Parent directories are created automatically.\n *\n * @example\n * ```typescript\n * const options: DaytonaSandboxOptions = {\n * language: \"typescript\",\n * initialFiles: {\n * \"/app/index.js\": \"console.log('Hello')\",\n * \"/app/package.json\": '{\"name\": \"test\"}',\n * },\n * };\n * ```\n */\n initialFiles?: Record<string, string>;\n\n /**\n * Authentication configuration for Daytona API.\n *\n * ### Environment Variable Setup\n *\n * ```bash\n * # Get your API key from https://app.daytona.io\n * export DAYTONA_API_KEY=your_api_key_here\n * ```\n *\n * Or pass the API key directly in this auth configuration.\n */\n auth?: {\n /**\n * Daytona API key.\n * If not provided, reads from `DAYTONA_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Daytona API URL.\n * If not provided, reads from `DAYTONA_API_URL` environment variable\n * or uses the default Daytona API URL.\n *\n * @default \"https://app.daytona.io/api\"\n */\n apiUrl?: string;\n };\n}\n\n/**\n * Error codes for Daytona Sandbox operations.\n *\n * Used to identify specific error conditions and handle them appropriately.\n */\nexport type DaytonaSandboxErrorCode =\n | SandboxErrorCode\n /** Authentication failed - check API key configuration */\n | \"AUTHENTICATION_FAILED\"\n /** Failed to create sandbox - check options and quotas */\n | \"SANDBOX_CREATION_FAILED\"\n /** Sandbox not found - may have been deleted or expired */\n | \"SANDBOX_NOT_FOUND\"\n /** Sandbox is not in started state */\n | \"SANDBOX_NOT_STARTED\"\n /** Resource limits exceeded (CPU, memory, storage) */\n | \"RESOURCE_LIMIT_EXCEEDED\";\n\nconst DAYTONA_SANDBOX_ERROR_SYMBOL = Symbol.for(\"daytona.sandbox.error\");\n\n/**\n * Custom error class for Daytona Sandbox operations.\n *\n * Provides structured error information including:\n * - Human-readable message\n * - Error code for programmatic handling\n * - Original cause for debugging\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"some command\");\n * } catch (error) {\n * if (error instanceof DaytonaSandboxError) {\n * switch (error.code) {\n * case \"NOT_INITIALIZED\":\n * await sandbox.initialize();\n * break;\n * case \"COMMAND_TIMEOUT\":\n * console.error(\"Command took too long\");\n * break;\n * default:\n * throw error;\n * }\n * }\n * }\n * ```\n */\nexport class DaytonaSandboxError extends SandboxError {\n /** Symbol for identifying sandbox error instances */\n [DAYTONA_SANDBOX_ERROR_SYMBOL] = true as const;\n\n /** Error name for instanceof checks and logging */\n override readonly name = \"DaytonaSandboxError\";\n\n /**\n * Creates a new DaytonaSandboxError.\n *\n * @param message - Human-readable error description\n * @param code - Structured error code for programmatic handling\n * @param cause - Original error that caused this error (for debugging)\n */\n constructor(\n message: string,\n public readonly code: DaytonaSandboxErrorCode,\n public override readonly cause?: Error,\n ) {\n super(message, code as SandboxErrorCode, cause);\n // Maintain proper prototype chain for instanceof checks\n Object.setPrototypeOf(this, DaytonaSandboxError.prototype);\n }\n\n /**\n * Checks if the error is an instance of DaytonaSandboxError.\n *\n * @param error - The error to check\n * @returns True if the error is an instance of DaytonaSandboxError, false otherwise\n */\n static isInstance(error: unknown): error is DaytonaSandboxError {\n return (\n typeof error === \"object\" &&\n error !== null &&\n (error as Record<symbol, unknown>)[DAYTONA_SANDBOX_ERROR_SYMBOL] === true\n );\n }\n}\n","/* eslint-disable no-instanceof/no-instanceof */\n/**\n * Daytona Sandbox implementation of the SandboxBackendProtocol.\n *\n * This module provides a Daytona Sandbox backend for deepagents, enabling agents\n * to execute commands, read/write files, and manage isolated sandbox environments\n * using Daytona's infrastructure.\n *\n * @packageDocumentation\n */\n\nimport { Daytona, type Sandbox } from \"@daytonaio/sdk\";\nimport {\n BaseSandbox,\n type ExecuteResponse,\n type FileDownloadResponse,\n type FileOperationError,\n type FileUploadResponse,\n type BackendFactory,\n} from \"deepagents\";\n\nimport { getAuthCredentials } from \"./auth.js\";\nimport { DaytonaSandboxError, type DaytonaSandboxOptions } from \"./types.js\";\n\n/**\n * Daytona Sandbox backend for deepagents.\n *\n * Extends `BaseSandbox` to provide command execution, file operations, and\n * sandbox lifecycle management using Daytona's SDK.\n *\n * ## Basic Usage\n *\n * ```typescript\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * timeout: 300,\n * });\n *\n * try {\n * // Execute commands\n * const result = await sandbox.execute(\"node --version\");\n * console.log(result.output);\n * } finally {\n * // Always cleanup\n * await sandbox.close();\n * }\n * ```\n *\n * ## Using with DeepAgent\n *\n * ```typescript\n * import { createDeepAgent } from \"deepagents\";\n * import { DaytonaSandbox } from \"@langchain/daytona\";\n *\n * const sandbox = await DaytonaSandbox.create();\n *\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant with sandbox access.\",\n * backend: sandbox,\n * });\n * ```\n */\nexport class DaytonaSandbox extends BaseSandbox {\n /** Private reference to the Daytona client */\n #daytona: Daytona | null = null;\n\n /** Private reference to the underlying Daytona Sandbox instance */\n #sandbox: Sandbox | null = null;\n\n /** Configuration options for this sandbox */\n #options: DaytonaSandboxOptions;\n\n /** Unique identifier for this sandbox instance */\n #id: string;\n\n /** Default timeout for command execution in seconds */\n #timeout: number;\n\n /**\n * Get the unique identifier for this sandbox.\n *\n * Before initialization, returns a temporary ID.\n * After initialization, returns the actual Daytona sandbox ID.\n */\n get id(): string {\n return this.#id;\n }\n\n /**\n * Get the underlying Daytona Sandbox instance.\n *\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create();\n * const daytonaSdk = sandbox.sandbox; // Access the raw SDK\n * ```\n */\n get instance(): Sandbox {\n if (!this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox not initialized. Call initialize() or use DaytonaSandbox.create()\",\n \"NOT_INITIALIZED\",\n );\n }\n return this.#sandbox;\n }\n\n /**\n * Get the underlying Daytona client instance.\n *\n * @throws {DaytonaSandboxError} If the client is not initialized\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create();\n * const daytonaClient = sandbox.client; // Access the raw Daytona client\n * ```\n */\n get client(): Daytona {\n if (!this.#daytona) {\n throw new DaytonaSandboxError(\n \"Daytona client not initialized. Call initialize() or use DaytonaSandbox.create()\",\n \"NOT_INITIALIZED\",\n );\n }\n return this.#daytona;\n }\n\n /**\n * Check if the sandbox is initialized and running.\n */\n get isRunning(): boolean {\n return this.#sandbox !== null;\n }\n\n /**\n * Create a new DaytonaSandbox instance.\n *\n * Note: This only creates the instance. Call `initialize()` to actually\n * create the Daytona Sandbox, or use the static `DaytonaSandbox.create()` method.\n *\n * @param options - Configuration options for the sandbox\n *\n * @example\n * ```typescript\n * // Two-step initialization\n * const sandbox = new DaytonaSandbox({ language: \"typescript\" });\n * await sandbox.initialize();\n *\n * // Or use the factory method\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n * ```\n */\n constructor(options: DaytonaSandboxOptions = {}) {\n super();\n\n // Set defaults\n this.#options = {\n language: \"typescript\",\n timeout: 300,\n ...options,\n };\n\n this.#timeout = this.#options.timeout ?? 300;\n\n // Generate temporary ID until initialized\n this.#id = `daytona-sandbox-${Date.now()}`;\n }\n\n /**\n * Initialize the sandbox by creating a new Daytona Sandbox instance.\n *\n * This method authenticates with Daytona and provisions a new sandbox.\n * After initialization, the `id` property will reflect the actual sandbox ID.\n *\n * @throws {DaytonaSandboxError} If already initialized (`ALREADY_INITIALIZED`)\n * @throws {DaytonaSandboxError} If authentication fails (`AUTHENTICATION_FAILED`)\n * @throws {DaytonaSandboxError} If sandbox creation fails (`SANDBOX_CREATION_FAILED`)\n *\n * @example\n * ```typescript\n * const sandbox = new DaytonaSandbox();\n * await sandbox.initialize();\n * console.log(`Sandbox ID: ${sandbox.id}`);\n * ```\n */\n async initialize(): Promise<void> {\n // Prevent double initialization\n if (this.#sandbox) {\n throw new DaytonaSandboxError(\n \"Sandbox is already initialized. Each DaytonaSandbox instance can only be initialized once.\",\n \"ALREADY_INITIALIZED\",\n );\n }\n\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(\n this.#options.auth,\n this.#options.target,\n );\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n // Create Daytona client\n this.#daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n // Determine if we're creating from image or snapshot\n if (this.#options.image) {\n // Create from image (allows custom resources)\n const createOptions: {\n image: string;\n language?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n resources?: { cpu?: number; memory?: number; disk?: number };\n } = {\n image: this.#options.image,\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n if (this.#options.resources) {\n createOptions.resources = this.#options.resources;\n }\n\n // Create the sandbox from image\n this.#sandbox = await this.#daytona.create(createOptions);\n } else {\n // Create from snapshot (default, simpler approach)\n const createOptions: {\n language?: string;\n snapshot?: string;\n envVars?: Record<string, string>;\n autoStopInterval?: number;\n labels?: Record<string, string>;\n } = {\n language: this.#options.language ?? \"typescript\",\n };\n\n if (this.#options.snapshot) {\n createOptions.snapshot = this.#options.snapshot;\n }\n\n if (this.#options.envVars) {\n createOptions.envVars = this.#options.envVars;\n }\n\n if (this.#options.autoStopInterval !== undefined) {\n createOptions.autoStopInterval = this.#options.autoStopInterval;\n }\n\n if (this.#options.labels) {\n createOptions.labels = this.#options.labels;\n }\n\n // Create the sandbox from snapshot\n this.#sandbox = await this.#daytona.create(createOptions);\n }\n\n // Update ID to the actual sandbox ID\n this.#id = this.#sandbox.id;\n\n // Upload initial files if provided\n if (this.#options.initialFiles) {\n await this.#uploadInitialFiles(this.#options.initialFiles);\n }\n } catch (error) {\n throw new DaytonaSandboxError(\n `Failed to create Daytona Sandbox: ${error instanceof Error ? error.message : String(error)}`,\n \"SANDBOX_CREATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload initial files to the sandbox.\n *\n * @param files - A map of file paths to their string contents\n */\n async #uploadInitialFiles(files: Record<string, string>): Promise<void> {\n const encoder = new TextEncoder();\n const fileEntries: Array<[string, Uint8Array]> = Object.entries(files).map(\n ([path, content]) => [path, encoder.encode(content)],\n );\n\n const results = await this.uploadFiles(fileEntries);\n\n // Check for any errors during upload\n const errors = results.filter((r) => r.error !== null);\n if (errors.length > 0) {\n const errorPaths = errors.map((e) => `${e.path}: ${e.error}`).join(\", \");\n throw new DaytonaSandboxError(\n `Failed to upload initial files: ${errorPaths}`,\n \"FILE_OPERATION_FAILED\",\n );\n }\n }\n\n /**\n * Execute a command in the sandbox.\n *\n * Commands are run using the sandbox's shell.\n *\n * @param command - The shell command to execute\n * @returns Execution result with output, exit code, and truncation flag\n * @throws {DaytonaSandboxError} If the sandbox is not initialized\n *\n * @example\n * ```typescript\n * const result = await sandbox.execute(\"echo 'Hello World'\");\n * console.log(result.output); // \"Hello World\\n\"\n * console.log(result.exitCode); // 0\n * ```\n */\n async execute(command: string): Promise<ExecuteResponse> {\n const sandbox = this.instance; // Throws if not initialized\n\n try {\n const response = await sandbox.process.executeCommand(\n command,\n undefined,\n undefined,\n this.#timeout,\n );\n\n return {\n output: response.result ?? \"\",\n exitCode: response.exitCode ?? 0,\n truncated: false,\n };\n } catch (error) {\n // Check for timeout\n if (error instanceof Error && error.message.includes(\"timeout\")) {\n throw new DaytonaSandboxError(\n `Command timed out: ${command}`,\n \"COMMAND_TIMEOUT\",\n error,\n );\n }\n\n throw new DaytonaSandboxError(\n `Command execution failed: ${error instanceof Error ? error.message : String(error)}`,\n \"COMMAND_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Upload files to the sandbox.\n *\n * Files are written to the sandbox filesystem. Parent directories are\n * created automatically if they don't exist.\n *\n * @param files - Array of [path, content] tuples to upload\n * @returns Upload result for each file, with success or error status\n *\n * @example\n * ```typescript\n * const encoder = new TextEncoder();\n * const results = await sandbox.uploadFiles([\n * [\"src/index.js\", encoder.encode(\"console.log('Hello')\")],\n * [\"package.json\", encoder.encode('{\"name\": \"test\"}')],\n * ]);\n * ```\n */\n async uploadFiles(\n files: Array<[string, Uint8Array]>,\n ): Promise<FileUploadResponse[]> {\n const sandbox = this.instance; // Throws if not initialized\n const results: FileUploadResponse[] = [];\n\n for (const [path, content] of files) {\n try {\n // Ensure parent directory exists\n const parentDir = path.substring(0, path.lastIndexOf(\"/\"));\n if (parentDir) {\n await sandbox.fs.createFolder(parentDir, \"755\");\n }\n\n // Upload the file content\n const buffer = Buffer.from(content);\n await sandbox.fs.uploadFile(buffer, path);\n results.push({ path, error: null });\n } catch (error) {\n results.push({ path, error: this.#mapError(error) });\n }\n }\n\n return results;\n }\n\n /**\n * Download files from the sandbox.\n *\n * Each file is read individually, allowing partial success when some\n * files exist and others don't.\n *\n * @param paths - Array of file paths to download\n * @returns Download result for each file, with content or error\n *\n * @example\n * ```typescript\n * const results = await sandbox.downloadFiles([\"src/index.js\", \"missing.txt\"]);\n * for (const result of results) {\n * if (result.content) {\n * console.log(new TextDecoder().decode(result.content));\n * } else {\n * console.error(`Error: ${result.error}`);\n * }\n * }\n * ```\n */\n async downloadFiles(paths: string[]): Promise<FileDownloadResponse[]> {\n const sandbox = this.instance; // Throws if not initialized\n const results: FileDownloadResponse[] = [];\n\n for (const path of paths) {\n try {\n const buffer = await sandbox.fs.downloadFile(path);\n results.push({\n path,\n content: new Uint8Array(buffer),\n error: null,\n });\n } catch (error) {\n results.push({\n path,\n content: null,\n error: this.#mapError(error),\n });\n }\n }\n\n return results;\n }\n\n /**\n * Close the sandbox and release all resources.\n *\n * After closing, the sandbox cannot be used again. The sandbox is deleted\n * from Daytona's infrastructure.\n *\n * @example\n * ```typescript\n * try {\n * await sandbox.execute(\"npm run build\");\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\n async close(): Promise<void> {\n if (this.#sandbox) {\n try {\n await this.#sandbox.delete();\n } finally {\n this.#sandbox = null;\n this.#daytona = null;\n }\n }\n }\n\n /**\n * Stop the sandbox without deleting it.\n *\n * The sandbox can be restarted later using `start()`.\n *\n * @example\n * ```typescript\n * await sandbox.stop();\n * // Later...\n * await sandbox.start();\n * ```\n */\n async stop(): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.stop();\n }\n }\n\n /**\n * Start a stopped sandbox.\n *\n * @param timeout - Maximum time to wait in seconds (default: 60)\n *\n * @example\n * ```typescript\n * await sandbox.start();\n * console.log(\"Sandbox is now running\");\n * ```\n */\n async start(timeout: number = 60): Promise<void> {\n if (this.#sandbox) {\n await this.#sandbox.start(timeout);\n }\n }\n\n /**\n * Forcefully terminate and delete the sandbox.\n *\n * Use this when you need to immediately stop the sandbox.\n *\n * @example\n * ```typescript\n * await sandbox.kill();\n * ```\n */\n async kill(): Promise<void> {\n await this.close();\n }\n\n /**\n * Get the working directory path inside the sandbox.\n *\n * @returns The absolute path to the sandbox working directory\n *\n * @example\n * ```typescript\n * const workDir = await sandbox.getWorkDir();\n * console.log(`Working directory: ${workDir}`);\n * ```\n */\n async getWorkDir(): Promise<string> {\n const sandbox = this.instance;\n const workDir = await sandbox.getWorkDir();\n return workDir ?? \"/home/daytona\";\n }\n\n /**\n * Get the user's home directory path inside the sandbox.\n *\n * @returns The absolute path to the user's home directory\n *\n * @example\n * ```typescript\n * const homeDir = await sandbox.getUserHomeDir();\n * console.log(`Home directory: ${homeDir}`);\n * ```\n */\n async getUserHomeDir(): Promise<string> {\n const sandbox = this.instance;\n const homeDir = await sandbox.getUserHomeDir();\n return homeDir ?? \"/home/daytona\";\n }\n\n /**\n * Set the sandbox from an existing Daytona Sandbox instance.\n * Used internally by the static `connect()` method.\n */\n #setFromExisting(\n daytona: Daytona,\n existingSandbox: Sandbox,\n sandboxId: string,\n ): void {\n this.#daytona = daytona;\n this.#sandbox = existingSandbox;\n this.#id = sandboxId;\n }\n\n /**\n * Map Daytona SDK errors to standardized FileOperationError codes.\n *\n * @param error - The error from the Daytona SDK\n * @returns A standardized error code\n */\n #mapError(error: unknown): FileOperationError {\n if (error instanceof Error) {\n const msg = error.message.toLowerCase();\n\n if (msg.includes(\"not found\") || msg.includes(\"enoent\")) {\n return \"file_not_found\";\n }\n if (msg.includes(\"permission\") || msg.includes(\"eacces\")) {\n return \"permission_denied\";\n }\n if (msg.includes(\"directory\") || msg.includes(\"eisdir\")) {\n return \"is_directory\";\n }\n }\n\n return \"invalid_path\";\n }\n\n /**\n * Create and initialize a new DaytonaSandbox in one step.\n *\n * This is the recommended way to create a sandbox. It combines\n * construction and initialization into a single async operation.\n *\n * @param options - Configuration options for the sandbox\n * @returns An initialized and ready-to-use sandbox\n *\n * @example\n * ```typescript\n * const sandbox = await DaytonaSandbox.create({\n * language: \"typescript\",\n * cpu: 2,\n * memory: 4,\n * });\n * ```\n */\n static async create(\n options?: DaytonaSandboxOptions,\n ): Promise<DaytonaSandbox> {\n const sandbox = new DaytonaSandbox(options);\n await sandbox.initialize();\n return sandbox;\n }\n\n /**\n * Delete all sandboxes matching the given labels.\n *\n * This is useful for cleaning up stale sandboxes from previous test runs\n * or CI pipelines that may not have shut down cleanly.\n *\n * @param labels - Label key-value pairs to filter sandboxes\n * @param options - Optional auth configuration\n * @returns The number of sandboxes that were deleted\n *\n * @example\n * ```typescript\n * // Clean up all integration-test sandboxes\n * const deleted = await DaytonaSandbox.deleteAll({\n * purpose: \"integration-test\",\n * package: \"@langchain/daytona\",\n * });\n * console.log(`Deleted ${deleted} stale sandboxes`);\n * ```\n */\n static async deleteAll(\n labels: Record<string, string>,\n options?: Pick<DaytonaSandboxOptions, \"auth\" | \"target\">,\n ): Promise<number> {\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(options?.auth, options?.target);\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n const daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n const { items } = await daytona.list(labels);\n\n const results = await Promise.all(\n items.map((sandbox) =>\n daytona\n .delete(sandbox)\n .then(() => true)\n .catch(() => false),\n ),\n );\n\n return results.filter(Boolean).length;\n }\n\n /**\n * Connect to an existing sandbox by ID.\n *\n * This allows you to resume working with a sandbox that was created\n * earlier or that is still running.\n *\n * @param sandboxId - The ID of the sandbox to connect to\n * @param options - Optional auth configuration (for API key)\n * @returns A connected sandbox instance\n *\n * @example\n * ```typescript\n * // Resume a sandbox from a stored ID\n * const sandbox = await DaytonaSandbox.connect(\"sandbox-abc123\");\n * const result = await sandbox.execute(\"ls -la\");\n * ```\n */\n static async fromId(\n id: string,\n options?: Pick<DaytonaSandboxOptions, \"auth\" | \"target\" | \"timeout\">,\n ): Promise<DaytonaSandbox> {\n // Get authentication credentials\n let credentials: { apiKey: string; apiUrl: string; target?: string };\n try {\n credentials = getAuthCredentials(options?.auth, options?.target);\n } catch (error) {\n throw new DaytonaSandboxError(\n \"Failed to authenticate with Daytona. Check your API key configuration.\",\n \"AUTHENTICATION_FAILED\",\n error instanceof Error ? error : undefined,\n );\n }\n\n try {\n const daytona = new Daytona({\n apiKey: credentials.apiKey,\n apiUrl: credentials.apiUrl,\n target: credentials.target,\n });\n\n const existingSandbox = await daytona.get(id);\n\n const daytonaSandbox = new DaytonaSandbox(options);\n // Set the existing sandbox directly (bypass initialize)\n daytonaSandbox.#setFromExisting(daytona, existingSandbox, id);\n\n return daytonaSandbox;\n } catch (error) {\n throw new DaytonaSandboxError(\n `Sandbox not found: ${id}`,\n \"SANDBOX_NOT_FOUND\",\n error instanceof Error ? error : undefined,\n );\n }\n }\n\n /**\n * Get a running sandbox by name from a deployed app.\n *\n * @param name - The name of the sandbox\n * @param options - Optional auth configuration\n * @returns A connected sandbox instance\n */\n static async fromName(\n name: string,\n options?: Pick<DaytonaSandboxOptions, \"auth\">,\n ): Promise<DaytonaSandbox> {\n return DaytonaSandbox.fromId(name, options);\n }\n}\n\n/**\n * Async factory function type for creating Daytona Sandbox instances.\n *\n * This is similar to BackendFactory but supports async creation,\n * which is required for Daytona Sandbox since initialization is async.\n */\nexport type AsyncDaytonaSandboxFactory = () => Promise<DaytonaSandbox>;\n\n/**\n * Create an async factory function that creates a new Daytona Sandbox per invocation.\n *\n * Each call to the factory will create and initialize a new sandbox.\n * This is useful when you want fresh, isolated environments for each\n * agent invocation.\n *\n * **Important**: This returns an async factory. For use with middleware that\n * requires synchronous BackendFactory, use `createDaytonaSandboxFactoryFromSandbox()`\n * with a pre-created sandbox instead.\n *\n * @param options - Optional configuration for sandbox creation\n * @returns An async factory function that creates new sandboxes\n *\n * @example\n * ```typescript\n * import { DaytonaSandbox, createDaytonaSandboxFactory } from \"@langchain/daytona\";\n *\n * // Create a factory for new sandboxes\n * const factory = createDaytonaSandboxFactory({ language: \"typescript\" });\n *\n * // Each call creates a new sandbox\n * const sandbox1 = await factory();\n * const sandbox2 = await factory();\n *\n * try {\n * // Use sandboxes...\n * } finally {\n * await sandbox1.close();\n * await sandbox2.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactory(\n options?: DaytonaSandboxOptions,\n): AsyncDaytonaSandboxFactory {\n return async () => {\n return await DaytonaSandbox.create(options);\n };\n}\n\n/**\n * Create a backend factory that reuses an existing Daytona Sandbox.\n *\n * This allows multiple agent invocations to share the same sandbox,\n * avoiding the startup overhead of creating new sandboxes.\n *\n * Important: You are responsible for managing the sandbox lifecycle\n * (calling `close()` when done).\n *\n * @param sandbox - An existing DaytonaSandbox instance (must be initialized)\n * @returns A BackendFactory that returns the provided sandbox\n *\n * @example\n * ```typescript\n * import { createDeepAgent, createFilesystemMiddleware } from \"deepagents\";\n * import { DaytonaSandbox, createDaytonaSandboxFactoryFromSandbox } from \"@langchain/daytona\";\n *\n * // Create and initialize a sandbox\n * const sandbox = await DaytonaSandbox.create({ language: \"typescript\" });\n *\n * try {\n * const agent = createDeepAgent({\n * model: new ChatAnthropic({ model: \"claude-sonnet-4-20250514\" }),\n * systemPrompt: \"You are a coding assistant.\",\n * middlewares: [\n * createFilesystemMiddleware({\n * backend: createDaytonaSandboxFactoryFromSandbox(sandbox),\n * }),\n * ],\n * });\n *\n * await agent.invoke({ messages: [...] });\n * } finally {\n * await sandbox.close();\n * }\n * ```\n */\nexport function createDaytonaSandboxFactoryFromSandbox(\n sandbox: DaytonaSandbox,\n): BackendFactory {\n return () => sandbox;\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/daytona",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Daytona Sandbox backend for deepagents",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"homepage": "https://github.com/langchain-ai/deepagentsjs#readme",
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@daytonaio/sdk": "^0.
|
|
30
|
+
"@daytonaio/sdk": "^0.143.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"deepagents": ">=1.6.0"
|
|
@@ -41,7 +41,8 @@
|
|
|
41
41
|
"tsx": "^4.21.0",
|
|
42
42
|
"typescript": "^5.9.3",
|
|
43
43
|
"vitest": "^4.0.18",
|
|
44
|
-
"deepagents": "1.
|
|
44
|
+
"deepagents": "1.8.0",
|
|
45
|
+
"@langchain/sandbox-standard-tests": "0.1.0"
|
|
45
46
|
},
|
|
46
47
|
"exports": {
|
|
47
48
|
".": {
|