e2b
Version:
E2B SDK that give agents cloud environments
2,069 lines • 72.6 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __await = function(promise, isYieldStar) {
this[0] = promise;
this[1] = isYieldStar;
};
var __asyncGenerator = (__this, __arguments, generator) => {
var resume = (k, v, yes, no) => {
try {
var x = generator[k](v), isAwait = (v = x.value) instanceof __await, done = x.done;
Promise.resolve(isAwait ? v[0] : v).then((y) => isAwait ? resume(k === "return" ? k : "next", v[1] ? { done: y.done, value: y.value } : y, yes, no) : yes({ value: y, done })).catch((e) => resume("throw", e, yes, no));
} catch (e) {
no(e);
}
}, method = (k) => it[k] = (x) => new Promise((yes, no) => resume(k, x, yes, no)), it = {};
return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
};
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
// src/index.ts
var src_exports = {};
__export(src_exports, {
ApiClient: () => ApiClient,
AuthenticationError: () => AuthenticationError,
CommandExitError: () => CommandExitError,
ConnectionConfig: () => ConnectionConfig,
FileType: () => FileType2,
FilesystemEventType: () => FilesystemEventType,
InvalidArgumentError: () => InvalidArgumentError,
NotEnoughSpaceError: () => NotEnoughSpaceError,
NotFoundError: () => NotFoundError,
Sandbox: () => Sandbox,
SandboxError: () => SandboxError,
TemplateError: () => TemplateError,
TimeoutError: () => TimeoutError,
default: () => src_default,
getSignature: () => getSignature
});
module.exports = __toCommonJS(src_exports);
// src/api/index.ts
var import_openapi_fetch = __toESM(require("openapi-fetch"));
// src/api/metadata.ts
var import_platform = __toESM(require("platform"));
// package.json
var version = "1.13.0";
// src/api/metadata.ts
function getRuntime() {
var _a2, _b, _c;
if (globalThis.Bun) {
return { runtime: "bun", version: globalThis.Bun.version };
}
if (globalThis.Deno) {
return { runtime: "deno", version: globalThis.Deno.version.deno };
}
if (((_b = (_a2 = globalThis.process) == null ? void 0 : _a2.release) == null ? void 0 : _b.name) === "node") {
return { runtime: "node", version: import_platform.default.version || "unknown" };
}
if (typeof EdgeRuntime === "string") {
return { runtime: "vercel-edge", version: "unknown" };
}
if (((_c = globalThis.navigator) == null ? void 0 : _c.userAgent) === "Cloudflare-Workers") {
return { runtime: "cloudflare-worker", version: "unknown" };
}
if (typeof window !== "undefined") {
return { runtime: "browser", version: import_platform.default.version || "unknown" };
}
return { runtime: "unknown", version: "unknown" };
}
var { runtime, version: runtimeVersion } = getRuntime();
var _a;
var defaultHeaders = {
browser: typeof window !== "undefined" && import_platform.default.name || "unknown",
lang: "js",
lang_version: runtimeVersion,
package_version: version,
publisher: "e2b",
sdk_runtime: runtime,
system: ((_a = import_platform.default.os) == null ? void 0 : _a.family) || "unknown"
};
function getEnvVar(name) {
if (runtime === "deno") {
return Deno.env.get(name);
}
if (typeof process === "undefined") {
return "";
}
return process.env[name];
}
// src/errors.ts
function formatSandboxTimeoutError(message) {
return new TimeoutError(
`${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.`
);
}
var SandboxError = class extends Error {
constructor(message) {
super(message);
this.name = "SandboxError";
}
};
var TimeoutError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "TimeoutError";
}
};
var InvalidArgumentError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "InvalidArgumentError";
}
};
var NotEnoughSpaceError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "NotEnoughSpaceError";
}
};
var NotFoundError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "NotFoundError";
}
};
var AuthenticationError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "AuthenticationError";
}
};
var TemplateError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "TemplateError";
}
};
var RateLimitError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "RateLimitError";
}
};
// src/logs.ts
function formatLog(log) {
return JSON.parse(JSON.stringify(log));
}
function createRpcLogger(logger) {
function logEach(stream) {
return __asyncGenerator(this, null, function* () {
var _a2;
try {
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
const m = temp.value;
(_a2 = logger.debug) == null ? void 0 : _a2.call(logger, "Response stream:", formatLog(m));
yield m;
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
} finally {
if (error)
throw error[0];
}
}
});
}
return (next) => async (req) => {
var _a2, _b;
(_a2 = logger.info) == null ? void 0 : _a2.call(logger, `Request: POST ${req.url}`);
const res = await next(req);
if (res.stream) {
return __spreadProps(__spreadValues({}, res), {
message: logEach(res.message)
});
} else {
(_b = logger.info) == null ? void 0 : _b.call(logger, "Response:", formatLog(res.message));
}
return res;
};
}
function createApiLogger(logger) {
return {
async onRequest(req) {
var _a2;
(_a2 = logger.info) == null ? void 0 : _a2.call(logger, `Request ${req.method} ${req.url}`);
return req;
},
async onResponse(res) {
var _a2, _b;
if (res.status >= 400) {
(_a2 = logger.error) == null ? void 0 : _a2.call(logger, "Response:", res.status, res.statusText);
} else {
(_b = logger.info) == null ? void 0 : _b.call(logger, "Response:", res.status, res.statusText);
}
return res;
}
};
}
// src/api/index.ts
function handleApiError(response) {
var _a2, _b;
if (!response.error) {
return;
}
if (response.response.status === 429) {
return new RateLimitError("Rate limit exceeded, please try again later.");
}
const message = (_b = (_a2 = response.error) == null ? void 0 : _a2.message) != null ? _b : response.error;
return new SandboxError(`${response.response.status}: ${message}`);
}
var ApiClient = class {
constructor(config, opts = { requireAccessToken: false, requireApiKey: true }) {
if (!(opts == null ? void 0 : opts.requireApiKey) && !config.apiKey) {
throw new AuthenticationError(
"API key is required, please visit the Team tab at https://e2b.dev/dashboard to get your API key. You can either set the environment variable `E2B_API_KEY` or you can pass it directly to the sandbox like Sandbox.create({ apiKey: 'e2b_...' })"
);
}
if ((opts == null ? void 0 : opts.requireAccessToken) && !config.accessToken) {
throw new AuthenticationError(
"Access token is required, please visit the Personal tab at https://e2b.dev/dashboard to get your access token. You can set the environment variable `E2B_ACCESS_TOKEN` or pass the `accessToken` in options."
);
}
this.api = (0, import_openapi_fetch.default)({
baseUrl: config.apiUrl,
// keepalive: true, // TODO: Return keepalive
headers: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, defaultHeaders), config.apiKey && { "X-API-KEY": config.apiKey }), config.accessToken && {
Authorization: `Bearer ${config.accessToken}`
}), config.headers)
});
if (config.logger) {
this.api.use(createApiLogger(config.logger));
}
}
};
// src/connectionConfig.ts
var REQUEST_TIMEOUT_MS = 3e4;
var KEEPALIVE_PING_INTERVAL_SEC = 50;
var KEEPALIVE_PING_HEADER = "Keepalive-Ping-Interval";
var ConnectionConfig = class _ConnectionConfig {
constructor(opts) {
var _a2;
this.apiKey = (opts == null ? void 0 : opts.apiKey) || _ConnectionConfig.apiKey;
this.debug = (opts == null ? void 0 : opts.debug) || _ConnectionConfig.debug;
this.domain = (opts == null ? void 0 : opts.domain) || _ConnectionConfig.domain;
this.accessToken = (opts == null ? void 0 : opts.accessToken) || _ConnectionConfig.accessToken;
this.requestTimeoutMs = (_a2 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a2 : REQUEST_TIMEOUT_MS;
this.logger = opts == null ? void 0 : opts.logger;
this.headers = (opts == null ? void 0 : opts.headers) || {};
this.headers["User-Agent"] = `e2b-js-sdk/${version}`;
this.apiUrl = this.debug ? "http://localhost:3000" : `https://api.${this.domain}`;
}
static get domain() {
return getEnvVar("E2B_DOMAIN") || "e2b.app";
}
static get debug() {
return (getEnvVar("E2B_DEBUG") || "false").toLowerCase() === "true";
}
static get apiKey() {
return getEnvVar("E2B_API_KEY");
}
static get accessToken() {
return getEnvVar("E2B_ACCESS_TOKEN");
}
getSignal(requestTimeoutMs) {
const timeout = requestTimeoutMs != null ? requestTimeoutMs : this.requestTimeoutMs;
return timeout ? AbortSignal.timeout(timeout) : void 0;
}
};
var defaultUsername = "user";
// src/utils.ts
async function sha256(data) {
if (typeof crypto !== "undefined") {
const encoder = new TextEncoder();
const dataBuffer = encoder.encode(data);
const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
const hashArray = new Uint8Array(hashBuffer);
return btoa(String.fromCharCode(...hashArray));
}
const { createHash } = require("crypto");
const hash = createHash("sha256").update(data, "utf8").digest();
return hash.toString("base64");
}
// src/sandbox/signature.ts
async function getSignature({
path,
operation,
user,
expirationInSeconds,
envdAccessToken
}) {
if (!envdAccessToken) {
throw new Error(
"Access token is not set and signature cannot be generated!"
);
}
const signatureExpiration = expirationInSeconds ? Math.floor(Date.now() / 1e3) + expirationInSeconds : null;
let signatureRaw;
if (signatureExpiration === null) {
signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}`;
} else {
signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}:${signatureExpiration.toString()}`;
}
const hashBase64 = await sha256(signatureRaw);
const signature = "v1_" + hashBase64.replace(/=+$/, "");
return {
signature,
expiration: signatureExpiration
};
}
// src/sandbox/filesystem/index.ts
var import_connect3 = require("@connectrpc/connect");
// src/envd/api.ts
var import_openapi_fetch2 = __toESM(require("openapi-fetch"));
var import_connect = require("@connectrpc/connect");
async function handleEnvdApiError(res) {
var _a2;
if (!res.error) {
return;
}
const message = typeof res.error == "string" ? res.error : ((_a2 = res.error) == null ? void 0 : _a2.message) || await res.response.text();
switch (res.response.status) {
case 400:
return new InvalidArgumentError(message);
case 401:
return new AuthenticationError(message);
case 404:
return new NotFoundError(message);
case 429:
return new SandboxError(
`${res.response.status}: ${message}: The requests are being rate limited.`
);
case 502:
return formatSandboxTimeoutError(message);
case 507:
return new NotEnoughSpaceError(message);
default:
return new SandboxError(`${res.response.status}: ${message}`);
}
}
async function handleProcessStartEvent(events) {
var _a2;
let startEvent;
try {
startEvent = (await events[Symbol.asyncIterator]().next()).value;
} catch (err) {
if (err instanceof import_connect.ConnectError) {
if (err.code === import_connect.Code.Unavailable) {
throw new NotFoundError("Sandbox is probably not running anymore");
}
}
throw err;
}
if (((_a2 = startEvent.event) == null ? void 0 : _a2.event.case) !== "start") {
throw new Error("Expected start event");
}
return startEvent.event.event.value.pid;
}
async function handleWatchDirStartEvent(events) {
var _a2;
let startEvent;
try {
startEvent = (await events[Symbol.asyncIterator]().next()).value;
} catch (err) {
if (err instanceof import_connect.ConnectError) {
if (err.code === import_connect.Code.Unavailable) {
throw new NotFoundError("Sandbox is probably not running anymore");
}
}
throw err;
}
if (((_a2 = startEvent.event) == null ? void 0 : _a2.case) !== "start") {
throw new Error("Expected start event");
}
return startEvent.event.value;
}
var EnvdApiClient = class {
constructor(config, metadata) {
this.api = (0, import_openapi_fetch2.default)({
baseUrl: config.apiUrl,
fetch: config == null ? void 0 : config.fetch,
headers: config == null ? void 0 : config.headers
// keepalive: true, // TODO: Return keepalive
});
this.version = metadata.version;
if (config.logger) {
this.api.use(createApiLogger(config.logger));
}
}
};
// src/envd/rpc.ts
var import_connect2 = require("@connectrpc/connect");
function handleRpcError(err) {
if (err instanceof import_connect2.ConnectError) {
switch (err.code) {
case import_connect2.Code.InvalidArgument:
return new InvalidArgumentError(err.message);
case import_connect2.Code.Unauthenticated:
return new AuthenticationError(err.message);
case import_connect2.Code.NotFound:
return new NotFoundError(err.message);
case import_connect2.Code.Unavailable:
return formatSandboxTimeoutError(err.message);
case import_connect2.Code.Canceled:
return new TimeoutError(
`${err.message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.`
);
case import_connect2.Code.DeadlineExceeded:
return new TimeoutError(
`${err.message}: This error is likely due to exceeding 'timeoutMs' \u2014 the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.`
);
default:
return new SandboxError(`${err.code}: ${err.message}`);
}
}
return err;
}
function encode64(value) {
switch (runtime) {
case "deno":
return btoa(value);
case "node":
return Buffer.from(value).toString("base64");
case "bun":
return Buffer.from(value).toString("base64");
default:
return btoa(value);
}
}
function authenticationHeader(username) {
const value = `${username || defaultUsername}:`;
const encoded = encode64(value);
return { "Authorization": `Basic ${encoded}` };
}
// src/envd/filesystem/filesystem_pb.ts
var import_codegenv2 = require("@bufbuild/protobuf/codegenv2");
var import_wkt = require("@bufbuild/protobuf/wkt");
var file_filesystem_filesystem = /* @__PURE__ */ (0, import_codegenv2.fileDesc)("ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i/QEKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQFCEQoPX3N5bWxpbmtfdGFyZ2V0Ii0KDkxpc3REaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSDQoFZGVwdGgYAiABKA0iOQoPTGlzdERpclJlc3BvbnNlEiYKB2VudHJpZXMYASADKAsyFS5maWxlc3lzdGVtLkVudHJ5SW5mbyIyCg9XYXRjaERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiRAoPRmlsZXN5c3RlbUV2ZW50EgwKBG5hbWUYASABKAkSIwoEdHlwZRgCIAEoDjIVLmZpbGVzeXN0ZW0uRXZlbnRUeXBlIuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiNwoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiKwoVQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEhIKCndhdGNoZXJfaWQYASABKAkiLQoXR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSJHChhHZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USKwoGZXZlbnRzGAEgAygLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnQiKgoUUmVtb3ZlV2F0Y2hlclJlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSIXChVSZW1vdmVXYXRjaGVyUmVzcG9uc2UqUgoIRmlsZVR5cGUSGQoVRklMRV9UWVBFX1VOU1BFQ0lGSUVEEAASEgoORklMRV9UWVBFX0ZJTEUQARIXChNGSUxFX1RZUEVfRElSRUNUT1JZEAIqmAEKCUV2ZW50VHlwZRIaChZFVkVOVF9UWVBFX1VOU1BFQ0lGSUVEEAASFQoRRVZFTlRfVFlQRV9DUkVBVEUQARIUChBFVkVOVF9UWVBFX1dSSVRFEAISFQoRRVZFTlRfVFlQRV9SRU1PVkUQAxIVChFFVkVOVF9UWVBFX1JFTkFNRRAEEhQKEEVWRU5UX1RZUEVfQ0hNT0QQBTKfBQoKRmlsZXN5c3RlbRI5CgRTdGF0EhcuZmlsZXN5c3RlbS5TdGF0UmVxdWVzdBoYLmZpbGVzeXN0ZW0uU3RhdFJlc3BvbnNlEkIKB01ha2VEaXISGi5maWxlc3lzdGVtLk1ha2VEaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5NYWtlRGlyUmVzcG9uc2USOQoETW92ZRIXLmZpbGVzeXN0ZW0uTW92ZVJlcXVlc3QaGC5maWxlc3lzdGVtLk1vdmVSZXNwb25zZRJCCgdMaXN0RGlyEhouZmlsZXN5c3RlbS5MaXN0RGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTGlzdERpclJlc3BvbnNlEj8KBlJlbW92ZRIZLmZpbGVzeXN0ZW0uUmVtb3ZlUmVxdWVzdBoaLmZpbGVzeXN0ZW0uUmVtb3ZlUmVzcG9uc2USRwoIV2F0Y2hEaXISGy5maWxlc3lzdGVtLldhdGNoRGlyUmVxdWVzdBocLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZTABElQKDUNyZWF0ZVdhdGNoZXISIC5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVzcG9uc2USXQoQR2V0V2F0Y2hlckV2ZW50cxIjLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QaJC5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXNwb25zZRJUCg1SZW1vdmVXYXRjaGVyEiAuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlc3BvbnNlQmkKDmNvbS5maWxlc3lzdGVtQg9GaWxlc3lzdGVtUHJvdG9QAaICA0ZYWKoCCkZpbGVzeXN0ZW3KAgpGaWxlc3lzdGVt4gIWRmlsZXN5c3RlbVxHUEJNZXRhZGF0YeoCCkZpbGVzeXN0ZW1iBnByb3RvMw", [import_wkt.file_google_protobuf_timestamp]);
var Filesystem = /* @__PURE__ */ (0, import_codegenv2.serviceDesc)(file_filesystem_filesystem, 0);
// src/sandbox/filesystem/watchHandle.ts
var FilesystemEventType = /* @__PURE__ */ ((FilesystemEventType2) => {
FilesystemEventType2["CHMOD"] = "chmod";
FilesystemEventType2["CREATE"] = "create";
FilesystemEventType2["REMOVE"] = "remove";
FilesystemEventType2["RENAME"] = "rename";
FilesystemEventType2["WRITE"] = "write";
return FilesystemEventType2;
})(FilesystemEventType || {});
function mapEventType(type) {
switch (type) {
case 5 /* CHMOD */:
return "chmod" /* CHMOD */;
case 1 /* CREATE */:
return "create" /* CREATE */;
case 3 /* REMOVE */:
return "remove" /* REMOVE */;
case 4 /* RENAME */:
return "rename" /* RENAME */;
case 2 /* WRITE */:
return "write" /* WRITE */;
}
}
var WatchHandle = class {
constructor(handleStop, events, onEvent, onExit) {
this.handleStop = handleStop;
this.events = events;
this.onEvent = onEvent;
this.onExit = onExit;
this.handleEvents();
}
/**
* Stop watching the directory.
*/
async stop() {
this.handleStop();
}
iterateEvents() {
return __asyncGenerator(this, null, function* () {
try {
try {
for (var iter = __forAwait(this.events), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
const event = temp.value;
switch (event.event.case) {
case "filesystem":
yield event.event;
break;
}
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
} finally {
if (error)
throw error[0];
}
}
} catch (err) {
throw handleRpcError(err);
}
});
}
async handleEvents() {
var _a2, _b, _c;
try {
try {
for (var iter = __forAwait(this.iterateEvents()), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
const event = temp.value;
const eventType = mapEventType(event.value.type);
if (eventType === void 0) {
continue;
}
(_a2 = this.onEvent) == null ? void 0 : _a2.call(this, {
name: event.value.name,
type: eventType
});
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && await temp.call(iter);
} finally {
if (error)
throw error[0];
}
}
(_b = this.onExit) == null ? void 0 : _b.call(this);
} catch (err) {
(_c = this.onExit) == null ? void 0 : _c.call(this, err);
}
}
};
// src/sandbox/filesystem/index.ts
var import_compare_versions = require("compare-versions");
// src/envd/versions.ts
var ENVD_VERSION_RECURSIVE_WATCH = "0.1.4";
// src/sandbox/filesystem/index.ts
var FileType2 = /* @__PURE__ */ ((FileType3) => {
FileType3["FILE"] = "file";
FileType3["DIR"] = "dir";
return FileType3;
})(FileType2 || {});
function mapFileType(fileType) {
switch (fileType) {
case 2 /* DIRECTORY */:
return "dir" /* DIR */;
case 1 /* FILE */:
return "file" /* FILE */;
}
}
function mapModifiedTime(modifiedTime) {
if (!modifiedTime) return void 0;
return new Date(
Number(modifiedTime.seconds) * 1e3 + Math.floor(modifiedTime.nanos / 1e6)
);
}
var Filesystem2 = class {
constructor(transport, envdApi, connectionConfig) {
this.envdApi = envdApi;
this.connectionConfig = connectionConfig;
this.defaultWatchTimeout = 6e4;
// 60 seconds
this.defaultWatchRecursive = false;
this.rpc = (0, import_connect3.createClient)(Filesystem, transport);
}
async read(path, opts) {
var _a2;
const format = (_a2 = opts == null ? void 0 : opts.format) != null ? _a2 : "text";
const res = await this.envdApi.api.GET("/files", {
params: {
query: {
path,
username: (opts == null ? void 0 : opts.user) || defaultUsername
}
},
parseAs: format === "bytes" ? "arrayBuffer" : format,
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
const err = await handleEnvdApiError(res);
if (err) {
throw err;
}
if (format === "bytes") {
return new Uint8Array(res.data);
}
if (res.response.headers.get("content-length") === "0") {
return "";
}
return res.data;
}
async write(pathOrFiles, dataOrOpts, opts) {
if (typeof pathOrFiles !== "string" && !Array.isArray(pathOrFiles)) {
throw new Error("Path or files are required");
}
if (typeof pathOrFiles === "string" && Array.isArray(dataOrOpts)) {
throw new Error(
"Cannot specify both path and array of files. You have to specify either path and data for a single file or an array for multiple files."
);
}
const { path, writeOpts, writeFiles } = typeof pathOrFiles === "string" ? {
path: pathOrFiles,
writeOpts: opts,
writeFiles: [
{
data: dataOrOpts
}
]
} : {
path: void 0,
writeOpts: dataOrOpts,
writeFiles: pathOrFiles
};
if (writeFiles.length === 0) return [];
const blobs = await Promise.all(
writeFiles.map((f) => new Response(f.data).blob())
);
const res = await this.envdApi.api.POST("/files", {
params: {
query: {
path,
username: (writeOpts == null ? void 0 : writeOpts.user) || defaultUsername
}
},
bodySerializer() {
return blobs.reduce((fd, blob, i) => {
fd.append("file", blob, writeFiles[i].path);
return fd;
}, new FormData());
},
body: {},
headers: {
"Content-Type": "multipart/form-data",
"Bun-Content-Type": "temporary-fix"
// https://github.com/oven-sh/bun/issues/14988
}
});
const err = await handleEnvdApiError(res);
if (err) {
throw err;
}
const files = res.data;
if (!files) {
throw new Error("Expected to receive information about written file");
}
return files.length === 1 && path ? files[0] : files;
}
/**
* List entries in a directory.
*
* @param path path to the directory.
* @param opts connection options.
*
* @returns list of entries in the sandbox filesystem directory.
*/
async list(path, opts) {
var _a2;
if (typeof (opts == null ? void 0 : opts.depth) === "number" && opts.depth < 1) {
throw new InvalidArgumentError("depth should be at least one");
}
try {
const res = await this.rpc.listDir(
{
path,
depth: (_a2 = opts == null ? void 0 : opts.depth) != null ? _a2 : 1
},
{
headers: authenticationHeader(opts == null ? void 0 : opts.user),
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
const entries = [];
for (const e of res.entries) {
const type = mapFileType(e.type);
if (type) {
entries.push({
name: e.name,
type,
path: e.path,
size: Number(e.size),
mode: e.mode,
permissions: e.permissions,
owner: e.owner,
group: e.group,
modifiedTime: mapModifiedTime(e.modifiedTime),
symlinkTarget: e.symlinkTarget
});
}
}
return entries;
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Create a new directory and all directories along the way if needed on the specified path.
*
* @param path path to a new directory. For example '/dirA/dirB' when creating 'dirB'.
* @param opts connection options.
*
* @returns `true` if the directory was created, `false` if it already exists.
*/
async makeDir(path, opts) {
try {
await this.rpc.makeDir(
{ path },
{
headers: authenticationHeader(opts == null ? void 0 : opts.user),
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
return true;
} catch (err) {
if (err instanceof import_connect3.ConnectError) {
if (err.code === import_connect3.Code.AlreadyExists) {
return false;
}
}
throw handleRpcError(err);
}
}
/**
* Rename a file or directory.
*
* @param oldPath path to the file or directory to rename.
* @param newPath new path for the file or directory.
* @param opts connection options.
*
* @returns information about renamed file or directory.
*/
async rename(oldPath, newPath, opts) {
try {
const res = await this.rpc.move(
{
source: oldPath,
destination: newPath
},
{
headers: authenticationHeader(opts == null ? void 0 : opts.user),
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
const entry = res.entry;
if (!entry) {
throw new Error("Expected to receive information about moved object");
}
return {
name: entry.name,
type: mapFileType(entry.type),
path: entry.path,
size: Number(entry.size),
mode: entry.mode,
permissions: entry.permissions,
owner: entry.owner,
group: entry.group,
modifiedTime: mapModifiedTime(entry.modifiedTime),
symlinkTarget: entry.symlinkTarget
};
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Remove a file or directory.
*
* @param path path to a file or directory.
* @param opts connection options.
*/
async remove(path, opts) {
try {
await this.rpc.remove(
{ path },
{
headers: authenticationHeader(opts == null ? void 0 : opts.user),
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Check if a file or a directory exists.
*
* @param path path to a file or a directory
* @param opts connection options.
*
* @returns `true` if the file or directory exists, `false` otherwise
*/
async exists(path, opts) {
try {
await this.rpc.stat(
{ path },
{
headers: authenticationHeader(opts == null ? void 0 : opts.user),
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
return true;
} catch (err) {
if (err instanceof import_connect3.ConnectError) {
if (err.code === import_connect3.Code.NotFound) {
return false;
}
}
throw handleRpcError(err);
}
}
/**
* Get information about a file or directory.
*
* @param path path to a file or directory.
* @param opts connection options.
*
* @returns information about the file or directory like name, type, and path.
*/
async getInfo(path, opts) {
try {
const res = await this.rpc.stat(
{ path },
{ headers: authenticationHeader(opts == null ? void 0 : opts.user) }
);
if (!res.entry) {
throw new Error(
"Expected to receive information about the file or directory"
);
}
return {
name: res.entry.name,
type: mapFileType(res.entry.type),
path: res.entry.path,
size: Number(res.entry.size),
mode: res.entry.mode,
permissions: res.entry.permissions,
owner: res.entry.owner,
group: res.entry.group,
modifiedTime: mapModifiedTime(res.entry.modifiedTime),
symlinkTarget: res.entry.symlinkTarget
};
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Start watching a directory for filesystem events.
*
* @param path path to directory to watch.
* @param onEvent callback to call when an event in the directory occurs.
* @param opts connection options.
*
* @returns `WatchHandle` object for stopping watching directory.
*/
async watchDir(path, onEvent, opts) {
var _a2, _b, _c;
if ((opts == null ? void 0 : opts.recursive) && this.envdApi.version && (0, import_compare_versions.compareVersions)(this.envdApi.version, ENVD_VERSION_RECURSIVE_WATCH) < 0) {
throw new TemplateError(
"You need to update the template to use recursive watching. You can do this by running `e2b template build` in the directory with the template."
);
}
const requestTimeoutMs = (_a2 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a2 : this.connectionConfig.requestTimeoutMs;
const controller = new AbortController();
const reqTimeout = requestTimeoutMs ? setTimeout(() => {
controller.abort();
}, requestTimeoutMs) : void 0;
const events = this.rpc.watchDir(
{
path,
recursive: (_b = opts == null ? void 0 : opts.recursive) != null ? _b : this.defaultWatchRecursive
},
{
headers: __spreadProps(__spreadValues({}, authenticationHeader(opts == null ? void 0 : opts.user)), {
[KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
}),
signal: controller.signal,
timeoutMs: (_c = opts == null ? void 0 : opts.timeoutMs) != null ? _c : this.defaultWatchTimeout
}
);
try {
await handleWatchDirStartEvent(events);
clearTimeout(reqTimeout);
return new WatchHandle(
() => controller.abort(),
events,
onEvent,
opts == null ? void 0 : opts.onExit
);
} catch (err) {
throw handleRpcError(err);
}
}
};
// src/sandbox/commands/commandHandle.ts
var CommandExitError = class extends SandboxError {
constructor(result) {
super(result.error);
this.result = result;
this.name = "CommandExitError";
}
/**
* Command execution exit code.
* `0` if the command finished successfully.
*/
get exitCode() {
return this.result.exitCode;
}
/**
* Error message from command execution.
*/
get error() {
return this.result.error;
}
/**
* Command execution stdout output.
*/
get stdout() {
return this.result.stdout;
}
/**
* Command execution stderr output.
*/
get stderr() {
return this.result.stderr;
}
};
var CommandHandle = class {
/**
* @hidden
* @internal
* @access protected
*/
constructor(pid, handleDisconnect, handleKill, events, onStdout, onStderr, onPty) {
this.pid = pid;
this.handleDisconnect = handleDisconnect;
this.handleKill = handleKill;
this.events = events;
this.onStdout = onStdout;
this.onStderr = onStderr;
this.onPty = onPty;
this._stdout = "";
this._stderr = "";
this._wait = this.handleEvents();
}
/**
* Command execution exit code.
* `0` if the command finished successfully.
*
* It is `undefined` if the command is still running.
*/
get exitCode() {
var _a2;
return (_a2 = this.result) == null ? void 0 : _a2.exitCode;
}
/**
* Error message from command execution.
*/
get error() {
var _a2;
return (_a2 = this.result) == null ? void 0 : _a2.error;
}
/**
* Command execution stderr output.
*/
get stderr() {
return this._stderr;
}
/**
* Command execution stdout output.
*/
get stdout() {
return this._stdout;
}
/**
* Wait for the command to finish and return the result.
* If the command exits with a non-zero exit code, it throws a `CommandExitError`.
*
* @returns `CommandResult` result of command execution.
*/
async wait() {
await this._wait;
if (this.iterationError) {
throw this.iterationError;
}
if (!this.result) {
throw new SandboxError("Process exited without a result");
}
if (this.result.exitCode !== 0) {
throw new CommandExitError(this.result);
}
return this.result;
}
/**
* Disconnect from the command.
*
* The command is not killed, but SDK stops receiving events from the command.
* You can reconnect to the command using {@link Commands.connect}.
*/
async disconnect() {
this.handleDisconnect();
}
/**
* Kill the command.
* It uses `SIGKILL` signal to kill the command.
*
* @returns `true` if the command was killed successfully, `false` if the command was not found.
*/
async kill() {
return await this.handleKill();
}
iterateEvents() {
return __asyncGenerator(this, null, function* () {
var _a2;
try {
for (var iter = __forAwait(this.events), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
const event = temp.value;
const e = (_a2 = event == null ? void 0 : event.event) == null ? void 0 : _a2.event;
let out;
switch (e == null ? void 0 : e.case) {
case "data":
switch (e.value.output.case) {
case "stdout":
out = new TextDecoder().decode(e.value.output.value);
this._stdout += out;
yield [out, null, null];
break;
case "stderr":
out = new TextDecoder().decode(e.value.output.value);
this._stderr += out;
yield [null, out, null];
break;
case "pty":
yield [null, null, e.value.output.value];
break;
}
break;
case "end":
this.result = {
exitCode: e.value.exitCode,
error: e.value.error,
stdout: this.stdout,
stderr: this.stderr
};
break;
}
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
} finally {
if (error)
throw error[0];
}
}
});
}
async handleEvents() {
var _a2, _b, _c;
try {
try {
for (var iter = __forAwait(this.iterateEvents()), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
const [stdout, stderr, pty] = temp.value;
if (stdout !== null) {
(_a2 = this.onStdout) == null ? void 0 : _a2.call(this, stdout);
} else if (stderr !== null) {
(_b = this.onStderr) == null ? void 0 : _b.call(this, stderr);
} else if (pty) {
(_c = this.onPty) == null ? void 0 : _c.call(this, pty);
}
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && await temp.call(iter);
} finally {
if (error)
throw error[0];
}
}
} catch (e) {
this.iterationError = handleRpcError(e);
}
}
};
// src/sandbox/index.ts
var import_connect_web = require("@connectrpc/connect-web");
// src/sandbox/commands/index.ts
var import_connect5 = require("@connectrpc/connect");
// src/envd/process/process_pb.ts
var import_codegenv22 = require("@bufbuild/protobuf/codegenv2");
var file_process_process = /* @__PURE__ */ (0, import_codegenv22.fileDesc)("ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvInkKDFN0YXJ0UmVxdWVzdBInCgdwcm9jZXNzGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEh4KA3B0eRgCIAEoCzIMLnByb2Nlc3MuUFRZSACIAQESEAoDdGFnGAMgASgJSAGIAQFCBgoEX3B0eUIGCgRfdGFnImIKDVVwZGF0ZVJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yEh4KA3B0eRgCIAEoCzIMLnByb2Nlc3MuUFRZSACIAQFCBgoEX3B0eSIQCg5VcGRhdGVSZXNwb25zZSKvAwoMUHJvY2Vzc0V2ZW50EjEKBXN0YXJ0GAEgASgLMiAucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuU3RhcnRFdmVudEgAEi8KBGRhdGEYAiABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5EYXRhRXZlbnRIABItCgNlbmQYAyABKAsyHi5wcm9jZXNzLlByb2Nlc3NFdmVudC5FbmRFdmVudEgAEjQKCWtlZXBhbGl2ZRgEIAEoCzIfLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LktlZXBBbGl2ZUgAGhkKClN0YXJ0RXZlbnQSCwoDcGlkGAEgASgNGkgKCURhdGFFdmVudBIQCgZzdGRvdXQYASABKAxIABIQCgZzdGRlcnIYAiABKAxIABINCgNwdHkYAyABKAxIAEIICgZvdXRwdXQaWwoIRW5kRXZlbnQSEQoJZXhpdF9jb2RlGAEgASgREg4KBmV4aXRlZBgCIAEoCBIOCgZzdGF0dXMYAyABKAkSEgoFZXJyb3IYBCABKAlIAIgBAUIICgZfZXJyb3IaCwoJS2VlcEFsaXZlQgcKBWV2ZW50IjUKDVN0YXJ0UmVzcG9uc2USJAoFZXZlbnQYASABKAsyFS5wcm9jZXNzLlByb2Nlc3NFdmVudCI3Cg9Db25uZWN0UmVzcG9uc2USJAoFZXZlbnQYASABKAsyFS5wcm9jZXNzLlByb2Nlc3NFdmVudCJjChBTZW5kSW5wdXRSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIkCgVpbnB1dBgCIAEoCzIVLnByb2Nlc3MuUHJvY2Vzc0lucHV0IhMKEVNlbmRJbnB1dFJlc3BvbnNlIjcKDFByb2Nlc3NJbnB1dBIPCgVzdGRpbhgBIAEoDEgAEg0KA3B0eRgCIAEoDEgAQgcKBWlucHV0IsICChJTdHJlYW1JbnB1dFJlcXVlc3QSNwoFc3RhcnQYASABKAsyJi5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5TdGFydEV2ZW50SAASNQoEZGF0YRgCIAEoCzIlLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXF1ZXN0LkRhdGFFdmVudEgAEjoKCWtlZXBhbGl2ZRgDIAEoCzIlLnByb2Nlc3MuU3RyZWFtSW5wdXRSZXF1ZXN0LktlZXBBbGl2ZUgAGjcKClN0YXJ0RXZlbnQSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yGjEKCURhdGFFdmVudBIkCgVpbnB1dBgCIAEoCzIVLnByb2Nlc3MuUHJvY2Vzc0lucHV0GgsKCUtlZXBBbGl2ZUIHCgVldmVudCIVChNTdHJlYW1JbnB1dFJlc3BvbnNlIl8KEVNlbmRTaWduYWxSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIfCgZzaWduYWwYAiABKA4yDy5wcm9jZXNzLlNpZ25hbCIUChJTZW5kU2lnbmFsUmVzcG9uc2UiOwoOQ29ubmVjdFJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIjsKD1Byb2Nlc3NTZWxlY3RvchINCgNwaWQYASABKA1IABINCgN0YWcYAiABKAlIAEIKCghzZWxlY3RvcipICgZTaWduYWwSFgoSU0lHTkFMX1VOU1BFQ0lGSUVEEAASEgoOU0lHTkFMX1NJR1RFUk0QDxISCg5TSUdOQUxfU0lHS0lMTBAJMsoDCgdQcm9jZXNzEjMKBExpc3QSFC5wcm9jZXNzLkxpc3RSZXF1ZXN0GhUucHJvY2Vzcy5MaXN0UmVzcG9uc2USPgoHQ29ubmVjdBIXLnByb2Nlc3MuQ29ubmVjdFJlcXVlc3QaGC5wcm9jZXNzLkNvbm5lY3RSZXNwb25zZTABEjgKBVN0YXJ0EhUucHJvY2Vzcy5TdGFydFJlcXVlc3QaFi5wcm9jZXNzLlN0YXJ0UmVzcG9uc2UwARI5CgZVcGRhdGUSFi5wcm9jZXNzLlVwZGF0ZVJlcXVlc3QaFy5wcm9jZXNzLlVwZGF0ZVJlc3BvbnNlEkoKC1N0cmVhbUlucHV0EhsucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QaHC5wcm9jZXNzLlN0cmVhbUlucHV0UmVzcG9uc2UoARJCCglTZW5kSW5wdXQSGS5wcm9jZXNzLlNlbmRJbnB1dFJlcXVlc3QaGi5wcm9jZXNzLlNlbmRJbnB1dFJlc3BvbnNlEkUKClNlbmRTaWduYWwSGi5wcm9jZXNzLlNlbmRTaWduYWxSZXF1ZXN0GhsucHJvY2Vzcy5TZW5kU2lnbmFsUmVzcG9uc2VCVwoLY29tLnByb2Nlc3NCDFByb2Nlc3NQcm90b1ABogIDUFhYqgIHUHJvY2Vzc8oCB1Byb2Nlc3PiAhNQcm9jZXNzXEdQQk1ldGFkYXRh6gIHUHJvY2Vzc2IGcHJvdG8z");
var Process = /* @__PURE__ */ (0, import_codegenv22.serviceDesc)(file_process_process, 0);
// src/sandbox/commands/pty.ts
var import_connect4 = require("@connectrpc/connect");
var Pty = class {
constructor(transport, connectionConfig) {
this.transport = transport;
this.connectionConfig = connectionConfig;
this.rpc = (0, import_connect4.createClient)(Process, this.transport);
}
/**
* Create a new PTY (pseudo-terminal).
*
* @param opts options for creating the PTY.
*
* @returns handle to interact with the PTY.
*/
async create(opts) {
var _a2, _b, _c;
const requestTimeoutMs = (_a2 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a2 : this.connectionConfig.requestTimeoutMs;
const envs = (_b = opts == null ? void 0 : opts.envs) != null ? _b : {};
envs.TERM = "xterm-256color";
const controller = new AbortController();
const reqTimeout = setTimeout(() => {
controller.abort();
}, requestTimeoutMs);
const events = this.rpc.start(
{
process: {
cmd: "/bin/bash",
args: ["-i", "-l"],
envs,
cwd: opts == null ? void 0 : opts.cwd
},
pty: {
size: {
cols: opts.cols,
rows: opts.rows
}
}
},
{
headers: __spreadProps(__spreadValues({}, authenticationHeader(opts == null ? void 0 : opts.user)), {
[KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
}),
signal: controller.signal,
timeoutMs: (_c = opts == null ? void 0 : opts.timeoutMs) != null ? _c : 6e4
}
);
try {
const pid = await handleProcessStartEvent(events);
clearTimeout(reqTimeout);
return new CommandHandle(
pid,
() => controller.abort(),
() => this.kill(pid),
events,
void 0,
void 0,
opts.onData
);
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Send input to a PTY.
*
* @param pid process ID of the PTY.
* @param data input data to send to the PTY.
* @param opts connection options.
*/
async sendInput(pid, data, opts) {
try {
await this.rpc.sendInput(
{
input: {
input: {
case: "pty",
value: data
}
},
process: {
selector: {
case: "pid",
value: pid
}
}
},
{
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Resize PTY.
* Call this when the terminal window is resized and the number of columns and rows has changed.
*
* @param pid process ID of the PTY.
* @param size new size of the PTY.
* @param opts connection options.
*/
async resize(pid, size, opts) {
try {
await this.rpc.update(
{
process: {
selector: {
case: "pid",
value: pid
}
},
pty: {
size
}
},
{
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Kill a running PTY specified by process ID.
* It uses `SIGKILL` signal to kill the PTY.
*
* @param pid process ID of the PTY.
* @param opts connection options.
*
* @returns `true` if the PTY was killed, `false` if the PTY was not found.
*/
async kill(pid, opts) {
try {
await this.rpc.sendSignal(
{
process: {
selector: {
case: "pid",
value: pid
}
},
signal: 9 /* SIGKILL */
},
{
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
return true;
} catch (err) {
if (err instanceof import_connect4.ConnectError) {
if (err.code === import_connect4.Code.NotFound) {
return false;
}
}
throw handleRpcError(err);
}
}
};
// src/sandbox/commands/index.ts
var Commands = class {
// 60 seconds
constructor(transport, connectionConfig) {
this.connectionConfig = connectionConfig;
this.defaultProcessConnectionTimeout = 6e4;
this.rpc = (0, import_connect5.createClient)(Process, transport);
}
/**
* List all running commands and PTY sessions.
*
* @param opts connection options.
*
* @returns list of running commands and PTY sessions.
*/
async list(opts) {
try {
const res = await this.rpc.list(
{},
{
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
return res.processes.map((p) => __spreadValues(__spreadProps(__spreadValues({
pid: p.pid
}, p.tag && { tag: p.tag }), {
args: p.config.args,
envs: p.config.envs,
cmd: p.config.cmd
}), p.config.cwd && { cwd: p.config.cwd }));
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Send data to command stdin.
*
* @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.
* @param data data to send to the command.
* @param opts connection options.
*/
async sendStdin(pid, data, opts) {
try {
await this.rpc.sendInput(
{
process: {
selector: {
case: "pid",
value: pid
}
},
input: {
input: {
case: "stdin",
value: new TextEncoder().encode(data)
}
}
},
{
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
} catch (err) {
throw handleRpcError(err);
}
}
/**
* Kill a running command specified by its process ID.
* It uses `SIGKILL` signal to kill the command.
*
* @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.
* @param opts connection options.
*
* @returns `true` if the command was killed, `false` if the command was not found.
*/
async kill(pid, opts) {
try {
await this.rpc.sendSignal(
{
process: {
selector: {
case: "pid",
value: pid
}
},
signal: 9 /* SIGKILL */
},
{
signal: this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
}
);
return true;
} catch (err) {
if (err instanceof import_connect5.ConnectError) {
if (err.code === import_connect5.Code.NotFound) {
return false;
}
}
throw handleRpcError(err);
}
}
/**
* Connect to a running command.
* You can use {@link CommandHandle.wait} to wait for the command to finish and get execution results.
*
* @param pid process ID of the command to connect to. You can get the list of running commands using {@link Commands.list}.
* @param opts connection options.
*
* @returns `CommandHandle` handle to interact with the running command.
*/
async connect(pid, opts) {
var _a2, _b;
const requestTimeoutMs = (_a2 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a2 : this.connectionConfig.requestTimeoutMs;
const controller = new AbortController();
const reqTimeout = requestTimeoutMs ? setTimeout(() => {
controller.abort();
}, requestTimeoutMs) : void 0;
const events = this.rpc.connect(
{
process: {
selector: {
case: "pid",
value: pid
}
}
},
{
signal: controller.signal,
headers: {
[KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
},
timeoutMs: (_b = opts == null ? void 0 : opts.timeoutMs) != null ? _b : this.defaultProcessConnectionTimeout
}
);
try {
const pid2 = await handleProcessStartEvent(events);
clearTimeout(reqTimeout);
return new CommandHandle(
pid2,
() => controller.abort(),
() => this.kill(pid2),
events,
opts == null ? void 0 : opts.onStdout,
opts == null ? void 0 : opts.onStderr,
void 0
);
} catch (err) {
throw handleRpcError(err);
}
}
async run(cmd, opts) {
const proc = await this.start(cmd, opts);
return (opts == null ? void 0 : opts.background) ? proc : proc.wait();
}
async start(cmd, opts) {
var _a2, _b;
const requestTimeoutMs = (_a2 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a2 : this.connectionConfig.requestTimeoutMs;
const controller = new AbortController();
const reqTimeout = requestTimeoutMs ? setTimeout(() => {
controller.abort();
}, requestTimeoutMs) : void 0;
const events = this.rpc.start(
{
process: {
cmd: "/bin/bash",
cwd: opts == null ? void 0 : opts.cwd,
envs: opts == null ? void 0 : opts.envs,
args: ["-l", "-c", cmd]
}
},
{
headers: __spreadProps(__spreadValues({}, authenticationHeader(opts == null ? void 0 : opts.user)), {
[KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString()
}),
signal: controller.signal,
timeoutMs: (_b = opts == null ? void 0 : opts.timeoutMs) != null ? _b : this.defaultProcessConnectionTimeout
}
);
try {
const pid = await handleProcessStartEvent(events);
clearTimeout(reqTimeout);
return new CommandHandle(
pid,
() => controller.abort(),
() => this.kill(pid),
events,
opts == null ? void 0 : opts.onStdout,
opts == null ? void 0 : opts.onStderr,
void 0
);
} catch (err) {
throw handleRpcError(err);
}
}
};
// src/sandbox/sandboxApi.ts
var import_compare_versions2 = require("compare-versions");
var SandboxApi = class {
constructor() {
}
/**
* Kill the sandbox specified by sandbox ID.
*
* @param sandboxId sandbox ID.
* @param opts connection options.
*
* @returns `true` if the sandbox was found and killed, `false` otherwise.
*/
static async kill(sandboxId, opts) {
var _a2;
const config = new ConnectionConfig(opts);
const client = new ApiClient(config);
const res = await client.api.DELETE("/sandboxes/{sandboxID}", {
params: {
path: {
sandboxID: sandboxId
}
},
signal: config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
if (((_a2 = res.error) == null ? void 0 : _a2.code) === 404) {
return false;
}
const err = handleApiError(res);
if (err) {
throw err;
}
return true;
}
/**
* List all running sandboxes.
*
* @param opts connection options.
*
* @returns list of running sandboxes.
*/
static async list(opts) {
var _a2, _b;
const config = new ConnectionConfig(opts);
const client = new ApiClient(config);
let metadata = void 0;
if (opts == null ? void 0 : opts.query) {
if (opts.query.metadata) {
const encodedPairs = Object.fromEntries(
Object.entries(opts.query.metadata).map(([key, value]) => [
encodeURIComponent(key),
encodeURIComponent(value)
])
);
metadata = new URLSearchParams(encodedPairs).toString();
}
}
const res = await client.api.GET("/sandboxes", {
params: {
query: { metadata }
},
signal: config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
const err = handleApiError(res);
if (err) {
throw err;
}
return (_b = (_a2 = res.data) == null ? void 0 : _a2.map((sandbox) => ({
sandboxId: sandbox.sandboxID,
templateId: sandbox.templateID,
clientId: sandbox.clientID,
state: sandbox.state,
cpuCount: sandbox.cpuCount,
memoryMB: sandbox.memoryMB,
alias: sandbox.alias,
metadata: sandbox.metadata,
startedAt: new Date(sandbox.startedAt),
endAt: new Date(sandbox.endAt)
}))) != null ? _b : [];
}
/**
* Get sandbox information like sandbox ID, template, metadata, started at/end at date.
*
* @param sandboxId sandbox ID.
* @param opts connection options.
*
* @returns sandbox information.
*/
static async getInfo(sandboxId, opts) {
var _a2;
const config = new ConnectionConfig(opts);
const client = new ApiClient(config);
const res = await client.api.GET("/sandboxes/{sandboxID}", {
params: {
path: {
sandboxID: sandboxId
}
},
signal: config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
const err = handleApiError(res);
if (err) {
throw err;
}
if (!res.data) {
throw new Error("Sandbox not found");
}
return __spreadProps(__spreadValues({
sandboxId: res.data.sandboxID,
sandboxDomain: res.data.domain || void 0,
templateId: res.data.templateID
}, res.data.alias && { name: res.data.alias }), {
metadata: (_a2 = res.data.metadata) != null ? _a2 : {},
envdVersion: res.data.envdVersion,
envdAccessToken: res.data.envdAccessToken,
startedAt: new Date(res.data.startedAt),
endAt: new Date(res.data.endAt)
});
}
/**
* Get the metrics of the sandbox.
*
* @param sandboxId sandbox ID.
* @param opts sandbox metrics options.
*
* @returns List of sandbox metrics containing CPU, memory and disk usage information.
*/
static async getMetrics(sandboxId, opts) {
var _a2, _b;
const config = new ConnectionConfig(opts);
const client = new ApiClient(config);
const res = await client.api.GET("/sandboxes/{sandboxID}/metrics", {
params: {
path: {
sandboxID: sandboxId,
start: opts == null ? void 0 : opts.start,
end: opts == null ? void 0 : opts.end
}
},
signal: config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
const err = handleApiError(res);
if (err) {
throw err;
}
return (_b = (_a2 = res.data) == null ? void 0 : _a2.map((metric) => ({
timestamp: new Date(metric.timestamp),
cpuUsedPct: metric.cpuUsedPct,
cpuCount: metric.cpuCount,
memUsed: metric.memUsed,
memTotal: metric.memTotal,
diskUsed: metric.diskUsed,
diskTotal: metric.diskTotal
}))) != null ? _b : [];
}
/**
* Set the timeout of the specified sandbox.
* After the timeout expires the sandbox will be automatically killed.
*
* This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to {@link Sandbox.setTimeout}.
*
* Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.
*
* @param sandboxId sandbox ID.
* @param timeoutMs timeout in **milliseconds**.
* @param opts connection options.
*/
static async setTimeout(sandboxId, timeoutMs, opts) {
const config = new ConnectionConfig(opts);
const client = new ApiClient(config);
const res = await client.api.POST("/sandboxes/{sandboxID}/timeout", {
params: {
path: {
sandboxID: sandboxId
}
},
body: {
timeout: this.timeoutToSeconds(timeoutMs)
},
signal: config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
const err = handleApiError(res);
if (err) {
throw err;
}
}
static async createSandbox(template, timeoutMs, opts) {
var _a2;
const config = new ConnectionConfig(opts);
const client = new ApiClient(config);
const res = await client.api.POST("/sandboxes", {
body: {
autoPause: false,
templateID: template,
metadata: opts == null ? void 0 : opts.metadata,
envVars: opts == null ? void 0 : opts.envs,
timeout: this.timeoutToSeconds(timeoutMs),
secure: opts == null ? void 0 : opts.secure,
allow_internet_access: (_a2 = opts == null ? void 0 : opts.allowInternetAccess) != null ? _a2 : true
},
signal: config.getSignal(opts == null ? void 0 : opts.requestTimeoutMs)
});
const err = handleApiError(res);
if (err) {
throw err;
}
if ((0, import_compare_versions2.compareVersions)(res.data.envdVersion, "0.1.0") < 0) {
await this.kill(res.data.sandboxID, opts);
throw new TemplateError(
"You need to update the template to use the new SDK. You can do this by running `e2b template build` in the directory with the template."
);
}
return {
sandboxId: res.data.sandboxID,
sandboxDomain: res.data.domain || void 0,
envdVersion: res.data.envdVersion,
envdAccessToken: res.data.envdAccessToken
};
}
static timeoutToSeconds(timeout) {
return Math.ceil(timeout / 1e3);
}
};
// src/sandbox/index.ts
var import_compare_versions3 = require("compare-versions");
var _Sandbox = class _Sandbox extends SandboxApi {
/**
* Use {@link Sandbox.create} to create a new Sandbox instead.
*
* @hidden
* @hide
* @internal
* @access protected
*/
constructor(opts) {
var _a2;
super();
this.envdPort = 49983;
this.connectionConfig = new ConnectionConfig(opts);
this.sandboxId = opts.sandboxId;
this.sandboxDomain = (_a2 = opts.sandboxDomain) != null ? _a2 : this.connectionConfig.domain;
this.envdAccessToken = opts.envdAccessToken;
this.envdApiUrl = `${this.connectionConfig.debug ? "http" : "https"}://${this.getHost(this.envdPort)}`;
const rpcTransport = (0, import_connect_web.createConnectTransport)({
baseUrl: this.envdApiUrl,
useBinaryFormat: false,
interceptors: (opts == null ? void 0 : opts.logger) ? [createRpcLogger(opts.logger)] : void 0,
fetch: (url, options) => {
const headers = new Headers(this.connectionConfig.headers);
new Headers(options == null ? void 0 : options.headers).forEach(
(value, key) => headers.append(key, value)
);
if (this.envdAccessToken) {
headers.append("X-Access-Token", this.envdAccessToken);
}
options = __spreadProps(__spreadValues({}, options != null ? options : {}), {
headers,
redirect: "follow"
});
return fetch(url, options);
}
});
this.envdApi = new EnvdApiClient(
{
apiUrl: this.envdApiUrl,
logger: opts == null ? void 0 : opts.logger,
accessToken: this.envdAccessToken,
headers: this.envdAccessToken ? { "X-Access-Token": this.envdAccessToken } : {}
},
{
version: opts == null ? void 0 : opts.envdVersion
}
);
this.files = new Filesystem2(
rpcTransport,
this.envdApi,
this.connectionConfig
);
this.commands = new Commands(rpcTransport, this.connectionConfig);
this.pty = new Pty(rpcTransport, this.connectionConfig);
}
static async create(templateOrOpts, opts) {
var _a2;
const { template, sandboxOpts } = typeof templateOrOpts === "string" ? { template: templateOrOpts, sandboxOpts: opts } : { template: this.defaultTemplate, sandboxOpts: templateOrOpts };
const config = new ConnectionConfig(sandboxOpts);
if (config.debug) {
return new this(__spreadValues({
sandboxId: "debug_sandbox_id"
}, config));
} else {
const sandbox = await this.createSandbox(
template,
(_a2 = sandboxOpts == null ? void 0 : sandboxOpts.timeoutMs) != null ? _a2 : this.defaultSandboxTimeoutMs,
sandboxOpts
);
return new this(__spreadValues(__spreadValues({}, sandbox), config));
}
}
/**
* Connect to an existing sandbox.
* With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).
*
* @param sandboxId sandbox ID.
* @param opts connection options.
*
* @returns sandbox instance for the existing sandbox.
*
* @example
* ```ts
* const sandbox = await Sandbox.create()
* const sandboxId = sandbox.sandboxId
*
* // Connect to the same sandbox.
* const sameSandbox = await Sandbox.connect(sandboxId)
* ```
*/
static async connect(sandboxId, opts) {
const config = new ConnectionConfig(opts);
const info = await this.getInfo(sandboxId, opts);
return new this(__spreadValues({
sandboxId,
sandboxDomain: info.sandboxDomain,
envdAccessToken: info.envdAccessToken,
envdVersion: info.envdVersion
}, config));
}
/**
* Get the host address for the specified sandbox port.
* You can then use this address to connect to the sandbox port from outside the sandbox via HTTP or WebSocket.
*
* @param port number of the port in the sandbox.
*
* @returns host address of the sandbox port.
*
* @example
* ```ts
* const sandbox = await Sandbox.create()
* // Start an HTTP server
* await sandbox.commands.exec('python3 -m http.server 3000')
* // Get the hostname of the HTTP server
* const serverURL = sandbox.getHost(3000)
* ```
*/
getHost(port) {
if (this.connectionConfig.debug) {
return `localhost:${port}`;
}
return `${port}-${this.sandboxId}.${this.sandboxDomain}`;
}
/**
* Check if the sandbox is running.
*
* @returns `true` if the sandbox is running, `false` otherwise.
*
* @example
* ```ts
* const sandbox = await Sandbox.create()
* await sandbox.isRunning() // Returns true
*
* await sandbox.kill()
* await sandbox.isRunning() // Returns false
* ```
*/
async isRunning(opts) {
const signal = this.connectionConfig.getSignal(opts == null ? void 0 : opts.requestTimeoutMs);
const res = await this.envdApi.api.GET("/health", {
signal
});
if (res.response.status == 502) {
return false;
}
const err = await handleEnvdApiError(res);
if (err) {
throw err;
}
return true;
}
/**
* Set the timeout of the sandbox.
* After the timeout expires the sandbox will be automatically killed.
*
* This method can extend or reduce the sandbox timeout set when creating the sandbox or from the last call to `.setTimeout`.
* Maximum time a sandbox can be kept alive is 24 hours (86_400_000 milliseconds) for Pro users and 1 hour (3_600_000 milliseconds) for Hobby users.
*
* @param timeoutMs timeout in **milliseconds**.
* @param opts connection options.
*/
async setTimeout(timeoutMs, opts) {
if (this.connectionConfig.debug) {
return;
}
await _Sandbox.setTimeout(this.sandboxId, timeoutMs, __spreadValues(__spreadValues({}, this.connectionConfig), opts));
}
/**
* Kill the sandbox.
*
* @param opts connection options.
*/
async kill(opts) {
if (this.connectionConfig.debug) {
return;
}
await _Sandbox.kill(this.sandboxId, __spreadValues(__spreadValues({}, this.connectionConfig), opts));
}
/**
* Get the URL to upload a file to the sandbox.
*
* You have to send a POST request to this URL with the file as multipart/form-data.
*
* @param path path to the file in the sandbox.
*
* @param opts download url options.
*
* @returns URL for uploading file.
*/
async uploadUrl(path, opts) {
var _a2;
opts = opts != null ? opts : {};
const useSignature = !!this.envdAccessToken;
if (!useSignature && opts.useSignatureExpiration != void 0) {
throw new Error(
"Signature expiration can be used only when sandbox is created as secured."
);
}
const username = (_a2 = opts.user) != null ? _a2 : defaultUsername;
const filePath = path != null ? path : "";
const fileUrl = this.fileUrl(filePath, username);
if (useSignature) {
const url = new URL(fileUrl);
const sig = await getSignature({
path: filePath,
operation: "write",
user: username,
expirationInSeconds: opts.useSignatureExpiration,
envdAccessToken: this.envdAccessToken
});
url.searchParams.set("signature", sig.signature);
if (sig.expiration) {
url.searchParams.set("signature_expiration", sig.expiration.toString());
}
return url.toString();
}
return fileUrl;
}
/**
* Get the URL to download a file from the sandbox.
*
* @param path path to the file in the sandbox.
*
* @param opts download url options.
*
* @returns URL for downloading file.
*/
async downloadUrl(path, opts) {
var _a2;
opts = opts != null ? opts : {};
const useSignature = !!this.envdAccessToken;
if (!useSignature && opts.useSignatureExpiration != void 0) {
throw new Error(
"Signature expiration can be used only when sandbox is created as secured."
);
}
const username = (_a2 = opts.user) != null ? _a2 : defaultUsername;
const fileUrl = this.fileUrl(path, username);
if (useSignature) {
const url = new URL(fileUrl);
const sig = await getSignature({
path,
operation: "read",
user: username,
expirationInSeconds: opts.useSignatureExpiration,
envdAccessToken: this.envdAccessToken
});
url.searchParams.set("signature", sig.signature);
if (sig.expiration) {
url.searchParams.set("signature_expiration", sig.expiration.toString());
}
return url.toString();
}
return fileUrl;
}
/**
* Get sandbox information like sandbox ID, template, metadata, started at/end at date.
*
* @param opts connection options.
*
* @returns information about the sandbox
*/
async getInfo(opts) {
return await _Sandbox.getInfo(this.sandboxId, __spreadValues(__spreadValues({}, this.connectionConfig), opts));
}
/**
* Get the metrics of the sandbox.
*
* @param opts connection options.
*
* @returns List of sandbox metrics containing CPU, memory and disk usage information.
*/
async getMetrics(opts) {
var _a2, _b;
if (this.envdApi.version) {
if ((0, import_compare_versions3.compareVersions)(this.envdApi.version, "0.1.5") < 0) {
throw new SandboxError(
"You need to update the template to use the new SDK. You can do this by running `e2b template build` in the directory with the template."
);
}
if ((0, import_compare_versions3.compareVersions)(this.envdApi.version, "0.2.4") < 0) {
(_b = (_a2 = this.connectionConfig.logger) == null ? void 0 : _a2.warn) == null ? void 0 : _b.call(
_a2,
"Disk metrics are not supported in this version of the sandbox, please rebuild the template to get disk metrics."
);
}
}
return await _Sandbox.getMetrics(this.sandboxId, __spreadValues(__spreadValues({}, this.connectionConfig), opts));
}
fileUrl(path, username) {
const url = new URL("/files", this.envdApiUrl);
url.searchParams.set("username", username != null ? username : defaultUsername);
if (path) {
url.searchParams.set("path", path);
}
return url.toString();
}
};
_Sandbox.defaultTemplate = "base";
_Sandbox.defaultSandboxTimeoutMs = 3e5;
var Sandbox = _Sandbox;
// src/index.ts
var src_default = Sandbox;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
ApiClient,
AuthenticationError,
CommandExitError,
ConnectionConfig,
FileType,
FilesystemEventType,
InvalidArgumentError,
NotEnoughSpaceError,
NotFoundError,
Sandbox,
SandboxError,
TemplateError,
TimeoutError,
getSignature
});
//# sourceMappingURL=index.js.map