@evolvingmachines/e2b 0.0.52-sable-rename.20260803.6ab54d4 → 0.0.53

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/README.md CHANGED
@@ -1,4 +1,8 @@
1
- # Evolve SDK E2B Provider
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/evolving-machines-lab/evolve/main/logo/evolving-machines-ink.png" alt="Evolving Machines" width="380">
3
+ </p>
4
+
5
+ # Evolving Machines — Evolve E2B Provider
2
6
 
3
7
  E2B sandbox provider for [Evolve SDK](https://www.npmjs.com/package/@evolvingmachines/sdk).
4
8
 
package/dist/index.cjs CHANGED
@@ -1,8 +1,2 @@
1
- 'use strict';var codeInterpreter=require('@e2b/code-interpreter');function p(s){if(!s||typeof s!="object")return false;if(s.name==="TimeoutError")return true;let e=s.message;return typeof e=="string"&&/timed?\s*out/i.test(e)}var P=100,v=100;function u(s){return s instanceof Date?s.toISOString():String(s)}function A(s){if(typeof s=="string"||s instanceof ArrayBuffer)return s;if(s instanceof Buffer)return new Uint8Array(s).buffer;if(s instanceof Uint8Array)return new Uint8Array(s).buffer;throw new Error(`Unsupported data type for file upload: ${typeof s}. Expected string, Buffer, ArrayBuffer, or Uint8Array.`)}var b=class extends Error{constructor(e){super(e),this.name="E2BResourcesError";}},g=class extends Error{constructor(){super("E2B has no idle timeout: its sandbox timeout is an ABSOLUTE lifetime that in-sandbox activity never extends. Use `timeoutMs` for the lifetime, and call setTimeout() to extend a sandbox you know is still working."),this.name="E2BIdleTimeoutError";}},x=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async run(e,t){try{let r=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:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let n=r;return {exitCode:n.exitCode,stdout:n.stdout??"",stderr:n.stderr??""}}if(p(r))return {exitCode:124,stdout:"",stderr:r instanceof Error?r.message:"command timed out"};throw r}}async spawn(e,t){let r=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(r.pid),wait:async()=>{try{let n=await r.wait();return {exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch(n){if(n&&typeof n=="object"&&"exitCode"in n){let i=n;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(p(n))return {exitCode:124,stdout:"",stderr:n instanceof Error?n.message:"command timed out"};throw n}},kill:()=>this.sandbox.commands.kill(r.pid)}}async list(){return (await this.sandbox.commands.list()).map(t=>({...t,processId:String(t.pid)}))}async connect(e,t){let r=await this.sandbox.commands.connect(Number(e),{onStdout:t?.onStdout,onStderr:t?.onStderr,timeoutMs:t?.timeoutMs});return {processId:String(r.pid),wait:async()=>{try{let n=await r.wait();return {exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch(n){if(n&&typeof n=="object"&&"exitCode"in n){let i=n;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(p(n))return {exitCode:124,stdout:"",stderr:n instanceof Error?n.message:"command timed out"};throw n}},kill:()=>this.sandbox.commands.kill(r.pid)}}async sendStdin(e,t){await this.sandbox.commands.sendStdin(Number(e),t);}async kill(e){return this.sandbox.commands.kill(Number(e))}},h=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async read(e){let t=await this.sandbox.files.read(e,{format:"bytes",requestTimeoutMs:3e5,user:this.defaultUser});if(!t.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(t)}catch{}return t}async write(e,t){await this.sandbox.files.write(e,A(t),{requestTimeoutMs:3e5,user:this.defaultUser});}async writeBatch(e){let t=e.map(r=>({path:r.path,data:A(r.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(r=>({name:r.name,path:r.path,type:r.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:r,statSync:n}=await import('fs'),{Readable:i}=await import('stream'),{randomBytes:o}=await import('crypto'),a=n(t).size,c=`----evolve${o(16).toString("hex")}`,w=Buffer.from(`--${c}\r
2
- Content-Disposition: form-data; name="file"; filename="blob"\r
3
- Content-Type: application/octet-stream\r
4
- \r
5
- `),S=Buffer.from(`\r
6
- --${c}--\r
7
- `);async function*I(){yield w;for await(let d of r(t))yield d;yield S;}try{let d=await this.uploadUrl(e),m=await fetch(d,{method:"POST",body:i.toWeb(i.from(I())),headers:{"Content-Type":`multipart/form-data; boundary=${c}`,"Content-Length":String(w.length+a+S.length)},duplex:"half"});if(!m.ok)throw new Error(`streamed upload to ${e} failed (HTTP ${m.status})`)}catch(d){console.warn(`[e2b] streamed upload of ${t} failed, falling back to a buffered write:`,d instanceof Error?d.message:d);let m=i.toWeb(r(t));await this.writeStream(e,m);}}async watchDir(e,t,r){let n=await this.sandbox.files.watchDir(e,t,{recursive:r?.recursive,timeoutMs:r?.timeoutMs,user:this.defaultUser,onExit:r?.onExit});return {stop:()=>n.stop()}}},l=class{constructor(e,t,r,n){this.sandbox=e;this.apiKey=t;this.apiUrl=r;this.commands=new x(e,n),this.files=new h(e,n);}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:u(e.startedAt),endAt:e.endAt?u(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});}},y=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.idleTimeoutMs!==void 0)throw new g;if(e.resources&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0))throw new b("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,r=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 n=e.network?.allowedDestinations??[],i=e.network?.outbound==="blocked"&&n.length>0,o=await codeInterpreter.Sandbox.create(r,{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:n}:void 0});return e.workingDirectory&&await o.files.makeDir(e.workingDirectory,{user:e.user}),e.user&&this.sandboxUsers.set(o.sandboxId,e.user),new l(o,this.apiKey,this.apiUrl,e.user)}async connect(e,t){let r=await codeInterpreter.Sandbox.connect(e,{apiKey:this.apiKey,apiUrl:this.apiUrl,timeoutMs:t??this.defaultTimeoutMs});return new l(r,this.apiKey,this.apiUrl,this.sandboxUsers.get(e))}async list(e){let t=await this.paginate(e);if(t.error&&!t.stoppedAtLimit)throw new Error(t.error);return t.sandboxes}async listAll(e){let{stoppedAtLimit:t,...r}=await this.paginate(e);return r}async paginate(e){let t=e?.limit;return U(codeInterpreter.Sandbox.list({apiKey:this.apiKey,apiUrl:this.apiUrl,query:{state:e?.state,metadata:e?.metadata},limit:t===void 0?P:Math.min(t,P)}),t)}};async function U(s,e){let t=[],r=0,n=new Set;for(;s.hasNext;){if(r>=v)return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list exceeded ${v} pages`};let i=s.nextToken;if(i!==void 0){if(n.has(i))return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:false,error:"pagination token repeated"};n.add(i);}let o;try{o=await s.nextItems();}catch(a){return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list failed: ${a instanceof Error?a.message:String(a)}`}}r+=1;for(let a of o){if(e!==void 0&&t.length>=e)return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${e} with more sandboxes available`};t.push({sandboxId:a.sandboxId,image:a.templateId,name:a.name,metadata:a.metadata??{},startedAt:u(a.startedAt),endAt:a.endAt?u(a.endAt):void 0});}if(e!==void 0&&t.length>=e&&s.hasNext)return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${e} with more sandboxes available`};if(e!==void 0&&t.length>=e)break}return {sandboxes:t,complete:true,pagesFetched:r,stoppedAtLimit:false}}var E=U;function C(s={}){let e=s.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 y({...s,apiKey:e})}
8
- exports.E2BCommands=x;exports.E2BFiles=h;exports.E2BIdleTimeoutError=g;exports.E2BProvider=y;exports.E2BResourcesError=b;exports.E2B_MAX_LIST_PAGES=v;exports.E2B_MAX_PAGE_SIZE=P;exports._testCollectSandboxPages=E;exports.createE2BProvider=C;
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;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,3 @@
1
- import { Sandbox } from '@e2b/code-interpreter';
2
-
3
1
  /**
4
2
  * E2B Sandbox Provider - Clean Architecture
5
3
  *
@@ -13,40 +11,6 @@ import { Sandbox } from '@e2b/code-interpreter';
13
11
  * - Configuration externalized (no hardcoded mappings)
14
12
  * - Clear naming (run = blocking, spawn = background)
15
13
  */
16
-
17
- /**
18
- * Largest page E2B will serve. Not a taste choice — a larger `limit` is refused
19
- * outright: `400 validation error: parameter "limit" in query has an error:
20
- * number must be at most 100`.
21
- */
22
- declare const E2B_MAX_PAGE_SIZE = 100;
23
- /**
24
- * Page ceiling for one enumeration — 10,000 sandboxes at the maximum page size.
25
- * A walk that reaches it stops and reports itself INCOMPLETE, because the one
26
- * thing a fleet enumeration may never do is return a short list that reads like
27
- * a whole one.
28
- */
29
- declare const E2B_MAX_LIST_PAGES = 100;
30
- /**
31
- * Typed error for create-time sizing requests E2B cannot enforce.
32
- * E2B sandboxes inherit cpu/memory from their TEMPLATE (Template.build
33
- * cpuCount/memoryMB; disk is plan-fixed) — Sandbox.create has no sizing
34
- * parameters, so a `resources` request would be silently ignored. Per the
35
- * provider law (reject what you cannot enforce) it is refused loudly here.
36
- */
37
- declare class E2BResourcesError extends Error {
38
- constructor(message: string);
39
- }
40
- /**
41
- * Typed error for an idle timeout E2B cannot enforce. E2B has exactly one
42
- * clock and it is absolute: the sandbox is killed when its timeout expires,
43
- * and only explicit client calls (create, connect, setTimeout) move that
44
- * deadline — never what the sandbox is or is not doing. An `idleTimeoutMs`
45
- * would therefore be silently ignored, so it is refused instead.
46
- */
47
- declare class E2BIdleTimeoutError extends Error {
48
- constructor();
49
- }
50
14
  /** Result of a completed sandbox command */
51
15
  interface SandboxCommandResult {
52
16
  exitCode: number;
@@ -121,44 +85,11 @@ interface SandboxConnectOptions {
121
85
  }
122
86
  /** Options for creating a sandbox */
123
87
  interface SandboxCreateOptions {
124
- /**
125
- * E2B template ID. OPTIONAL: create() falls back to the provider's
126
- * configured `templateId`, then to "evolve-all" — declaring it required
127
- * contradicted that implementation and only went unnoticed because TS
128
- * method parameters are bivariant, so the SDK could already call
129
- * create({}) through the shared contract.
130
- */
131
- image?: string;
88
+ image: string;
132
89
  envs?: Record<string, string>;
133
90
  metadata?: Record<string, string>;
134
91
  timeoutMs?: number;
135
- /**
136
- * REJECTED with E2BIdleTimeoutError. E2B's timeout is an ABSOLUTE lifetime
137
- * that in-sandbox activity never extends, so there is no inactivity clock to
138
- * map this onto and honouring it would be a lie.
139
- */
140
- idleTimeoutMs?: number;
141
92
  workingDirectory?: string;
142
- /**
143
- * Per-sandbox compute sizing (cpu cores, memory GiB, disk GiB). E2B sizes
144
- * sandboxes at TEMPLATE BUILD time only (Template.build cpuCount/memoryMB;
145
- * disk is plan-fixed) — create-time sizing cannot be enforced, so any value
146
- * here is REJECTED with E2BResourcesError rather than silently ignored.
147
- * Bake sizing into the template the `image` names instead.
148
- */
149
- resources?: {
150
- cpu?: number;
151
- memory?: number;
152
- disk?: number;
153
- };
154
- network?: {
155
- outbound: "open" | "blocked";
156
- allowedDestinations?: string[];
157
- };
158
- /** Run all commands and file operations as this user (passed on every E2B operation that supports it). */
159
- user?: string;
160
- /** Home directory used by the SDK for agent config paths; not consumed by the provider. */
161
- homeDir?: string;
162
93
  }
163
94
  /** Options for listing sandboxes */
164
95
  interface SandboxListOptions {
@@ -166,20 +97,6 @@ interface SandboxListOptions {
166
97
  metadata?: Record<string, string>;
167
98
  limit?: number;
168
99
  }
169
- /**
170
- * A COMPLETE (or admittedly incomplete) enumeration of the project's fleet.
171
- *
172
- * `complete` is the load-bearing field. Callers that need a whole fleet —
173
- * orphan sweeps, lifecycle reconciliation — read a sandbox's ABSENCE from the
174
- * list as evidence it is gone, so a truncated page and a small fleet must never
175
- * be the same answer. `complete: false` means leave every row alone.
176
- */
177
- interface SandboxListPage {
178
- sandboxes: SandboxInfo[];
179
- complete: boolean;
180
- pagesFetched: number;
181
- error?: string;
182
- }
183
100
  /** Command execution capabilities */
184
101
  interface SandboxCommands {
185
102
  /** Run command and wait for completion */
@@ -210,8 +127,6 @@ interface SandboxFiles {
210
127
  readStream(path: string): Promise<ReadableStream<Uint8Array>>;
211
128
  /** Write from stream */
212
129
  writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
213
- /** Upload a local file by path, streamed off disk (never buffered whole) */
214
- writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
215
130
  /** Get pre-signed upload URL for large files (expiration in seconds) */
216
131
  uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
217
132
  /** Get pre-signed download URL for large files (expiration in seconds) */
@@ -249,16 +164,12 @@ interface SandboxInstance {
249
164
  interface SandboxProvider {
250
165
  /** Provider type identifier */
251
166
  readonly providerType: string;
252
- /** Human-readable provider name for logging */
253
- readonly name?: string;
254
167
  /** Create new sandbox */
255
168
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
256
169
  /** Connect to existing sandbox */
257
170
  connect(sandboxId: string, timeoutMs?: number): Promise<SandboxInstance>;
258
- /** List sandboxes, paginating to exhaustion. `limit` bounds items returned. */
171
+ /** List sandboxes (first page only, up to limit) */
259
172
  list(options?: SandboxListOptions): Promise<SandboxInfo[]>;
260
- /** The same enumeration for fleet bookkeeping: never throws, reports completeness. */
261
- listAll(options?: SandboxListOptions): Promise<SandboxListPage>;
262
173
  }
263
174
  interface E2BConfig {
264
175
  /** E2B API key. Default: reads from E2B_API_KEY env var */
@@ -276,134 +187,17 @@ interface ResolvedE2BConfig {
276
187
  defaultTimeoutMs?: number;
277
188
  templateId?: string;
278
189
  }
279
- declare class E2BCommands implements SandboxCommands {
280
- private sandbox;
281
- private defaultUser?;
282
- constructor(sandbox: Sandbox, defaultUser?: string | undefined);
283
- run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
284
- spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
285
- list(): Promise<ProcessInfo[]>;
286
- connect(processId: string, options?: SandboxConnectOptions): Promise<SandboxCommandHandle>;
287
- sendStdin(processId: string, data: string): Promise<void>;
288
- kill(processId: string): Promise<boolean>;
289
- }
290
- declare class E2BFiles implements SandboxFiles {
291
- private sandbox;
292
- private defaultUser?;
293
- constructor(sandbox: Sandbox, defaultUser?: string | undefined);
294
- read(path: string): Promise<string | Uint8Array>;
295
- write(path: string, content: string | Buffer | ArrayBuffer | Uint8Array): Promise<void>;
296
- writeBatch(files: Array<{
297
- path: string;
298
- data: string | Buffer | ArrayBuffer | Uint8Array;
299
- }>): Promise<void>;
300
- makeDir(path: string): Promise<void>;
301
- uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
302
- downloadUrl(path: string, expiresInSeconds?: number): Promise<string>;
303
- exists(path: string): Promise<boolean>;
304
- list(path: string): Promise<FileInfo[]>;
305
- remove(path: string): Promise<void>;
306
- rename(oldPath: string, newPath: string): Promise<void>;
307
- readStream(path: string): Promise<ReadableStream<Uint8Array>>;
308
- writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
309
- /**
310
- * Upload a local file by PATH, streamed off disk with real backpressure.
311
- *
312
- * Why this does NOT go through files.write(): that method calls
313
- * `new Response(data).blob()` on whatever it is given, which MATERIALIZES the
314
- * body — measured at +463 MB RSS for a 200 MB source, whether the input is a
315
- * stream, a Buffer, or even a file-backed Blob. So handing it a stream looks
316
- * like streaming and is not, which is precisely the trap this method exists to
317
- * avoid: a caller uploading a large artifact once per concurrent task would
318
- * still pay the full size every time.
319
- *
320
- * Instead the multipart body is assembled as a ReadableStream and POSTed to
321
- * the signed upload URL with `duplex: "half"` — the same shape E2B's own
322
- * template-context upload uses. Verified to hold backpressure: against a
323
- * deliberately slow sink the producer had read 7 MB of a 200 MB file after
324
- * four seconds, rather than racing to the end.
325
- *
326
- * The wire format mirrors files.write()'s single-file case exactly: the
327
- * destination is the `path` query parameter of the signed URL, and the body is
328
- * one `file` part. If E2B ever changes that, the POST fails and we fall back to
329
- * the SDK's own (buffering) path — a correct upload beats a cheap one.
330
- */
331
- writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
332
- watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
333
- }
334
190
  declare class E2BProvider implements SandboxProvider {
335
191
  readonly providerType: "e2b";
336
- readonly name = "E2B";
337
192
  private readonly apiKey;
338
193
  private readonly apiUrl?;
339
194
  private readonly defaultTimeoutMs;
340
195
  private readonly templateId?;
341
- /**
342
- * Sandbox user configured at create time, reapplied on connect() (e.g., resume).
343
- * In-memory only: a connect() from a fresh process runs as the template default
344
- * user — callers reconnecting across processes must recreate the provider config
345
- * with the same user, or operations on user-owned files fail loudly.
346
- */
347
- private readonly sandboxUsers;
348
196
  constructor(config: ResolvedE2BConfig);
349
197
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
350
198
  connect(sandboxId: string, timeoutMs?: number): Promise<SandboxInstance>;
351
- /**
352
- * List sandboxes, walking every page.
353
- *
354
- * This used to call `nextItems()` exactly once and return whatever the first
355
- * page held — an account with more than E2B_MAX_PAGE_SIZE sandboxes was
356
- * silently truncated, and nothing in the return value said so. That is a
357
- * correctness bug rather than a performance one for any caller that reads
358
- * absence from the list as "this sandbox is gone".
359
- *
360
- * `limit` still means what a caller expects: stop after this many ITEMS, so
361
- * an explicit limit remains a cost bound. The per-request page size is capped
362
- * separately at E2B_MAX_PAGE_SIZE because E2B rejects anything larger
363
- * outright (`400 validation error: parameter "limit" ... must be at most
364
- * 100`), so a caller asking for 500 gets five requests, not one refusal.
365
- */
366
199
  list(options?: SandboxListOptions): Promise<SandboxInfo[]>;
367
- /**
368
- * The fleet-bookkeeping enumeration: same walk, never throws.
369
- *
370
- * The distinction from `list()` is what a failure MEANS to the caller. An
371
- * orphan sweep treats a missing sandbox as a terminated one, so it must be
372
- * able to tell "the project has no sandboxes" from "the enumeration stopped
373
- * early" — and an exception it catches and turns into an empty array erases
374
- * exactly that difference.
375
- */
376
- listAll(options?: SandboxListOptions): Promise<SandboxListPage>;
377
- private paginate;
378
200
  }
379
- /** The paginator surface this walk needs — E2B's SandboxPaginator satisfies it. */
380
- interface E2BSandboxPaginator {
381
- readonly hasNext: boolean;
382
- readonly nextToken?: string;
383
- nextItems(): Promise<Array<{
384
- sandboxId: string;
385
- templateId: string;
386
- name?: string;
387
- metadata?: Record<string, string>;
388
- startedAt: unknown;
389
- endAt?: unknown;
390
- }>>;
391
- }
392
- /**
393
- * Drain a paginator into one answer, with an honest completeness verdict.
394
- *
395
- * Separate from the provider because everything worth getting wrong lives here
396
- * and none of it needs a network: the two ways a walk can fail to terminate,
397
- * the difference between "the caller asked for ten" and "the provider ran out",
398
- * and the rule that a failure mid-walk yields the sandboxes seen so far marked
399
- * INCOMPLETE rather than either an exception or a short complete list.
400
- *
401
- * Exported for its test (`_testCollectSandboxPages`).
402
- */
403
- declare function collectSandboxPages(paginator: E2BSandboxPaginator, wanted?: number): Promise<SandboxListPage & {
404
- stoppedAtLimit: boolean;
405
- }>;
406
- declare const _testCollectSandboxPages: typeof collectSandboxPages;
407
201
  /**
408
202
  * Create E2B sandbox provider.
409
203
  *
@@ -412,4 +206,4 @@ declare const _testCollectSandboxPages: typeof collectSandboxPages;
412
206
  */
413
207
  declare function createE2BProvider(config?: E2BConfig): SandboxProvider;
414
208
 
415
- export { E2BCommands, type E2BConfig, E2BFiles, E2BIdleTimeoutError, E2BProvider, E2BResourcesError, type E2BSandboxPaginator, E2B_MAX_LIST_PAGES, E2B_MAX_PAGE_SIZE, 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 SandboxListPage, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, _testCollectSandboxPages, createE2BProvider };
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 };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,3 @@
1
- import { Sandbox } from '@e2b/code-interpreter';
2
-
3
1
  /**
4
2
  * E2B Sandbox Provider - Clean Architecture
5
3
  *
@@ -13,40 +11,6 @@ import { Sandbox } from '@e2b/code-interpreter';
13
11
  * - Configuration externalized (no hardcoded mappings)
14
12
  * - Clear naming (run = blocking, spawn = background)
15
13
  */
16
-
17
- /**
18
- * Largest page E2B will serve. Not a taste choice — a larger `limit` is refused
19
- * outright: `400 validation error: parameter "limit" in query has an error:
20
- * number must be at most 100`.
21
- */
22
- declare const E2B_MAX_PAGE_SIZE = 100;
23
- /**
24
- * Page ceiling for one enumeration — 10,000 sandboxes at the maximum page size.
25
- * A walk that reaches it stops and reports itself INCOMPLETE, because the one
26
- * thing a fleet enumeration may never do is return a short list that reads like
27
- * a whole one.
28
- */
29
- declare const E2B_MAX_LIST_PAGES = 100;
30
- /**
31
- * Typed error for create-time sizing requests E2B cannot enforce.
32
- * E2B sandboxes inherit cpu/memory from their TEMPLATE (Template.build
33
- * cpuCount/memoryMB; disk is plan-fixed) — Sandbox.create has no sizing
34
- * parameters, so a `resources` request would be silently ignored. Per the
35
- * provider law (reject what you cannot enforce) it is refused loudly here.
36
- */
37
- declare class E2BResourcesError extends Error {
38
- constructor(message: string);
39
- }
40
- /**
41
- * Typed error for an idle timeout E2B cannot enforce. E2B has exactly one
42
- * clock and it is absolute: the sandbox is killed when its timeout expires,
43
- * and only explicit client calls (create, connect, setTimeout) move that
44
- * deadline — never what the sandbox is or is not doing. An `idleTimeoutMs`
45
- * would therefore be silently ignored, so it is refused instead.
46
- */
47
- declare class E2BIdleTimeoutError extends Error {
48
- constructor();
49
- }
50
14
  /** Result of a completed sandbox command */
51
15
  interface SandboxCommandResult {
52
16
  exitCode: number;
@@ -121,44 +85,11 @@ interface SandboxConnectOptions {
121
85
  }
122
86
  /** Options for creating a sandbox */
123
87
  interface SandboxCreateOptions {
124
- /**
125
- * E2B template ID. OPTIONAL: create() falls back to the provider's
126
- * configured `templateId`, then to "evolve-all" — declaring it required
127
- * contradicted that implementation and only went unnoticed because TS
128
- * method parameters are bivariant, so the SDK could already call
129
- * create({}) through the shared contract.
130
- */
131
- image?: string;
88
+ image: string;
132
89
  envs?: Record<string, string>;
133
90
  metadata?: Record<string, string>;
134
91
  timeoutMs?: number;
135
- /**
136
- * REJECTED with E2BIdleTimeoutError. E2B's timeout is an ABSOLUTE lifetime
137
- * that in-sandbox activity never extends, so there is no inactivity clock to
138
- * map this onto and honouring it would be a lie.
139
- */
140
- idleTimeoutMs?: number;
141
92
  workingDirectory?: string;
142
- /**
143
- * Per-sandbox compute sizing (cpu cores, memory GiB, disk GiB). E2B sizes
144
- * sandboxes at TEMPLATE BUILD time only (Template.build cpuCount/memoryMB;
145
- * disk is plan-fixed) — create-time sizing cannot be enforced, so any value
146
- * here is REJECTED with E2BResourcesError rather than silently ignored.
147
- * Bake sizing into the template the `image` names instead.
148
- */
149
- resources?: {
150
- cpu?: number;
151
- memory?: number;
152
- disk?: number;
153
- };
154
- network?: {
155
- outbound: "open" | "blocked";
156
- allowedDestinations?: string[];
157
- };
158
- /** Run all commands and file operations as this user (passed on every E2B operation that supports it). */
159
- user?: string;
160
- /** Home directory used by the SDK for agent config paths; not consumed by the provider. */
161
- homeDir?: string;
162
93
  }
163
94
  /** Options for listing sandboxes */
164
95
  interface SandboxListOptions {
@@ -166,20 +97,6 @@ interface SandboxListOptions {
166
97
  metadata?: Record<string, string>;
167
98
  limit?: number;
168
99
  }
169
- /**
170
- * A COMPLETE (or admittedly incomplete) enumeration of the project's fleet.
171
- *
172
- * `complete` is the load-bearing field. Callers that need a whole fleet —
173
- * orphan sweeps, lifecycle reconciliation — read a sandbox's ABSENCE from the
174
- * list as evidence it is gone, so a truncated page and a small fleet must never
175
- * be the same answer. `complete: false` means leave every row alone.
176
- */
177
- interface SandboxListPage {
178
- sandboxes: SandboxInfo[];
179
- complete: boolean;
180
- pagesFetched: number;
181
- error?: string;
182
- }
183
100
  /** Command execution capabilities */
184
101
  interface SandboxCommands {
185
102
  /** Run command and wait for completion */
@@ -210,8 +127,6 @@ interface SandboxFiles {
210
127
  readStream(path: string): Promise<ReadableStream<Uint8Array>>;
211
128
  /** Write from stream */
212
129
  writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
213
- /** Upload a local file by path, streamed off disk (never buffered whole) */
214
- writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
215
130
  /** Get pre-signed upload URL for large files (expiration in seconds) */
216
131
  uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
217
132
  /** Get pre-signed download URL for large files (expiration in seconds) */
@@ -249,16 +164,12 @@ interface SandboxInstance {
249
164
  interface SandboxProvider {
250
165
  /** Provider type identifier */
251
166
  readonly providerType: string;
252
- /** Human-readable provider name for logging */
253
- readonly name?: string;
254
167
  /** Create new sandbox */
255
168
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
256
169
  /** Connect to existing sandbox */
257
170
  connect(sandboxId: string, timeoutMs?: number): Promise<SandboxInstance>;
258
- /** List sandboxes, paginating to exhaustion. `limit` bounds items returned. */
171
+ /** List sandboxes (first page only, up to limit) */
259
172
  list(options?: SandboxListOptions): Promise<SandboxInfo[]>;
260
- /** The same enumeration for fleet bookkeeping: never throws, reports completeness. */
261
- listAll(options?: SandboxListOptions): Promise<SandboxListPage>;
262
173
  }
263
174
  interface E2BConfig {
264
175
  /** E2B API key. Default: reads from E2B_API_KEY env var */
@@ -276,134 +187,17 @@ interface ResolvedE2BConfig {
276
187
  defaultTimeoutMs?: number;
277
188
  templateId?: string;
278
189
  }
279
- declare class E2BCommands implements SandboxCommands {
280
- private sandbox;
281
- private defaultUser?;
282
- constructor(sandbox: Sandbox, defaultUser?: string | undefined);
283
- run(command: string, options?: SandboxRunOptions): Promise<SandboxCommandResult>;
284
- spawn(command: string, options?: SandboxSpawnOptions): Promise<SandboxCommandHandle>;
285
- list(): Promise<ProcessInfo[]>;
286
- connect(processId: string, options?: SandboxConnectOptions): Promise<SandboxCommandHandle>;
287
- sendStdin(processId: string, data: string): Promise<void>;
288
- kill(processId: string): Promise<boolean>;
289
- }
290
- declare class E2BFiles implements SandboxFiles {
291
- private sandbox;
292
- private defaultUser?;
293
- constructor(sandbox: Sandbox, defaultUser?: string | undefined);
294
- read(path: string): Promise<string | Uint8Array>;
295
- write(path: string, content: string | Buffer | ArrayBuffer | Uint8Array): Promise<void>;
296
- writeBatch(files: Array<{
297
- path: string;
298
- data: string | Buffer | ArrayBuffer | Uint8Array;
299
- }>): Promise<void>;
300
- makeDir(path: string): Promise<void>;
301
- uploadUrl(path: string, expiresInSeconds?: number): Promise<string>;
302
- downloadUrl(path: string, expiresInSeconds?: number): Promise<string>;
303
- exists(path: string): Promise<boolean>;
304
- list(path: string): Promise<FileInfo[]>;
305
- remove(path: string): Promise<void>;
306
- rename(oldPath: string, newPath: string): Promise<void>;
307
- readStream(path: string): Promise<ReadableStream<Uint8Array>>;
308
- writeStream(path: string, stream: ReadableStream<Uint8Array>): Promise<void>;
309
- /**
310
- * Upload a local file by PATH, streamed off disk with real backpressure.
311
- *
312
- * Why this does NOT go through files.write(): that method calls
313
- * `new Response(data).blob()` on whatever it is given, which MATERIALIZES the
314
- * body — measured at +463 MB RSS for a 200 MB source, whether the input is a
315
- * stream, a Buffer, or even a file-backed Blob. So handing it a stream looks
316
- * like streaming and is not, which is precisely the trap this method exists to
317
- * avoid: a caller uploading a large artifact once per concurrent task would
318
- * still pay the full size every time.
319
- *
320
- * Instead the multipart body is assembled as a ReadableStream and POSTed to
321
- * the signed upload URL with `duplex: "half"` — the same shape E2B's own
322
- * template-context upload uses. Verified to hold backpressure: against a
323
- * deliberately slow sink the producer had read 7 MB of a 200 MB file after
324
- * four seconds, rather than racing to the end.
325
- *
326
- * The wire format mirrors files.write()'s single-file case exactly: the
327
- * destination is the `path` query parameter of the signed URL, and the body is
328
- * one `file` part. If E2B ever changes that, the POST fails and we fall back to
329
- * the SDK's own (buffering) path — a correct upload beats a cheap one.
330
- */
331
- writeFromPath(sandboxPath: string, localPath: string): Promise<void>;
332
- watchDir(path: string, onEvent: (event: FilesystemEvent) => void | Promise<void>, options?: WatchOptions): Promise<WatchHandle>;
333
- }
334
190
  declare class E2BProvider implements SandboxProvider {
335
191
  readonly providerType: "e2b";
336
- readonly name = "E2B";
337
192
  private readonly apiKey;
338
193
  private readonly apiUrl?;
339
194
  private readonly defaultTimeoutMs;
340
195
  private readonly templateId?;
341
- /**
342
- * Sandbox user configured at create time, reapplied on connect() (e.g., resume).
343
- * In-memory only: a connect() from a fresh process runs as the template default
344
- * user — callers reconnecting across processes must recreate the provider config
345
- * with the same user, or operations on user-owned files fail loudly.
346
- */
347
- private readonly sandboxUsers;
348
196
  constructor(config: ResolvedE2BConfig);
349
197
  create(options: SandboxCreateOptions): Promise<SandboxInstance>;
350
198
  connect(sandboxId: string, timeoutMs?: number): Promise<SandboxInstance>;
351
- /**
352
- * List sandboxes, walking every page.
353
- *
354
- * This used to call `nextItems()` exactly once and return whatever the first
355
- * page held — an account with more than E2B_MAX_PAGE_SIZE sandboxes was
356
- * silently truncated, and nothing in the return value said so. That is a
357
- * correctness bug rather than a performance one for any caller that reads
358
- * absence from the list as "this sandbox is gone".
359
- *
360
- * `limit` still means what a caller expects: stop after this many ITEMS, so
361
- * an explicit limit remains a cost bound. The per-request page size is capped
362
- * separately at E2B_MAX_PAGE_SIZE because E2B rejects anything larger
363
- * outright (`400 validation error: parameter "limit" ... must be at most
364
- * 100`), so a caller asking for 500 gets five requests, not one refusal.
365
- */
366
199
  list(options?: SandboxListOptions): Promise<SandboxInfo[]>;
367
- /**
368
- * The fleet-bookkeeping enumeration: same walk, never throws.
369
- *
370
- * The distinction from `list()` is what a failure MEANS to the caller. An
371
- * orphan sweep treats a missing sandbox as a terminated one, so it must be
372
- * able to tell "the project has no sandboxes" from "the enumeration stopped
373
- * early" — and an exception it catches and turns into an empty array erases
374
- * exactly that difference.
375
- */
376
- listAll(options?: SandboxListOptions): Promise<SandboxListPage>;
377
- private paginate;
378
200
  }
379
- /** The paginator surface this walk needs — E2B's SandboxPaginator satisfies it. */
380
- interface E2BSandboxPaginator {
381
- readonly hasNext: boolean;
382
- readonly nextToken?: string;
383
- nextItems(): Promise<Array<{
384
- sandboxId: string;
385
- templateId: string;
386
- name?: string;
387
- metadata?: Record<string, string>;
388
- startedAt: unknown;
389
- endAt?: unknown;
390
- }>>;
391
- }
392
- /**
393
- * Drain a paginator into one answer, with an honest completeness verdict.
394
- *
395
- * Separate from the provider because everything worth getting wrong lives here
396
- * and none of it needs a network: the two ways a walk can fail to terminate,
397
- * the difference between "the caller asked for ten" and "the provider ran out",
398
- * and the rule that a failure mid-walk yields the sandboxes seen so far marked
399
- * INCOMPLETE rather than either an exception or a short complete list.
400
- *
401
- * Exported for its test (`_testCollectSandboxPages`).
402
- */
403
- declare function collectSandboxPages(paginator: E2BSandboxPaginator, wanted?: number): Promise<SandboxListPage & {
404
- stoppedAtLimit: boolean;
405
- }>;
406
- declare const _testCollectSandboxPages: typeof collectSandboxPages;
407
201
  /**
408
202
  * Create E2B sandbox provider.
409
203
  *
@@ -412,4 +206,4 @@ declare const _testCollectSandboxPages: typeof collectSandboxPages;
412
206
  */
413
207
  declare function createE2BProvider(config?: E2BConfig): SandboxProvider;
414
208
 
415
- export { E2BCommands, type E2BConfig, E2BFiles, E2BIdleTimeoutError, E2BProvider, E2BResourcesError, type E2BSandboxPaginator, E2B_MAX_LIST_PAGES, E2B_MAX_PAGE_SIZE, 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 SandboxListPage, type SandboxProvider, type SandboxRunOptions, type SandboxSpawnOptions, type WatchHandle, type WatchOptions, _testCollectSandboxPages, createE2BProvider };
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 };
package/dist/index.js CHANGED
@@ -1,8 +1,2 @@
1
- import {Sandbox}from'@e2b/code-interpreter';function p(s){if(!s||typeof s!="object")return false;if(s.name==="TimeoutError")return true;let e=s.message;return typeof e=="string"&&/timed?\s*out/i.test(e)}var P=100,v=100;function u(s){return s instanceof Date?s.toISOString():String(s)}function A(s){if(typeof s=="string"||s instanceof ArrayBuffer)return s;if(s instanceof Buffer)return new Uint8Array(s).buffer;if(s instanceof Uint8Array)return new Uint8Array(s).buffer;throw new Error(`Unsupported data type for file upload: ${typeof s}. Expected string, Buffer, ArrayBuffer, or Uint8Array.`)}var b=class extends Error{constructor(e){super(e),this.name="E2BResourcesError";}},g=class extends Error{constructor(){super("E2B has no idle timeout: its sandbox timeout is an ABSOLUTE lifetime that in-sandbox activity never extends. Use `timeoutMs` for the lifetime, and call setTimeout() to extend a sandbox you know is still working."),this.name="E2BIdleTimeoutError";}},x=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async run(e,t){try{let r=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:r.exitCode,stdout:r.stdout,stderr:r.stderr}}catch(r){if(r&&typeof r=="object"&&"exitCode"in r){let n=r;return {exitCode:n.exitCode,stdout:n.stdout??"",stderr:n.stderr??""}}if(p(r))return {exitCode:124,stdout:"",stderr:r instanceof Error?r.message:"command timed out"};throw r}}async spawn(e,t){let r=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(r.pid),wait:async()=>{try{let n=await r.wait();return {exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch(n){if(n&&typeof n=="object"&&"exitCode"in n){let i=n;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(p(n))return {exitCode:124,stdout:"",stderr:n instanceof Error?n.message:"command timed out"};throw n}},kill:()=>this.sandbox.commands.kill(r.pid)}}async list(){return (await this.sandbox.commands.list()).map(t=>({...t,processId:String(t.pid)}))}async connect(e,t){let r=await this.sandbox.commands.connect(Number(e),{onStdout:t?.onStdout,onStderr:t?.onStderr,timeoutMs:t?.timeoutMs});return {processId:String(r.pid),wait:async()=>{try{let n=await r.wait();return {exitCode:n.exitCode,stdout:n.stdout,stderr:n.stderr}}catch(n){if(n&&typeof n=="object"&&"exitCode"in n){let i=n;return {exitCode:i.exitCode,stdout:i.stdout??"",stderr:i.stderr??""}}if(p(n))return {exitCode:124,stdout:"",stderr:n instanceof Error?n.message:"command timed out"};throw n}},kill:()=>this.sandbox.commands.kill(r.pid)}}async sendStdin(e,t){await this.sandbox.commands.sendStdin(Number(e),t);}async kill(e){return this.sandbox.commands.kill(Number(e))}},h=class{constructor(e,t){this.sandbox=e;this.defaultUser=t;}async read(e){let t=await this.sandbox.files.read(e,{format:"bytes",requestTimeoutMs:3e5,user:this.defaultUser});if(!t.includes(0))try{return new TextDecoder("utf-8",{fatal:!0,ignoreBOM:!0}).decode(t)}catch{}return t}async write(e,t){await this.sandbox.files.write(e,A(t),{requestTimeoutMs:3e5,user:this.defaultUser});}async writeBatch(e){let t=e.map(r=>({path:r.path,data:A(r.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(r=>({name:r.name,path:r.path,type:r.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:r,statSync:n}=await import('fs'),{Readable:i}=await import('stream'),{randomBytes:o}=await import('crypto'),a=n(t).size,c=`----evolve${o(16).toString("hex")}`,w=Buffer.from(`--${c}\r
2
- Content-Disposition: form-data; name="file"; filename="blob"\r
3
- Content-Type: application/octet-stream\r
4
- \r
5
- `),S=Buffer.from(`\r
6
- --${c}--\r
7
- `);async function*I(){yield w;for await(let d of r(t))yield d;yield S;}try{let d=await this.uploadUrl(e),m=await fetch(d,{method:"POST",body:i.toWeb(i.from(I())),headers:{"Content-Type":`multipart/form-data; boundary=${c}`,"Content-Length":String(w.length+a+S.length)},duplex:"half"});if(!m.ok)throw new Error(`streamed upload to ${e} failed (HTTP ${m.status})`)}catch(d){console.warn(`[e2b] streamed upload of ${t} failed, falling back to a buffered write:`,d instanceof Error?d.message:d);let m=i.toWeb(r(t));await this.writeStream(e,m);}}async watchDir(e,t,r){let n=await this.sandbox.files.watchDir(e,t,{recursive:r?.recursive,timeoutMs:r?.timeoutMs,user:this.defaultUser,onExit:r?.onExit});return {stop:()=>n.stop()}}},l=class{constructor(e,t,r,n){this.sandbox=e;this.apiKey=t;this.apiUrl=r;this.commands=new x(e,n),this.files=new h(e,n);}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:u(e.startedAt),endAt:e.endAt?u(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});}},y=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.idleTimeoutMs!==void 0)throw new g;if(e.resources&&(e.resources.cpu!==void 0||e.resources.memory!==void 0||e.resources.disk!==void 0))throw new b("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,r=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 n=e.network?.allowedDestinations??[],i=e.network?.outbound==="blocked"&&n.length>0,o=await Sandbox.create(r,{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:n}:void 0});return e.workingDirectory&&await o.files.makeDir(e.workingDirectory,{user:e.user}),e.user&&this.sandboxUsers.set(o.sandboxId,e.user),new l(o,this.apiKey,this.apiUrl,e.user)}async connect(e,t){let r=await Sandbox.connect(e,{apiKey:this.apiKey,apiUrl:this.apiUrl,timeoutMs:t??this.defaultTimeoutMs});return new l(r,this.apiKey,this.apiUrl,this.sandboxUsers.get(e))}async list(e){let t=await this.paginate(e);if(t.error&&!t.stoppedAtLimit)throw new Error(t.error);return t.sandboxes}async listAll(e){let{stoppedAtLimit:t,...r}=await this.paginate(e);return r}async paginate(e){let t=e?.limit;return U(Sandbox.list({apiKey:this.apiKey,apiUrl:this.apiUrl,query:{state:e?.state,metadata:e?.metadata},limit:t===void 0?P:Math.min(t,P)}),t)}};async function U(s,e){let t=[],r=0,n=new Set;for(;s.hasNext;){if(r>=v)return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list exceeded ${v} pages`};let i=s.nextToken;if(i!==void 0){if(n.has(i))return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:false,error:"pagination token repeated"};n.add(i);}let o;try{o=await s.nextItems();}catch(a){return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:false,error:`sandbox list failed: ${a instanceof Error?a.message:String(a)}`}}r+=1;for(let a of o){if(e!==void 0&&t.length>=e)return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${e} with more sandboxes available`};t.push({sandboxId:a.sandboxId,image:a.templateId,name:a.name,metadata:a.metadata??{},startedAt:u(a.startedAt),endAt:a.endAt?u(a.endAt):void 0});}if(e!==void 0&&t.length>=e&&s.hasNext)return {sandboxes:t,complete:false,pagesFetched:r,stoppedAtLimit:true,error:`stopped at the requested limit of ${e} with more sandboxes available`};if(e!==void 0&&t.length>=e)break}return {sandboxes:t,complete:true,pagesFetched:r,stoppedAtLimit:false}}var E=U;function C(s={}){let e=s.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 y({...s,apiKey:e})}
8
- export{x as E2BCommands,h as E2BFiles,g as E2BIdleTimeoutError,y as E2BProvider,b as E2BResourcesError,v as E2B_MAX_LIST_PAGES,P as E2B_MAX_PAGE_SIZE,E as _testCollectSandboxPages,C as createE2BProvider};
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};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evolvingmachines/e2b",
3
- "version": "0.0.52-sable-rename.20260803.6ab54d4",
3
+ "version": "0.0.53",
4
4
  "keywords": [
5
5
  "ai",
6
6
  "agents",
@@ -32,8 +32,7 @@
32
32
  "scripts": {
33
33
  "build": "tsup --minify",
34
34
  "dev": "tsup --watch",
35
- "type-check": "tsc --noEmit",
36
- "test:unit": "tsx tests/unit/e2b-list-pagination.test.ts && tsx tests/unit/e2b-files-read.test.ts"
35
+ "type-check": "tsc --noEmit"
37
36
  },
38
37
  "dependencies": {
39
38
  "@e2b/code-interpreter": "^2.0.1"