@evolvingmachines/e2b 0.0.51 → 0.0.52-project-sable.20260726.6e95f36

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 CHANGED
@@ -1,2 +1,8 @@
1
- 'use strict';var codeInterpreter=require('@e2b/code-interpreter');var p=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function a(i){return i instanceof Date?i.toISOString():String(i)}function l(i){if(typeof i=="string"||i instanceof ArrayBuffer)return i;if(i instanceof Buffer)return new Uint8Array(i).buffer;if(i instanceof Uint8Array)return new Uint8Array(i).buffer;throw new Error(`Unsupported data type for file upload: ${typeof i}. Expected string, Buffer, ArrayBuffer, or Uint8Array.`)}function g(i){let t=i.substring(i.lastIndexOf(".")).toLowerCase();return p.has(t)}var m=class{constructor(t){this.sandbox=t;}async run(t,e){try{let n=await this.sandbox.commands.run(t,{timeoutMs:e?.timeoutMs,envs:e?.envs,cwd:e?.cwd,onStdout:e?.onStdout,onStderr:e?.onStderr});return {exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch(n){if(n&&typeof n=="object"&&"exitCode"in n){let r=n;return {exitCode:r.exitCode,stdout:r.stdout??"",stderr:r.stderr??""}}throw n}}async spawn(t,e){let n=await this.sandbox.commands.run(t,{background:true,stdin:e?.stdin??true,timeoutMs:e?.timeoutMs,envs:e?.envs,cwd:e?.cwd,onStdout:e?.onStdout,onStderr:e?.onStderr});return {processId:String(n.pid),wait:async()=>{try{let r=await n.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let s=r;return {exitCode:s.exitCode,stdout:s.stdout??"",stderr:s.stderr??""}}throw r}},kill:()=>this.sandbox.commands.kill(n.pid)}}async list(){return (await this.sandbox.commands.list()).map(e=>({...e,processId:String(e.pid)}))}async connect(t,e){let n=await this.sandbox.commands.connect(Number(t),{onStdout:e?.onStdout,onStderr:e?.onStderr,timeoutMs:e?.timeoutMs});return {processId:String(n.pid),wait:async()=>{try{let r=await n.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let s=r;return {exitCode:s.exitCode,stdout:s.stdout??"",stderr:s.stderr??""}}throw r}},kill:()=>this.sandbox.commands.kill(n.pid)}}async sendStdin(t,e){await this.sandbox.commands.sendStdin(Number(t),e);}async kill(t){return this.sandbox.commands.kill(Number(t))}},c=class{constructor(t){this.sandbox=t;}async read(t){return g(t)?this.sandbox.files.read(t,{format:"bytes",requestTimeoutMs:3e5}):this.sandbox.files.read(t,{format:"text",requestTimeoutMs:3e5})}async write(t,e){await this.sandbox.files.write(t,l(e),{requestTimeoutMs:3e5});}async writeBatch(t){let e=t.map(n=>({path:n.path,data:l(n.data)}));await this.sandbox.files.write(e,{requestTimeoutMs:3e5});}async makeDir(t){await this.sandbox.files.makeDir(t);}async uploadUrl(t,e){return this.sandbox.uploadUrl(t,e?{useSignatureExpiration:e}:void 0)}async downloadUrl(t,e){return this.sandbox.downloadUrl(t,e?{useSignatureExpiration:e}:void 0)}async exists(t){return this.sandbox.files.exists(t)}async list(t){return (await this.sandbox.files.list(t)).map(n=>({name:n.name,path:n.path,type:n.type==="dir"?"dir":"file"}))}async remove(t){await this.sandbox.files.remove(t);}async rename(t,e){await this.sandbox.files.rename(t,e);}async readStream(t){return this.sandbox.files.read(t,{format:"stream"})}async writeStream(t,e){await this.sandbox.files.write(t,e);}async watchDir(t,e,n){let r=await this.sandbox.files.watchDir(t,e,{recursive:n?.recursive,timeoutMs:n?.timeoutMs,onExit:n?.onExit});return {stop:()=>r.stop()}}},o=class{constructor(t,e,n){this.sandbox=t;this.apiKey=e;this.apiUrl=n;this.commands=new m(t),this.files=new c(t);}commands;files;get sandboxId(){return this.sandbox.sandboxId}getHost(t){return Promise.resolve(this.sandbox.getHost(t))}async isRunning(){return this.sandbox.isRunning()}async getInfo(){let t=await this.sandbox.getInfo();return {sandboxId:t.sandboxId,image:t.templateId,name:t.name,metadata:t.metadata??{},startedAt:a(t.startedAt),endAt:t.endAt?a(t.endAt):void 0}}async kill(){try{await this.sandbox.kill();}catch{await new Promise(t=>setTimeout(t,500)),await this.sandbox.kill();}}async pause(){await this.sandbox.betaPause({apiKey:this.apiKey,apiUrl:this.apiUrl});}},u=class{providerType="e2b";apiKey;apiUrl;defaultTimeoutMs;templateId;constructor(t){this.apiKey=t.apiKey,this.apiUrl=t.apiUrl,this.defaultTimeoutMs=t.defaultTimeoutMs??36e5,this.templateId=t.templateId;}async create(t){let e=t.timeoutMs??this.defaultTimeoutMs,n=t.image??this.templateId??"evolve-all",r=await codeInterpreter.Sandbox.create(n,{apiKey:this.apiKey,apiUrl:this.apiUrl,envs:t.envs,metadata:t.metadata,timeoutMs:e});return t.workingDirectory&&await r.files.makeDir(t.workingDirectory),new o(r,this.apiKey,this.apiUrl)}async connect(t,e){let n=await codeInterpreter.Sandbox.connect(t,{apiKey:this.apiKey,apiUrl:this.apiUrl,timeoutMs:e??this.defaultTimeoutMs});return new o(n,this.apiKey,this.apiUrl)}async list(t){return (await codeInterpreter.Sandbox.list({apiKey:this.apiKey,apiUrl:this.apiUrl,query:{state:t?.state,metadata:t?.metadata},limit:t?.limit??100}).nextItems()).map(r=>({sandboxId:r.sandboxId,image:r.templateId,name:r.name,metadata:r.metadata??{},startedAt:a(r.startedAt),endAt:r.endAt?a(r.endAt):void 0}))}};function b(i={}){let t=i.apiKey??process.env.E2B_API_KEY;if(!t)throw new Error("E2B API key required. Set E2B_API_KEY environment variable or pass apiKey in config. Get your key at https://e2b.dev/sign-in");return new u({...i,apiKey:t})}
2
- exports.E2BProvider=u;exports.createE2BProvider=b;
1
+ 'use strict';var codeInterpreter=require('@e2b/code-interpreter');function f(n){if(!n||typeof n!="object")return false;if(n.name==="TimeoutError")return true;let e=n.message;return typeof e=="string"&&/timed?\s*out/i.test(e)}var P=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function m(n){return n instanceof Date?n.toISOString():String(n)}function w(n){if(typeof n=="string"||n instanceof ArrayBuffer)return n;if(n instanceof Buffer)return new Uint8Array(n).buffer;if(n instanceof Uint8Array)return new Uint8Array(n).buffer;throw new Error(`Unsupported data type for file upload: ${typeof n}. Expected string, Buffer, ArrayBuffer, or Uint8Array.`)}function U(n){let e=n.substring(n.lastIndexOf(".")).toLowerCase();return P.has(e)}var g=class extends Error{constructor(e){super(e),this.name="E2BResourcesError";}},p=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async run(e,t){try{let s=await this.sandbox.commands.run(e,{timeoutMs:t?.timeoutMs,envs:t?.envs,cwd:t?.cwd,user:this.defaultUser,onStdout:t?.onStdout,onStderr:t?.onStderr});return {exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr}}catch(s){if(s&&typeof s=="object"&&"exitCode"in s){let r=s;return {exitCode:r.exitCode,stdout:r.stdout??"",stderr:r.stderr??""}}if(f(s))return {exitCode:124,stdout:"",stderr:s instanceof Error?s.message:"command timed out"};throw s}}async spawn(e,t){let s=await this.sandbox.commands.run(e,{background:true,stdin:t?.stdin??true,timeoutMs:t?.timeoutMs,envs:t?.envs,cwd:t?.cwd,user:this.defaultUser,onStdout:t?.onStdout,onStderr:t?.onStderr});return {processId:String(s.pid),wait:async()=>{try{let r=await s.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let i=r;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(f(r))return {exitCode:124,stdout:"",stderr:r instanceof Error?r.message:"command timed out"};throw r}},kill:()=>this.sandbox.commands.kill(s.pid)}}async list(){return (await this.sandbox.commands.list()).map(t=>({...t,processId:String(t.pid)}))}async connect(e,t){let s=await this.sandbox.commands.connect(Number(e),{onStdout:t?.onStdout,onStderr:t?.onStderr,timeoutMs:t?.timeoutMs});return {processId:String(s.pid),wait:async()=>{try{let r=await s.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let i=r;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(f(r))return {exitCode:124,stdout:"",stderr:r instanceof Error?r.message:"command timed out"};throw r}},kill:()=>this.sandbox.commands.kill(s.pid)}}async sendStdin(e,t){await this.sandbox.commands.sendStdin(Number(e),t);}async kill(e){return this.sandbox.commands.kill(Number(e))}},b=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async read(e){return U(e)?this.sandbox.files.read(e,{format:"bytes",requestTimeoutMs:3e5,user:this.defaultUser}):this.sandbox.files.read(e,{format:"text",requestTimeoutMs:3e5,user:this.defaultUser})}async write(e,t){await this.sandbox.files.write(e,w(t),{requestTimeoutMs:3e5,user:this.defaultUser});}async writeBatch(e){let t=e.map(s=>({path:s.path,data:w(s.data)}));await this.sandbox.files.write(t,{requestTimeoutMs:3e5,user:this.defaultUser});}async makeDir(e){await this.sandbox.files.makeDir(e,{user:this.defaultUser});}async uploadUrl(e,t){return this.sandbox.uploadUrl(e,{user:this.defaultUser,...t?{useSignatureExpiration:t}:{}})}async downloadUrl(e,t){return this.sandbox.downloadUrl(e,{user:this.defaultUser,...t?{useSignatureExpiration:t}:{}})}async exists(e){return this.sandbox.files.exists(e,{user:this.defaultUser})}async list(e){return (await this.sandbox.files.list(e,{user:this.defaultUser})).map(s=>({name:s.name,path:s.path,type:s.type==="dir"?"dir":"file"}))}async remove(e){await this.sandbox.files.remove(e,{user:this.defaultUser});}async rename(e,t){await this.sandbox.files.rename(e,t,{user:this.defaultUser});}async readStream(e){return this.sandbox.files.read(e,{format:"stream",user:this.defaultUser})}async writeStream(e,t){await this.sandbox.files.write(e,t,{user:this.defaultUser});}async writeFromPath(e,t){let{createReadStream:s,statSync:r}=await import('fs'),{Readable:i}=await import('stream'),{randomBytes:o}=await import('crypto'),S=r(t).size,l=`----evolve${o(16).toString("hex")}`,y=Buffer.from(`--${l}\r
2
+ Content-Disposition: form-data; name="file"; filename="blob"\r
3
+ Content-Type: application/octet-stream\r
4
+ \r
5
+ `),h=Buffer.from(`\r
6
+ --${l}--\r
7
+ `);async function*v(){yield y;for await(let a of s(t))yield a;yield h;}try{let a=await this.uploadUrl(e),d=await fetch(a,{method:"POST",body:i.toWeb(i.from(v())),headers:{"Content-Type":`multipart/form-data; boundary=${l}`,"Content-Length":String(y.length+S+h.length)},duplex:"half"});if(!d.ok)throw new Error(`streamed upload to ${e} failed (HTTP ${d.status})`)}catch(a){console.warn(`[e2b] streamed upload of ${t} failed, falling back to a buffered write:`,a instanceof Error?a.message:a);let d=i.toWeb(s(t));await this.writeStream(e,d);}}async watchDir(e,t,s){let r=await this.sandbox.files.watchDir(e,t,{recursive:s?.recursive,timeoutMs:s?.timeoutMs,user:this.defaultUser,onExit:s?.onExit});return {stop:()=>r.stop()}}},u=class{constructor(e,t,s,r){this.sandbox=e;this.apiKey=t;this.apiUrl=s;this.commands=new p(e,r),this.files=new b(e,r);}commands;files;get sandboxId(){return this.sandbox.sandboxId}getHost(e){return Promise.resolve(this.sandbox.getHost(e))}async isRunning(){return this.sandbox.isRunning()}async getInfo(){let e=await this.sandbox.getInfo();return {sandboxId:e.sandboxId,image:e.templateId,name:e.name,metadata:e.metadata??{},startedAt:m(e.startedAt),endAt:e.endAt?m(e.endAt):void 0}}async kill(){try{await this.sandbox.kill();}catch{await new Promise(e=>setTimeout(e,500)),await this.sandbox.kill();}}async pause(){await this.sandbox.betaPause({apiKey:this.apiKey,apiUrl:this.apiUrl});}},x=class{providerType="e2b";name="E2B";apiKey;apiUrl;defaultTimeoutMs;templateId;sandboxUsers=new Map;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl,this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.templateId=e.templateId;}async create(e){if(e.resources&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0))throw new g("E2B cannot size a sandbox at create time: sizing is fixed by the template (Template.build cpuCount/memoryMB; disk is plan-fixed). Build a template with the desired resources and pass it as `image` instead of `resources`.");let t=e.timeoutMs??this.defaultTimeoutMs,s=e.image??this.templateId??"evolve-all";if(e.network?.outbound==="open"&&e.network.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");let r=e.network?.allowedDestinations??[],i=e.network?.outbound==="blocked"&&r.length>0,o=await codeInterpreter.Sandbox.create(s,{apiKey:this.apiKey,apiUrl:this.apiUrl,envs:e.envs,metadata:e.metadata,timeoutMs:t,allowInternetAccess:e.network?.outbound!=="blocked"||i,network:i?{denyOut:["0.0.0.0/0"],allowOut:r}:void 0});return e.workingDirectory&&await o.files.makeDir(e.workingDirectory,{user:e.user}),e.user&&this.sandboxUsers.set(o.sandboxId,e.user),new u(o,this.apiKey,this.apiUrl,e.user)}async connect(e,t){let s=await codeInterpreter.Sandbox.connect(e,{apiKey:this.apiKey,apiUrl:this.apiUrl,timeoutMs:t??this.defaultTimeoutMs});return new u(s,this.apiKey,this.apiUrl,this.sandboxUsers.get(e))}async list(e){return (await codeInterpreter.Sandbox.list({apiKey:this.apiKey,apiUrl:this.apiUrl,query:{state:e?.state,metadata:e?.metadata},limit:e?.limit??100}).nextItems()).map(r=>({sandboxId:r.sandboxId,image:r.templateId,name:r.name,metadata:r.metadata??{},startedAt:m(r.startedAt),endAt:r.endAt?m(r.endAt):void 0}))}};function k(n={}){let e=n.apiKey??process.env.E2B_API_KEY;if(!e)throw new Error("E2B API key required. Set E2B_API_KEY environment variable or pass apiKey in config. Get your key at https://e2b.dev/sign-in");return new x({...n,apiKey:e})}
8
+ exports.E2BCommands=p;exports.E2BFiles=b;exports.E2BProvider=x;exports.E2BResourcesError=g;exports.createE2BProvider=k;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Sandbox } from '@e2b/code-interpreter';
2
+
1
3
  /**
2
4
  * E2B Sandbox Provider - Clean Architecture
3
5
  *
@@ -11,6 +13,17 @@
11
13
  * - Configuration externalized (no hardcoded mappings)
12
14
  * - Clear naming (run = blocking, spawn = background)
13
15
  */
16
+
17
+ /**
18
+ * Typed error for create-time sizing requests E2B cannot enforce.
19
+ * E2B sandboxes inherit cpu/memory from their TEMPLATE (Template.build
20
+ * cpuCount/memoryMB; disk is plan-fixed) — Sandbox.create has no sizing
21
+ * parameters, so a `resources` request would be silently ignored. Per the
22
+ * provider law (reject what you cannot enforce) it is refused loudly here.
23
+ */
24
+ declare class E2BResourcesError extends Error {
25
+ constructor(message: string);
26
+ }
14
27
  /** Result of a completed sandbox command */
15
28
  interface SandboxCommandResult {
16
29
  exitCode: number;
@@ -85,11 +98,38 @@ interface SandboxConnectOptions {
85
98
  }
86
99
  /** Options for creating a sandbox */
87
100
  interface SandboxCreateOptions {
88
- image: string;
101
+ /**
102
+ * E2B template ID. OPTIONAL: create() falls back to the provider's
103
+ * configured `templateId`, then to "evolve-all" — declaring it required
104
+ * contradicted that implementation and only went unnoticed because TS
105
+ * method parameters are bivariant, so the SDK could already call
106
+ * create({}) through the shared contract.
107
+ */
108
+ image?: string;
89
109
  envs?: Record<string, string>;
90
110
  metadata?: Record<string, string>;
91
111
  timeoutMs?: number;
92
112
  workingDirectory?: string;
113
+ /**
114
+ * Per-sandbox compute sizing (cpu cores, memory GiB, disk GiB). E2B sizes
115
+ * sandboxes at TEMPLATE BUILD time only (Template.build cpuCount/memoryMB;
116
+ * disk is plan-fixed) — create-time sizing cannot be enforced, so any value
117
+ * here is REJECTED with E2BResourcesError rather than silently ignored.
118
+ * Bake sizing into the template the `image` names instead.
119
+ */
120
+ resources?: {
121
+ cpu?: number;
122
+ memory?: number;
123
+ disk?: number;
124
+ };
125
+ network?: {
126
+ outbound: "open" | "blocked";
127
+ allowedDestinations?: string[];
128
+ };
129
+ /** Run all commands and file operations as this user (passed on every E2B operation that supports it). */
130
+ user?: string;
131
+ /** Home directory used by the SDK for agent config paths; not consumed by the provider. */
132
+ homeDir?: string;
93
133
  }
94
134
  /** Options for listing sandboxes */
95
135
  interface SandboxListOptions {
@@ -127,6 +167,8 @@ interface SandboxFiles {
127
167
  readStream(path: string): Promise<ReadableStream<Uint8Array>>;
128
168
  /** Write from stream */
129
169
  writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
170
+ /** Upload a local file by path, streamed off disk (never buffered whole) */
171
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
130
172
  /** Get pre-signed upload URL for large files (expiration in seconds) */
131
173
  uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
132
174
  /** Get pre-signed download URL for large files (expiration in seconds) */
@@ -164,6 +206,8 @@ interface SandboxInstance {
164
206
  interface SandboxProvider {
165
207
  /** Provider type identifier */
166
208
  readonly providerType: string;
209
+ /** Human-readable provider name for logging */
210
+ readonly name?: string;
167
211
  /** Create new sandbox */
168
212
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
169
213
  /** Connect to existing sandbox */
@@ -187,12 +231,75 @@ interface ResolvedE2BConfig {
187
231
  defaultTimeoutMs?: number;
188
232
  templateId?: string;
189
233
  }
234
+ declare class E2BCommands implements SandboxCommands {
235
+ private sandbox;
236
+ private defaultUser?;
237
+ constructor(sandbox: Sandbox, defaultUser?: string | undefined);
238
+ run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
239
+ spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
240
+ list(): Promise<ProcessInfo[]>;
241
+ connect(processId: string, options?: SandboxConnectOptions): Promise<SandboxCommandHandle>;
242
+ sendStdin(processId: string, data: string): Promise<void>;
243
+ kill(processId: string): Promise<boolean>;
244
+ }
245
+ declare class E2BFiles implements SandboxFiles {
246
+ private sandbox;
247
+ private defaultUser?;
248
+ constructor(sandbox: Sandbox, defaultUser?: string | undefined);
249
+ read(path: string): Promise<string | Uint8Array>;
250
+ write(path: string, content: string | Buffer | ArrayBuffer | Uint8Array): Promise<void>;
251
+ writeBatch(files: Array<{
252
+ path: string;
253
+ data: string | Buffer | ArrayBuffer | Uint8Array;
254
+ }>): Promise<void>;
255
+ makeDir(path: string): Promise<void>;
256
+ uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
257
+ downloadUrl(path: string, expiresInSeconds?: number): Promise<string>;
258
+ exists(path: string): Promise<boolean>;
259
+ list(path: string): Promise<FileInfo[]>;
260
+ remove(path: string): Promise<void>;
261
+ rename(oldPath: string, newPath: string): Promise<void>;
262
+ readStream(path: string): Promise<ReadableStream<Uint8Array>>;
263
+ writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
264
+ /**
265
+ * Upload a local file by PATH, streamed off disk with real backpressure.
266
+ *
267
+ * Why this does NOT go through files.write(): that method calls
268
+ * `new Response(data).blob()` on whatever it is given, which MATERIALIZES the
269
+ * body — measured at +463 MB RSS for a 200 MB source, whether the input is a
270
+ * stream, a Buffer, or even a file-backed Blob. So handing it a stream looks
271
+ * like streaming and is not, which is precisely the trap this method exists to
272
+ * avoid: a caller uploading a large artifact once per concurrent task would
273
+ * still pay the full size every time.
274
+ *
275
+ * Instead the multipart body is assembled as a ReadableStream and POSTed to
276
+ * the signed upload URL with `duplex: "half"` — the same shape E2B's own
277
+ * template-context upload uses. Verified to hold backpressure: against a
278
+ * deliberately slow sink the producer had read 7 MB of a 200 MB file after
279
+ * four seconds, rather than racing to the end.
280
+ *
281
+ * The wire format mirrors files.write()'s single-file case exactly: the
282
+ * destination is the `path` query parameter of the signed URL, and the body is
283
+ * one `file` part. If E2B ever changes that, the POST fails and we fall back to
284
+ * the SDK's own (buffering) path — a correct upload beats a cheap one.
285
+ */
286
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
287
+ watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
288
+ }
190
289
  declare class E2BProvider implements SandboxProvider {
191
290
  readonly providerType: "e2b";
291
+ readonly name = "E2B";
192
292
  private readonly apiKey;
193
293
  private readonly apiUrl?;
194
294
  private readonly defaultTimeoutMs;
195
295
  private readonly templateId?;
296
+ /**
297
+ * Sandbox user configured at create time, reapplied on connect() (e.g., resume).
298
+ * In-memory only: a connect() from a fresh process runs as the template default
299
+ * user — callers reconnecting across processes must recreate the provider config
300
+ * with the same user, or operations on user-owned files fail loudly.
301
+ */
302
+ private readonly sandboxUsers;
196
303
  constructor(config: ResolvedE2BConfig);
197
304
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
198
305
  connect(sandboxId: string, timeoutMs?: number): Promise<SandboxInstance>;
@@ -206,4 +313,4 @@ declare class E2BProvider implements SandboxProvider {
206
313
  */
207
314
  declare function createE2BProvider(config?: E2BConfig): SandboxProvider;
208
315
 
209
- export { type E2BConfig, E2BProvider, type FileInfo, type FilesystemEvent, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, createE2BProvider };
316
+ export { E2BCommands, type E2BConfig, E2BFiles, E2BProvider, E2BResourcesError, type FileInfo, type FilesystemEvent, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, createE2BProvider };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { Sandbox } from '@e2b/code-interpreter';
2
+
1
3
  /**
2
4
  * E2B Sandbox Provider - Clean Architecture
3
5
  *
@@ -11,6 +13,17 @@
11
13
  * - Configuration externalized (no hardcoded mappings)
12
14
  * - Clear naming (run = blocking, spawn = background)
13
15
  */
16
+
17
+ /**
18
+ * Typed error for create-time sizing requests E2B cannot enforce.
19
+ * E2B sandboxes inherit cpu/memory from their TEMPLATE (Template.build
20
+ * cpuCount/memoryMB; disk is plan-fixed) — Sandbox.create has no sizing
21
+ * parameters, so a `resources` request would be silently ignored. Per the
22
+ * provider law (reject what you cannot enforce) it is refused loudly here.
23
+ */
24
+ declare class E2BResourcesError extends Error {
25
+ constructor(message: string);
26
+ }
14
27
  /** Result of a completed sandbox command */
15
28
  interface SandboxCommandResult {
16
29
  exitCode: number;
@@ -85,11 +98,38 @@ interface SandboxConnectOptions {
85
98
  }
86
99
  /** Options for creating a sandbox */
87
100
  interface SandboxCreateOptions {
88
- image: string;
101
+ /**
102
+ * E2B template ID. OPTIONAL: create() falls back to the provider's
103
+ * configured `templateId`, then to "evolve-all" — declaring it required
104
+ * contradicted that implementation and only went unnoticed because TS
105
+ * method parameters are bivariant, so the SDK could already call
106
+ * create({}) through the shared contract.
107
+ */
108
+ image?: string;
89
109
  envs?: Record<string, string>;
90
110
  metadata?: Record<string, string>;
91
111
  timeoutMs?: number;
92
112
  workingDirectory?: string;
113
+ /**
114
+ * Per-sandbox compute sizing (cpu cores, memory GiB, disk GiB). E2B sizes
115
+ * sandboxes at TEMPLATE BUILD time only (Template.build cpuCount/memoryMB;
116
+ * disk is plan-fixed) — create-time sizing cannot be enforced, so any value
117
+ * here is REJECTED with E2BResourcesError rather than silently ignored.
118
+ * Bake sizing into the template the `image` names instead.
119
+ */
120
+ resources?: {
121
+ cpu?: number;
122
+ memory?: number;
123
+ disk?: number;
124
+ };
125
+ network?: {
126
+ outbound: "open" | "blocked";
127
+ allowedDestinations?: string[];
128
+ };
129
+ /** Run all commands and file operations as this user (passed on every E2B operation that supports it). */
130
+ user?: string;
131
+ /** Home directory used by the SDK for agent config paths; not consumed by the provider. */
132
+ homeDir?: string;
93
133
  }
94
134
  /** Options for listing sandboxes */
95
135
  interface SandboxListOptions {
@@ -127,6 +167,8 @@ interface SandboxFiles {
127
167
  readStream(path: string): Promise<ReadableStream<Uint8Array>>;
128
168
  /** Write from stream */
129
169
  writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
170
+ /** Upload a local file by path, streamed off disk (never buffered whole) */
171
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
130
172
  /** Get pre-signed upload URL for large files (expiration in seconds) */
131
173
  uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
132
174
  /** Get pre-signed download URL for large files (expiration in seconds) */
@@ -164,6 +206,8 @@ interface SandboxInstance {
164
206
  interface SandboxProvider {
165
207
  /** Provider type identifier */
166
208
  readonly providerType: string;
209
+ /** Human-readable provider name for logging */
210
+ readonly name?: string;
167
211
  /** Create new sandbox */
168
212
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
169
213
  /** Connect to existing sandbox */
@@ -187,12 +231,75 @@ interface ResolvedE2BConfig {
187
231
  defaultTimeoutMs?: number;
188
232
  templateId?: string;
189
233
  }
234
+ declare class E2BCommands implements SandboxCommands {
235
+ private sandbox;
236
+ private defaultUser?;
237
+ constructor(sandbox: Sandbox, defaultUser?: string | undefined);
238
+ run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
239
+ spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
240
+ list(): Promise<ProcessInfo[]>;
241
+ connect(processId: string, options?: SandboxConnectOptions): Promise<SandboxCommandHandle>;
242
+ sendStdin(processId: string, data: string): Promise<void>;
243
+ kill(processId: string): Promise<boolean>;
244
+ }
245
+ declare class E2BFiles implements SandboxFiles {
246
+ private sandbox;
247
+ private defaultUser?;
248
+ constructor(sandbox: Sandbox, defaultUser?: string | undefined);
249
+ read(path: string): Promise<string | Uint8Array>;
250
+ write(path: string, content: string | Buffer | ArrayBuffer | Uint8Array): Promise<void>;
251
+ writeBatch(files: Array<{
252
+ path: string;
253
+ data: string | Buffer | ArrayBuffer | Uint8Array;
254
+ }>): Promise<void>;
255
+ makeDir(path: string): Promise<void>;
256
+ uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
257
+ downloadUrl(path: string, expiresInSeconds?: number): Promise<string>;
258
+ exists(path: string): Promise<boolean>;
259
+ list(path: string): Promise<FileInfo[]>;
260
+ remove(path: string): Promise<void>;
261
+ rename(oldPath: string, newPath: string): Promise<void>;
262
+ readStream(path: string): Promise<ReadableStream<Uint8Array>>;
263
+ writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
264
+ /**
265
+ * Upload a local file by PATH, streamed off disk with real backpressure.
266
+ *
267
+ * Why this does NOT go through files.write(): that method calls
268
+ * `new Response(data).blob()` on whatever it is given, which MATERIALIZES the
269
+ * body — measured at +463 MB RSS for a 200 MB source, whether the input is a
270
+ * stream, a Buffer, or even a file-backed Blob. So handing it a stream looks
271
+ * like streaming and is not, which is precisely the trap this method exists to
272
+ * avoid: a caller uploading a large artifact once per concurrent task would
273
+ * still pay the full size every time.
274
+ *
275
+ * Instead the multipart body is assembled as a ReadableStream and POSTed to
276
+ * the signed upload URL with `duplex: "half"` — the same shape E2B's own
277
+ * template-context upload uses. Verified to hold backpressure: against a
278
+ * deliberately slow sink the producer had read 7 MB of a 200 MB file after
279
+ * four seconds, rather than racing to the end.
280
+ *
281
+ * The wire format mirrors files.write()'s single-file case exactly: the
282
+ * destination is the `path` query parameter of the signed URL, and the body is
283
+ * one `file` part. If E2B ever changes that, the POST fails and we fall back to
284
+ * the SDK's own (buffering) path — a correct upload beats a cheap one.
285
+ */
286
+ writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
287
+ watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
288
+ }
190
289
  declare class E2BProvider implements SandboxProvider {
191
290
  readonly providerType: "e2b";
291
+ readonly name = "E2B";
192
292
  private readonly apiKey;
193
293
  private readonly apiUrl?;
194
294
  private readonly defaultTimeoutMs;
195
295
  private readonly templateId?;
296
+ /**
297
+ * Sandbox user configured at create time, reapplied on connect() (e.g., resume).
298
+ * In-memory only: a connect() from a fresh process runs as the template default
299
+ * user — callers reconnecting across processes must recreate the provider config
300
+ * with the same user, or operations on user-owned files fail loudly.
301
+ */
302
+ private readonly sandboxUsers;
196
303
  constructor(config: ResolvedE2BConfig);
197
304
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
198
305
  connect(sandboxId: string, timeoutMs?: number): Promise<SandboxInstance>;
@@ -206,4 +313,4 @@ declare class E2BProvider implements SandboxProvider {
206
313
  */
207
314
  declare function createE2BProvider(config?: E2BConfig): SandboxProvider;
208
315
 
209
- export { type E2BConfig, E2BProvider, type FileInfo, type FilesystemEvent, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, createE2BProvider };
316
+ export { E2BCommands, type E2BConfig, E2BFiles, E2BProvider, E2BResourcesError, type FileInfo, type FilesystemEvent, type ProcessInfo, type SandboxCommandHandle, type SandboxCommandResult, type SandboxCommands, type SandboxConnectOptions, type SandboxCreateOptions, type SandboxFiles, type SandboxInfo, type SandboxInstance, type SandboxListOptions, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, createE2BProvider };
package/dist/index.js CHANGED
@@ -1,2 +1,8 @@
1
- import {Sandbox}from'@e2b/code-interpreter';var p=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function a(i){return i instanceof Date?i.toISOString():String(i)}function l(i){if(typeof i=="string"||i instanceof ArrayBuffer)return i;if(i instanceof Buffer)return new Uint8Array(i).buffer;if(i instanceof Uint8Array)return new Uint8Array(i).buffer;throw new Error(`Unsupported data type for file upload: ${typeof i}. Expected string, Buffer, ArrayBuffer, or Uint8Array.`)}function g(i){let t=i.substring(i.lastIndexOf(".")).toLowerCase();return p.has(t)}var m=class{constructor(t){this.sandbox=t;}async run(t,e){try{let n=await this.sandbox.commands.run(t,{timeoutMs:e?.timeoutMs,envs:e?.envs,cwd:e?.cwd,onStdout:e?.onStdout,onStderr:e?.onStderr});return {exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch(n){if(n&&typeof n=="object"&&"exitCode"in n){let r=n;return {exitCode:r.exitCode,stdout:r.stdout??"",stderr:r.stderr??""}}throw n}}async spawn(t,e){let n=await this.sandbox.commands.run(t,{background:true,stdin:e?.stdin??true,timeoutMs:e?.timeoutMs,envs:e?.envs,cwd:e?.cwd,onStdout:e?.onStdout,onStderr:e?.onStderr});return {processId:String(n.pid),wait:async()=>{try{let r=await n.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let s=r;return {exitCode:s.exitCode,stdout:s.stdout??"",stderr:s.stderr??""}}throw r}},kill:()=>this.sandbox.commands.kill(n.pid)}}async list(){return (await this.sandbox.commands.list()).map(e=>({...e,processId:String(e.pid)}))}async connect(t,e){let n=await this.sandbox.commands.connect(Number(t),{onStdout:e?.onStdout,onStderr:e?.onStderr,timeoutMs:e?.timeoutMs});return {processId:String(n.pid),wait:async()=>{try{let r=await n.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let s=r;return {exitCode:s.exitCode,stdout:s.stdout??"",stderr:s.stderr??""}}throw r}},kill:()=>this.sandbox.commands.kill(n.pid)}}async sendStdin(t,e){await this.sandbox.commands.sendStdin(Number(t),e);}async kill(t){return this.sandbox.commands.kill(Number(t))}},c=class{constructor(t){this.sandbox=t;}async read(t){return g(t)?this.sandbox.files.read(t,{format:"bytes",requestTimeoutMs:3e5}):this.sandbox.files.read(t,{format:"text",requestTimeoutMs:3e5})}async write(t,e){await this.sandbox.files.write(t,l(e),{requestTimeoutMs:3e5});}async writeBatch(t){let e=t.map(n=>({path:n.path,data:l(n.data)}));await this.sandbox.files.write(e,{requestTimeoutMs:3e5});}async makeDir(t){await this.sandbox.files.makeDir(t);}async uploadUrl(t,e){return this.sandbox.uploadUrl(t,e?{useSignatureExpiration:e}:void 0)}async downloadUrl(t,e){return this.sandbox.downloadUrl(t,e?{useSignatureExpiration:e}:void 0)}async exists(t){return this.sandbox.files.exists(t)}async list(t){return (await this.sandbox.files.list(t)).map(n=>({name:n.name,path:n.path,type:n.type==="dir"?"dir":"file"}))}async remove(t){await this.sandbox.files.remove(t);}async rename(t,e){await this.sandbox.files.rename(t,e);}async readStream(t){return this.sandbox.files.read(t,{format:"stream"})}async writeStream(t,e){await this.sandbox.files.write(t,e);}async watchDir(t,e,n){let r=await this.sandbox.files.watchDir(t,e,{recursive:n?.recursive,timeoutMs:n?.timeoutMs,onExit:n?.onExit});return {stop:()=>r.stop()}}},o=class{constructor(t,e,n){this.sandbox=t;this.apiKey=e;this.apiUrl=n;this.commands=new m(t),this.files=new c(t);}commands;files;get sandboxId(){return this.sandbox.sandboxId}getHost(t){return Promise.resolve(this.sandbox.getHost(t))}async isRunning(){return this.sandbox.isRunning()}async getInfo(){let t=await this.sandbox.getInfo();return {sandboxId:t.sandboxId,image:t.templateId,name:t.name,metadata:t.metadata??{},startedAt:a(t.startedAt),endAt:t.endAt?a(t.endAt):void 0}}async kill(){try{await this.sandbox.kill();}catch{await new Promise(t=>setTimeout(t,500)),await this.sandbox.kill();}}async pause(){await this.sandbox.betaPause({apiKey:this.apiKey,apiUrl:this.apiUrl});}},u=class{providerType="e2b";apiKey;apiUrl;defaultTimeoutMs;templateId;constructor(t){this.apiKey=t.apiKey,this.apiUrl=t.apiUrl,this.defaultTimeoutMs=t.defaultTimeoutMs??36e5,this.templateId=t.templateId;}async create(t){let e=t.timeoutMs??this.defaultTimeoutMs,n=t.image??this.templateId??"evolve-all",r=await Sandbox.create(n,{apiKey:this.apiKey,apiUrl:this.apiUrl,envs:t.envs,metadata:t.metadata,timeoutMs:e});return t.workingDirectory&&await r.files.makeDir(t.workingDirectory),new o(r,this.apiKey,this.apiUrl)}async connect(t,e){let n=await Sandbox.connect(t,{apiKey:this.apiKey,apiUrl:this.apiUrl,timeoutMs:e??this.defaultTimeoutMs});return new o(n,this.apiKey,this.apiUrl)}async list(t){return (await Sandbox.list({apiKey:this.apiKey,apiUrl:this.apiUrl,query:{state:t?.state,metadata:t?.metadata},limit:t?.limit??100}).nextItems()).map(r=>({sandboxId:r.sandboxId,image:r.templateId,name:r.name,metadata:r.metadata??{},startedAt:a(r.startedAt),endAt:r.endAt?a(r.endAt):void 0}))}};function b(i={}){let t=i.apiKey??process.env.E2B_API_KEY;if(!t)throw new Error("E2B API key required. Set E2B_API_KEY environment variable or pass apiKey in config. Get your key at https://e2b.dev/sign-in");return new u({...i,apiKey:t})}
2
- export{u as E2BProvider,b as createE2BProvider};
1
+ import {Sandbox}from'@e2b/code-interpreter';function f(n){if(!n||typeof n!="object")return false;if(n.name==="TimeoutError")return true;let e=n.message;return typeof e=="string"&&/timed?\s*out/i.test(e)}var P=new Set([".xlsx",".xls",".docx",".doc",".pptx",".ppt",".pdf",".zip",".tar",".gz",".7z",".rar",".png",".jpg",".jpeg",".gif",".webp",".ico",".bmp",".mp3",".wav",".ogg",".flac",".aac",".mp4",".avi",".mov",".mkv",".webm",".woff",".woff2",".ttf",".otf",".eot",".exe",".dll",".so",".dylib",".sqlite",".db",".pickle",".pkl",".parquet"]);function m(n){return n instanceof Date?n.toISOString():String(n)}function w(n){if(typeof n=="string"||n instanceof ArrayBuffer)return n;if(n instanceof Buffer)return new Uint8Array(n).buffer;if(n instanceof Uint8Array)return new Uint8Array(n).buffer;throw new Error(`Unsupported data type for file upload: ${typeof n}. Expected string, Buffer, ArrayBuffer, or Uint8Array.`)}function U(n){let e=n.substring(n.lastIndexOf(".")).toLowerCase();return P.has(e)}var g=class extends Error{constructor(e){super(e),this.name="E2BResourcesError";}},p=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async run(e,t){try{let s=await this.sandbox.commands.run(e,{timeoutMs:t?.timeoutMs,envs:t?.envs,cwd:t?.cwd,user:this.defaultUser,onStdout:t?.onStdout,onStderr:t?.onStderr});return {exitCode:s.exitCode,stdout:s.stdout,stderr:s.stderr}}catch(s){if(s&&typeof s=="object"&&"exitCode"in s){let r=s;return {exitCode:r.exitCode,stdout:r.stdout??"",stderr:r.stderr??""}}if(f(s))return {exitCode:124,stdout:"",stderr:s instanceof Error?s.message:"command timed out"};throw s}}async spawn(e,t){let s=await this.sandbox.commands.run(e,{background:true,stdin:t?.stdin??true,timeoutMs:t?.timeoutMs,envs:t?.envs,cwd:t?.cwd,user:this.defaultUser,onStdout:t?.onStdout,onStderr:t?.onStderr});return {processId:String(s.pid),wait:async()=>{try{let r=await s.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let i=r;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(f(r))return {exitCode:124,stdout:"",stderr:r instanceof Error?r.message:"command timed out"};throw r}},kill:()=>this.sandbox.commands.kill(s.pid)}}async list(){return (await this.sandbox.commands.list()).map(t=>({...t,processId:String(t.pid)}))}async connect(e,t){let s=await this.sandbox.commands.connect(Number(e),{onStdout:t?.onStdout,onStderr:t?.onStderr,timeoutMs:t?.timeoutMs});return {processId:String(s.pid),wait:async()=>{try{let r=await s.wait();return {exitCode:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let i=r;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(f(r))return {exitCode:124,stdout:"",stderr:r instanceof Error?r.message:"command timed out"};throw r}},kill:()=>this.sandbox.commands.kill(s.pid)}}async sendStdin(e,t){await this.sandbox.commands.sendStdin(Number(e),t);}async kill(e){return this.sandbox.commands.kill(Number(e))}},b=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async read(e){return U(e)?this.sandbox.files.read(e,{format:"bytes",requestTimeoutMs:3e5,user:this.defaultUser}):this.sandbox.files.read(e,{format:"text",requestTimeoutMs:3e5,user:this.defaultUser})}async write(e,t){await this.sandbox.files.write(e,w(t),{requestTimeoutMs:3e5,user:this.defaultUser});}async writeBatch(e){let t=e.map(s=>({path:s.path,data:w(s.data)}));await this.sandbox.files.write(t,{requestTimeoutMs:3e5,user:this.defaultUser});}async makeDir(e){await this.sandbox.files.makeDir(e,{user:this.defaultUser});}async uploadUrl(e,t){return this.sandbox.uploadUrl(e,{user:this.defaultUser,...t?{useSignatureExpiration:t}:{}})}async downloadUrl(e,t){return this.sandbox.downloadUrl(e,{user:this.defaultUser,...t?{useSignatureExpiration:t}:{}})}async exists(e){return this.sandbox.files.exists(e,{user:this.defaultUser})}async list(e){return (await this.sandbox.files.list(e,{user:this.defaultUser})).map(s=>({name:s.name,path:s.path,type:s.type==="dir"?"dir":"file"}))}async remove(e){await this.sandbox.files.remove(e,{user:this.defaultUser});}async rename(e,t){await this.sandbox.files.rename(e,t,{user:this.defaultUser});}async readStream(e){return this.sandbox.files.read(e,{format:"stream",user:this.defaultUser})}async writeStream(e,t){await this.sandbox.files.write(e,t,{user:this.defaultUser});}async writeFromPath(e,t){let{createReadStream:s,statSync:r}=await import('fs'),{Readable:i}=await import('stream'),{randomBytes:o}=await import('crypto'),S=r(t).size,l=`----evolve${o(16).toString("hex")}`,y=Buffer.from(`--${l}\r
2
+ Content-Disposition: form-data; name="file"; filename="blob"\r
3
+ Content-Type: application/octet-stream\r
4
+ \r
5
+ `),h=Buffer.from(`\r
6
+ --${l}--\r
7
+ `);async function*v(){yield y;for await(let a of s(t))yield a;yield h;}try{let a=await this.uploadUrl(e),d=await fetch(a,{method:"POST",body:i.toWeb(i.from(v())),headers:{"Content-Type":`multipart/form-data; boundary=${l}`,"Content-Length":String(y.length+S+h.length)},duplex:"half"});if(!d.ok)throw new Error(`streamed upload to ${e} failed (HTTP ${d.status})`)}catch(a){console.warn(`[e2b] streamed upload of ${t} failed, falling back to a buffered write:`,a instanceof Error?a.message:a);let d=i.toWeb(s(t));await this.writeStream(e,d);}}async watchDir(e,t,s){let r=await this.sandbox.files.watchDir(e,t,{recursive:s?.recursive,timeoutMs:s?.timeoutMs,user:this.defaultUser,onExit:s?.onExit});return {stop:()=>r.stop()}}},u=class{constructor(e,t,s,r){this.sandbox=e;this.apiKey=t;this.apiUrl=s;this.commands=new p(e,r),this.files=new b(e,r);}commands;files;get sandboxId(){return this.sandbox.sandboxId}getHost(e){return Promise.resolve(this.sandbox.getHost(e))}async isRunning(){return this.sandbox.isRunning()}async getInfo(){let e=await this.sandbox.getInfo();return {sandboxId:e.sandboxId,image:e.templateId,name:e.name,metadata:e.metadata??{},startedAt:m(e.startedAt),endAt:e.endAt?m(e.endAt):void 0}}async kill(){try{await this.sandbox.kill();}catch{await new Promise(e=>setTimeout(e,500)),await this.sandbox.kill();}}async pause(){await this.sandbox.betaPause({apiKey:this.apiKey,apiUrl:this.apiUrl});}},x=class{providerType="e2b";name="E2B";apiKey;apiUrl;defaultTimeoutMs;templateId;sandboxUsers=new Map;constructor(e){this.apiKey=e.apiKey,this.apiUrl=e.apiUrl,this.defaultTimeoutMs=e.defaultTimeoutMs??36e5,this.templateId=e.templateId;}async create(e){if(e.resources&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0))throw new g("E2B cannot size a sandbox at create time: sizing is fixed by the template (Template.build cpuCount/memoryMB; disk is plan-fixed). Build a template with the desired resources and pass it as `image` instead of `resources`.");let t=e.timeoutMs??this.defaultTimeoutMs,s=e.image??this.templateId??"evolve-all";if(e.network?.outbound==="open"&&e.network.allowedDestinations?.length)throw new Error("network.allowedDestinations is only valid when outbound is blocked");let r=e.network?.allowedDestinations??[],i=e.network?.outbound==="blocked"&&r.length>0,o=await Sandbox.create(s,{apiKey:this.apiKey,apiUrl:this.apiUrl,envs:e.envs,metadata:e.metadata,timeoutMs:t,allowInternetAccess:e.network?.outbound!=="blocked"||i,network:i?{denyOut:["0.0.0.0/0"],allowOut:r}:void 0});return e.workingDirectory&&await o.files.makeDir(e.workingDirectory,{user:e.user}),e.user&&this.sandboxUsers.set(o.sandboxId,e.user),new u(o,this.apiKey,this.apiUrl,e.user)}async connect(e,t){let s=await Sandbox.connect(e,{apiKey:this.apiKey,apiUrl:this.apiUrl,timeoutMs:t??this.defaultTimeoutMs});return new u(s,this.apiKey,this.apiUrl,this.sandboxUsers.get(e))}async list(e){return (await Sandbox.list({apiKey:this.apiKey,apiUrl:this.apiUrl,query:{state:e?.state,metadata:e?.metadata},limit:e?.limit??100}).nextItems()).map(r=>({sandboxId:r.sandboxId,image:r.templateId,name:r.name,metadata:r.metadata??{},startedAt:m(r.startedAt),endAt:r.endAt?m(r.endAt):void 0}))}};function k(n={}){let e=n.apiKey??process.env.E2B_API_KEY;if(!e)throw new Error("E2B API key required. Set E2B_API_KEY environment variable or pass apiKey in config. Get your key at https://e2b.dev/sign-in");return new x({...n,apiKey:e})}
8
+ export{p as E2BCommands,b as E2BFiles,x as E2BProvider,g as E2BResourcesError,k as createE2BProvider};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolvingmachines/e2b",
3
- "version": "0.0.51",
3
+ "version": "0.0.52-project-sable.20260726.6e95f36",
4
4
  "keywords": [
5
5
  "ai",
6
6
  "agents",