e2b
Version:
E2B SDK that give agents cloud environments
1,411 lines (1,388 loc) • 236 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 __typeError = (msg) => {
throw TypeError(msg);
};
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 __objRest = (source, exclude) => {
var target = {};
for (var prop in source)
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
target[prop] = source[prop];
if (source != null && __getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(source)) {
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
target[prop] = source[prop];
}
return target;
};
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 __yieldStar = (value) => {
var obj = value[__knownSymbol("asyncIterator")], isAwait = false, method, it = {};
if (obj == null) {
obj = value[__knownSymbol("iterator")]();
method = (k) => it[k] = (x) => obj[k](x);
} else {
obj = obj.call(value);
method = (k) => it[k] = (v) => {
if (isAwait) {
isAwait = false;
if (k === "throw") throw v;
return v;
}
isAwait = true;
return {
done: false,
value: new __await(new Promise((resolve) => {
var x = obj[k](v);
if (!(x instanceof Object)) __typeError("Object expected");
resolve(x);
}), 1)
};
};
}
return it[__knownSymbol("iterator")] = () => it, method("next"), "throw" in obj ? method("throw") : it.throw = (x) => {
throw x;
}, "return" in obj && 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, {
ALL_TRAFFIC: () => ALL_TRAFFIC,
ApiClient: () => ApiClient,
AuthenticationError: () => AuthenticationError,
BuildError: () => BuildError,
CommandExitError: () => CommandExitError,
ConnectionConfig: () => ConnectionConfig,
FileNotFoundError: () => FileNotFoundError,
FileType: () => FileType2,
FileUploadError: () => FileUploadError,
FilesystemEventType: () => FilesystemEventType,
Git: () => Git,
GitAuthError: () => GitAuthError,
GitUpstreamError: () => GitUpstreamError,
InvalidArgumentError: () => InvalidArgumentError,
LogEntry: () => LogEntry,
LogEntryEnd: () => LogEntryEnd,
LogEntryStart: () => LogEntryStart,
NotEnoughSpaceError: () => NotEnoughSpaceError,
NotFoundError: () => NotFoundError,
RateLimitError: () => RateLimitError,
ReadyCmd: () => ReadyCmd,
Sandbox: () => Sandbox,
SandboxError: () => SandboxError,
SandboxNotFoundError: () => SandboxNotFoundError,
Template: () => Template,
TemplateBase: () => TemplateBase,
TemplateError: () => TemplateError,
TimeoutError: () => TimeoutError,
Volume: () => Volume,
VolumeError: () => VolumeError,
VolumeFileType: () => VolumeFileType,
default: () => src_default,
defaultBuildLogger: () => defaultBuildLogger,
getSignature: () => getSignature,
waitForFile: () => waitForFile,
waitForPort: () => waitForPort,
waitForProcess: () => waitForProcess,
waitForTimeout: () => waitForTimeout,
waitForURL: () => waitForURL
});
module.exports = __toCommonJS(src_exports);
// src/api/index.ts
var import_openapi_fetch = __toESM(require("openapi-fetch"));
// src/api/metadata.ts
var import_platform2 = __toESM(require("platform"));
// package.json
var version = "2.32.0";
// src/utils.ts
var import_platform = __toESM(require("platform"));
function getRuntime() {
var _a3, _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 = (_a3 = globalThis.process) == null ? void 0 : _a3.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();
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");
}
function timeoutToSeconds(timeout) {
return Math.ceil(timeout / 1e3);
}
function dynamicRequire(module2) {
if (runtime === "browser") {
throw new Error("Browser runtime is not supported for require");
}
return require(module2);
}
async function dynamicImport(module2) {
if (runtime === "browser") {
throw new Error("Browser runtime is not supported for dynamic import");
}
return await import(module2);
}
function ansiRegex({ onlyFirst = false } = {}) {
const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)";
const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`;
const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]";
const pattern = `${osc}|${csi}`;
return new RegExp(pattern, onlyFirst ? void 0 : "g");
}
function stripAnsi(text) {
return text.replace(ansiRegex(), "");
}
function toBlob(data) {
if (data instanceof Blob) {
return data;
}
if (typeof data === "string" || data instanceof ArrayBuffer) {
return new Blob([data]);
}
return new Response(data).blob();
}
var UNSAFE_SHELL_CHAR = /[^\w@%+=:,./-]/;
function shellQuote(s) {
if (s === "") {
return "''";
}
if (!UNSAFE_SHELL_CHAR.test(s)) {
return s;
}
return "'" + s.replace(/'/g, `'"'"'`) + "'";
}
async function toUploadBody(data, gzip) {
if (gzip) {
const stream = data instanceof ReadableStream ? data : data instanceof Blob ? data.stream() : new Blob([data]).stream();
const compressed = stream.pipeThrough(new CompressionStream("gzip"));
return runtime === "browser" ? new Response(compressed).blob() : compressed;
}
if (data instanceof ReadableStream && runtime !== "browser") {
return data;
}
return toBlob(data);
}
// src/api/metadata.ts
var _a;
var defaultHeaders = {
browser: typeof window !== "undefined" && import_platform2.default.name || "unknown",
lang: "js",
lang_version: runtimeVersion,
package_version: version,
publisher: "e2b",
sdk_runtime: runtime,
system: ((_a = import_platform2.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];
}
function parseIntEnv(name, defaultValue) {
const raw = getEnvVar(name);
if (!raw) return defaultValue;
const parsed = Number.parseInt(raw, 10);
if (!Number.isFinite(parsed)) {
throw new Error(
`Invalid ${name}=${JSON.stringify(raw)}: expected an integer.`
);
}
return parsed;
}
function parsePositiveIntEnv(name, defaultValue) {
const parsed = parseIntEnv(name, defaultValue);
if (parsed < 1) {
throw new Error(`Invalid ${name}=${parsed}: expected a positive integer.`);
}
return parsed;
}
function parseInflightLimitEnv(name, defaultValue) {
const parsed = parseIntEnv(name, defaultValue);
if (parsed < 0) {
throw new Error(
`Invalid ${name}=${parsed}: expected a non-negative integer (use 0 to disable the cap).`
);
}
return parsed;
}
// src/api/inflight.ts
var Semaphore = class {
constructor(max) {
this.max = max;
this.active = 0;
this.queue = [];
}
async acquire(signal) {
if (signal == null ? void 0 : signal.aborted) throw abortReason(signal);
if (this.active < this.max) {
this.active++;
return () => this.release();
}
return new Promise((resolve, reject) => {
const onAcquire = () => {
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
this.active++;
resolve(() => this.release());
};
const onAbort = () => {
const i = this.queue.indexOf(onAcquire);
if (i >= 0) this.queue.splice(i, 1);
reject(abortReason(signal));
};
this.queue.push(onAcquire);
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
});
}
release() {
this.active--;
const next = this.queue.shift();
if (next) next();
}
};
function abortReason(signal) {
var _a3;
return (_a3 = signal == null ? void 0 : signal.reason) != null ? _a3 : new DOMException("Aborted", "AbortError");
}
function limitConcurrency(fetcher, max) {
if (!Number.isFinite(max) || max <= 0) {
return fetcher;
}
const sem = new Semaphore(max);
return (async (input, init) => {
var _a3;
const signal = (_a3 = init == null ? void 0 : init.signal) != null ? _a3 : input instanceof Request ? input.signal : void 0;
const release = await sem.acquire(signal);
try {
return await fetcher(input, init);
} finally {
release();
}
});
}
// src/undici.ts
async function loadUndici() {
try {
const importModule = new Function(
"moduleName",
"return import(moduleName)"
);
return await importModule("undici");
} catch (e) {
return void 0;
}
}
function toUndiciRequestInput(input, init) {
if (!(input instanceof Request)) {
return { input, init };
}
const requestInit = __spreadValues({
body: input.body,
cache: input.cache,
credentials: input.credentials,
headers: input.headers,
integrity: input.integrity,
keepalive: input.keepalive,
method: input.method,
mode: input.mode,
redirect: input.redirect,
referrer: input.referrer,
referrerPolicy: input.referrerPolicy,
signal: input.signal
}, init);
if (requestInit.body) {
requestInit.duplex = "half";
}
return {
input: input.url,
init: requestInit
};
}
// src/api/http2.ts
var DEFAULT_API_CONNECTION_LIMIT = 100;
var DEFAULT_API_INFLIGHT_LIMIT = 1e3;
var apiFetchers = /* @__PURE__ */ new Map();
function createApiFetch(proxy) {
const key = proxy != null ? proxy : "";
const cached = apiFetchers.get(key);
if (cached) {
return cached;
}
const apiFetch = createApiFetchForRuntime(runtime, { proxy });
apiFetchers.set(key, apiFetch);
return apiFetch;
}
function createApiFetchForRuntime(currentRuntime = runtime, options = {}) {
if (currentRuntime !== "node") {
return fetch;
}
let fetcherPromise;
return (async (input, init) => {
fetcherPromise != null ? fetcherPromise : fetcherPromise = buildApiFetcher(options);
const fetcher = await fetcherPromise;
return fetcher(input, init);
});
}
async function buildApiFetcher(options) {
var _a3, _b, _c;
const undici = await ((_a3 = options.loadUndici) != null ? _a3 : loadUndici)();
const inflightLimit = (_b = options.inflightLimit) != null ? _b : getApiInflightLimit();
if (!undici) {
return limitConcurrency(fetch, inflightLimit);
}
const { Agent, ProxyAgent, fetch: undiciFetch } = undici;
const connections = (_c = options.connectionLimit) != null ? _c : getApiConnectionLimit();
const dispatcher = options.proxy ? new ProxyAgent({
uri: options.proxy,
allowH2: true,
connections
}) : new Agent({
allowH2: true,
connections
});
const fetchWithDispatcher = undiciFetch;
const wrapped = ((input, init) => {
const request = toUndiciRequestInput(input, init);
return fetchWithDispatcher(request.input, __spreadProps(__spreadValues({}, request.init), {
dispatcher
}));
});
return limitConcurrency(wrapped, inflightLimit);
}
function getApiConnectionLimit() {
return parsePositiveIntEnv(
"E2B_API_CONNECTIONS",
DEFAULT_API_CONNECTION_LIMIT
);
}
function getApiInflightLimit() {
return parseInflightLimitEnv(
"E2B_API_INFLIGHT_REQUESTS",
DEFAULT_API_INFLIGHT_LIMIT
);
}
// 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, stackTrace) {
super(message);
this.name = "SandboxError";
if (stackTrace) {
this.stack = stackTrace;
}
}
};
var TimeoutError = class extends SandboxError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "TimeoutError";
}
};
var InvalidArgumentError = class extends SandboxError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "InvalidArgumentError";
}
};
var NotEnoughSpaceError = class extends SandboxError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "NotEnoughSpaceError";
}
};
var NotFoundError = class extends SandboxError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "NotFoundError";
}
};
var FileNotFoundError = class extends NotFoundError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "FileNotFoundError";
}
};
var SandboxNotFoundError = class extends NotFoundError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "SandboxNotFoundError";
}
};
var AuthenticationError = class extends Error {
constructor(message) {
super(message);
this.name = "AuthenticationError";
}
};
var GitAuthError = class extends AuthenticationError {
constructor(message) {
super(message);
this.name = "GitAuthError";
}
};
var GitUpstreamError = class extends SandboxError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "GitUpstreamError";
}
};
var TemplateError = class extends SandboxError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "TemplateError";
}
};
var RateLimitError = class extends SandboxError {
constructor(message) {
super(message);
this.name = "RateLimitError";
}
};
var BuildError = class extends Error {
constructor(message, stackTrace) {
super(message);
this.name = "BuildError";
if (stackTrace) {
this.stack = stackTrace;
}
}
};
var FileUploadError = class extends BuildError {
constructor(message, stackTrace) {
super(message, stackTrace);
this.name = "FileUploadError";
}
};
var VolumeError = class extends Error {
constructor(message) {
super(message);
this.name = "VolumeError";
}
};
// src/logs.ts
function formatLog(log) {
return JSON.parse(
JSON.stringify(
log,
(_, value) => typeof value === "bigint" ? value.toString() : value
)
);
}
function createRpcLogger(logger) {
function logEach(stream) {
return __asyncGenerator(this, null, function* () {
var _a3;
try {
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
const m = temp.value;
(_a3 = logger.debug) == null ? void 0 : _a3.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 _a3, _b;
(_a3 = logger.info) == null ? void 0 : _a3.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({ request }) {
var _a3;
(_a3 = logger.info) == null ? void 0 : _a3.call(logger, `Request ${request.method} ${request.url}`);
return request;
},
async onResponse({ response }) {
var _a3, _b;
if (response.status >= 400) {
(_a3 = logger.error) == null ? void 0 : _a3.call(logger, "Response:", response.status, response.statusText);
} else {
(_b = logger.info) == null ? void 0 : _b.call(logger, "Response:", response.status, response.statusText);
}
return response;
}
};
}
// src/api/index.ts
var API_KEY_PATTERN = /^e2b_[0-9a-f]+$/;
var API_KEY_EXAMPLE = `e2b_${"0".repeat(40)}`;
function validateApiKey(apiKey) {
if (!API_KEY_PATTERN.test(apiKey)) {
throw new AuthenticationError(
`Invalid API key format: expected "e2b_" followed by hex characters (e.g. "${API_KEY_EXAMPLE}"). Visit the API Keys tab at https://e2b.dev/dashboard?tab=keys to get your API key.`
);
}
}
function handleApiError(response, errorClass = SandboxError, stackTrace) {
var _a3, _b, _c, _d, _e;
if (response.response.ok) {
return;
}
if (response.response.status === 401) {
const message2 = "Unauthorized, please check your credentials.";
const content = (_b = (_a3 = response.error) == null ? void 0 : _a3.message) != null ? _b : response.error;
if (content) {
return new AuthenticationError(`${message2} - ${content}`);
}
return new AuthenticationError(message2);
}
if (response.response.status === 429) {
const message2 = "Rate limit exceeded, please try again later";
const content = (_d = (_c = response.error) == null ? void 0 : _c.message) != null ? _d : response.error;
if (content) {
return new RateLimitError(`${message2} - ${content}`);
}
return new RateLimitError(message2);
}
const message = ((_e = response.error) == null ? void 0 : _e.message) || response.error || response.response.statusText;
return new errorClass(`${response.response.status}: ${message}`, stackTrace);
}
var ApiClient = class {
constructor(config, opts = {}) {
var _a3;
if (((_a3 = opts.requireApiKey) != null ? _a3 : true) && !config.apiKey) {
throw new AuthenticationError(
"API key is required, please visit the API Keys tab at https://e2b.dev/dashboard?tab=keys 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 (config.apiKey && config.validateApiKey) {
validateApiKey(config.apiKey);
}
this.api = (0, import_openapi_fetch.default)({
baseUrl: config.apiUrl,
fetch: createApiFetch(config.proxy),
// In HTTP 1.1, all connections are considered persistent unless declared otherwise
// keepalive: true,
headers: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, defaultHeaders), config.apiKey && { "X-API-KEY": config.apiKey }), config.accessToken && {
Authorization: `Bearer ${config.accessToken}`
}), config.headers),
querySerializer: {
array: {
style: "form",
explode: false
}
}
});
if (config.logger) {
this.api.use(createApiLogger(config.logger));
}
}
};
// src/connectionConfig.ts
var supportedDomains = ["e2b.app", "e2b.dev", "e2b.pro", "e2b-staging.dev"];
var REQUEST_TIMEOUT_MS = 6e4;
var DEFAULT_SANDBOX_TIMEOUT_MS = 3e5;
var KEEPALIVE_PING_INTERVAL_SEC = 50;
var KEEPALIVE_PING_HEADER = "Keepalive-Ping-Interval";
function buildRequestSignal(requestTimeoutMs, userSignal) {
const timeoutSignal = requestTimeoutMs ? AbortSignal.timeout(requestTimeoutMs) : void 0;
if (timeoutSignal && userSignal) {
return AbortSignal.any([timeoutSignal, userSignal]);
}
return timeoutSignal != null ? timeoutSignal : userSignal;
}
function setupRequestController(requestTimeoutMs, userSignal) {
const controller = new AbortController();
const onUserAbort = () => controller.abort(userSignal == null ? void 0 : userSignal.reason);
if (userSignal) {
if (userSignal.aborted) {
controller.abort(userSignal.reason);
} else {
userSignal.addEventListener("abort", onUserAbort, { once: true });
}
}
let reqTimeout = requestTimeoutMs ? setTimeout(
() => controller.abort(
new DOMException(
`Request handshake timed out after ${requestTimeoutMs}ms`,
"TimeoutError"
)
),
requestTimeoutMs
) : void 0;
const clearStartTimeout = () => {
if (reqTimeout) {
clearTimeout(reqTimeout);
reqTimeout = void 0;
}
};
let cleaned = false;
const cleanup = () => {
if (cleaned) return;
cleaned = true;
userSignal == null ? void 0 : userSignal.removeEventListener("abort", onUserAbort);
clearStartTimeout();
controller.abort();
};
return { controller, clearStartTimeout, cleanup };
}
function createIdleAbort(controller, idleTimeoutMs, label) {
let timer;
const clear = () => {
if (timer) {
clearTimeout(timer);
timer = void 0;
}
};
const arm = () => {
if (!idleTimeoutMs) return;
clear();
timer = setTimeout(
() => controller.abort(
new DOMException(
`${label} idle for ${idleTimeoutMs}ms`,
"TimeoutError"
)
),
idleTimeoutMs
);
};
return { arm, clear };
}
function wrapStreamWithConnectionCleanup(body, {
clearStartTimeout,
cleanup,
controller,
idleTimeoutMs
}) {
clearStartTimeout();
if (!body) {
cleanup();
return new Blob([]).stream();
}
const reader = body.getReader();
const idle = createIdleAbort(controller, idleTimeoutMs, "Stream");
const release = () => {
idle.clear();
cleanup();
};
return new ReadableStream({
async pull(streamController) {
idle.arm();
try {
const { done, value } = await reader.read();
idle.clear();
if (done) {
release();
streamController.close();
} else {
streamController.enqueue(value);
}
} catch (err) {
release();
streamController.error(err);
}
},
async cancel(reason) {
try {
await reader.cancel(reason);
} finally {
release();
}
}
});
}
function buildUserAgent(integration) {
const userAgentParts = [`e2b-js-sdk/${version}`];
if (integration) {
userAgentParts.push(integration);
}
return userAgentParts.join(" ");
}
var _ConnectionConfig = class _ConnectionConfig {
constructor(opts) {
var _a3, _b, _c, _d, _e;
this.apiKey = (opts == null ? void 0 : opts.apiKey) || _ConnectionConfig.apiKey;
this.validateApiKey = (_a3 = opts == null ? void 0 : opts.validateApiKey) != null ? _a3 : _ConnectionConfig.validateApiKey;
this.debug = (_b = opts == null ? void 0 : opts.debug) != null ? _b : _ConnectionConfig.debug;
this.domain = (opts == null ? void 0 : opts.domain) || _ConnectionConfig.domain;
this.accessToken = (opts == null ? void 0 : opts.accessToken) || _ConnectionConfig.accessToken;
this.requestTimeoutMs = (_c = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _c : REQUEST_TIMEOUT_MS;
this.logger = opts == null ? void 0 : opts.logger;
this.integration = opts == null ? void 0 : opts.integration;
this.headers = __spreadValues(__spreadValues({}, (_d = opts == null ? void 0 : opts.headers) != null ? _d : {}), (_e = opts == null ? void 0 : opts.apiHeaders) != null ? _e : {});
this.headers["User-Agent"] = buildUserAgent(this.integration);
this.proxy = opts == null ? void 0 : opts.proxy;
this.apiUrl = (opts == null ? void 0 : opts.apiUrl) || _ConnectionConfig.apiUrl || (this.debug ? "http://localhost:3000" : `https://api.${this.domain}`);
this.sandboxUrl = (opts == null ? void 0 : opts.sandboxUrl) || _ConnectionConfig.sandboxUrl;
}
static get domain() {
return getEnvVar("E2B_DOMAIN") || "e2b.app";
}
static get apiUrl() {
return getEnvVar("E2B_API_URL");
}
static get sandboxUrl() {
return getEnvVar("E2B_SANDBOX_URL");
}
static get debug() {
return (getEnvVar("E2B_DEBUG") || "false").toLowerCase() === "true";
}
static get apiKey() {
return getEnvVar("E2B_API_KEY");
}
static get validateApiKey() {
return (getEnvVar("E2B_VALIDATE_API_KEY") || "true").toLowerCase() !== "false";
}
static get accessToken() {
return getEnvVar("E2B_ACCESS_TOKEN");
}
getSignal(requestTimeoutMs, signal) {
return buildRequestSignal(requestTimeoutMs != null ? requestTimeoutMs : this.requestTimeoutMs, signal);
}
getSandboxUrl(sandboxId, opts) {
var _a3;
if (this.sandboxUrl) {
return this.sandboxUrl;
}
if (this.debug) {
return `http://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`;
}
const sandboxDomain = (_a3 = opts.sandboxDomain) != null ? _a3 : this.domain;
if (runtime !== "browser" && supportedDomains.includes(sandboxDomain)) {
return `https://sandbox.${sandboxDomain}`;
}
return `https://${this.getHost(sandboxId, opts.envdPort, sandboxDomain)}`;
}
getSandboxDirectUrl(sandboxId, opts) {
if (this.sandboxUrl) {
return this.sandboxUrl;
}
if (this.debug) {
return `http://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`;
}
return `https://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`;
}
getHost(sandboxId, port, sandboxDomain) {
if (this.debug) {
return `localhost:${port}`;
}
return `${port}-${sandboxId}.${sandboxDomain != null ? sandboxDomain : this.domain}`;
}
};
_ConnectionConfig.envdPort = 49983;
var ConnectionConfig = _ConnectionConfig;
var defaultUsername = "user";
// src/sandbox/signature.ts
async function getSignature({
path: path2,
operation,
user,
expirationInSeconds,
envdAccessToken
}) {
if (!envdAccessToken) {
throw new Error(
"Access token is not set and signature cannot be generated!"
);
}
const signatureExpiration = expirationInSeconds != null ? Math.floor(Date.now() / 1e3) + expirationInSeconds : null;
let signatureRaw;
if (user == void 0) {
user = "";
}
if (signatureExpiration === null) {
signatureRaw = `${path2}:${operation}:${user}:${envdAccessToken}`;
} else {
signatureRaw = `${path2}:${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_connect2 = require("@connectrpc/connect");
// src/envd/rpc.ts
var import_connect = require("@connectrpc/connect");
var import_compare_versions = require("compare-versions");
// src/envd/versions.ts
var ENVD_VERSION_RECURSIVE_WATCH = "0.1.4";
var ENVD_DEBUG_FALLBACK = "99.99.99";
var ENVD_COMMANDS_STDIN = "0.3.0";
var ENVD_DEFAULT_USER = "0.4.0";
var ENVD_ENVD_CLOSE = "0.5.2";
var ENVD_OCTET_STREAM_UPLOAD = "0.5.7";
var ENVD_FILE_METADATA = "0.6.2";
var ENVD_VERSION_FS_EVENT_ENTRY_INFO = "0.6.3";
var ENVD_VERSION_WATCH_NETWORK_MOUNTS = "0.6.4";
// src/envd/rpc.ts
var CONNECTION_TERMINATED_MESSAGES = [
"terminated",
"The socket connection was closed unexpectedly",
"error reading a body from connection"
];
function isConnectionTerminatedMessage(message) {
if (!message) {
return false;
}
return CONNECTION_TERMINATED_MESSAGES.some(
(fragment) => message.includes(fragment)
);
}
function isConnectionTerminatedError(err) {
return err instanceof import_connect.ConnectError && err.code === import_connect.Code.Unknown && isConnectionTerminatedMessage(err.rawMessage);
}
var DEFAULT_ERROR_MAP = {
[import_connect.Code.InvalidArgument]: (message) => new InvalidArgumentError(message),
[import_connect.Code.Unauthenticated]: (message) => new AuthenticationError(message),
[import_connect.Code.NotFound]: (message) => new NotFoundError(message),
[import_connect.Code.ResourceExhausted]: (message) => new RateLimitError(
`${message}: Rate limit exceeded, please try again later.`
),
[import_connect.Code.Unavailable]: formatSandboxTimeoutError,
[import_connect.Code.Canceled]: (message) => new TimeoutError(
`${message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.`
),
[import_connect.Code.DeadlineExceeded]: (message) => new TimeoutError(
`${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.`
)
};
function handleRpcError(err, errorMap) {
if (err instanceof import_connect.ConnectError) {
if (errorMap && err.code in errorMap) {
return errorMap[err.code](err.message);
}
if (err.code in DEFAULT_ERROR_MAP) {
return DEFAULT_ERROR_MAP[err.code](err.message);
}
return new SandboxError(`${err.code}: ${err.message}`);
}
return err;
}
async function handleRpcErrorWithHealthCheck(err, checkHealth, errorMap) {
if (isConnectionTerminatedError(err) && checkHealth) {
const running = await checkHealth().catch(() => void 0);
if (running === false) {
return new TimeoutError(
`${err.message}: The sandbox was killed or reached its end of life while the request was in flight.`
);
}
}
return handleRpcError(err, errorMap);
}
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(envdVersion, username) {
if (username == void 0 && (0, import_compare_versions.compareVersions)(envdVersion, ENVD_DEFAULT_USER) < 0) {
username = defaultUsername;
}
if (!username) {
return {};
}
const value = `${username}:`;
const encoded = encode64(value);
return { Authorization: `Basic ${encoded}` };
}
// src/envd/api.ts
var DEFAULT_ERROR_MAP2 = {
400: (message) => new InvalidArgumentError(message),
401: (message) => new AuthenticationError(message),
404: (message) => new NotFoundError(message),
429: (message) => new RateLimitError(`${message}: The requests are being rate limited.`),
502: formatSandboxTimeoutError,
507: (message) => new NotEnoughSpaceError(message)
};
var HEALTH_CHECK_TIMEOUT_MS = 5e3;
async function checkSandboxHealth(envdApi) {
try {
const res = await envdApi.api.GET("/health", {
signal: AbortSignal.timeout(HEALTH_CHECK_TIMEOUT_MS)
});
if (res.response.status === 502) {
return false;
}
if (res.response.ok) {
return true;
}
return void 0;
} catch (e) {
return void 0;
}
}
async function handleEnvdApiFetchError(err, checkHealth) {
if (err instanceof Error && isConnectionTerminatedMessage(err.message)) {
const running = checkHealth ? await checkHealth().catch(() => void 0) : void 0;
if (running === false) {
return new TimeoutError(
`${err.message}: The sandbox was killed or reached its end of life while the request was in flight.`
);
}
}
return err;
}
async function handleEnvdApiError(res, errorMap) {
var _a3, _b, _c, _d;
if (res.response.ok) {
return;
}
let message = (_b = typeof res.error === "string" ? res.error : (_a3 = res.error) == null ? void 0 : _a3.message) != null ? _b : "";
if (!message && !res.response.bodyUsed) {
try {
message = await res.response.text();
} catch (e) {
}
}
message = message || res.response.statusText;
if (errorMap && res.response.status in errorMap) {
return (_c = errorMap[res.response.status]) == null ? void 0 : _c.call(errorMap, message);
}
if (res.response.status in DEFAULT_ERROR_MAP2) {
return (_d = DEFAULT_ERROR_MAP2[res.response.status]) == null ? void 0 : _d.call(DEFAULT_ERROR_MAP2, message);
}
return new SandboxError(`${res.response.status}: ${message}`);
}
async function handleProcessStartEvent(events) {
var _a3;
let startEvent;
try {
startEvent = (await events[Symbol.asyncIterator]().next()).value;
} catch (err) {
if (err instanceof import_connect2.ConnectError) {
if (err.code === import_connect2.Code.Unavailable) {
throw new SandboxNotFoundError(
"Sandbox is probably not running anymore"
);
}
}
throw err;
}
if (((_a3 = startEvent.event) == null ? void 0 : _a3.event.case) !== "start") {
throw new Error("Expected start event");
}
return startEvent.event.event.value.pid;
}
async function handleWatchDirStartEvent(events) {
var _a3;
let startEvent;
try {
startEvent = (await events[Symbol.asyncIterator]().next()).value;
} catch (err) {
if (err instanceof import_connect2.ConnectError) {
if (err.code === import_connect2.Code.Unavailable) {
throw new SandboxNotFoundError(
"Sandbox is probably not running anymore"
);
}
}
throw err;
}
if (((_a3 = startEvent.event) == null ? void 0 : _a3.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: __spreadValues(__spreadValues({}, config == null ? void 0 : config.headers), config.envdAccessToken && {
"X-Access-Token": config.envdAccessToken
})
// In HTTP 1.1, all connections are considered persistent unless declared otherwise
// keepalive: true,
});
this.version = metadata.version;
if (config.logger) {
this.api.use(createApiLogger(config.logger));
}
}
};
// 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)(
"ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i5QIKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQESNQoIbWV0YWRhdGEYCyADKAsyIy5maWxlc3lzdGVtLkVudHJ5SW5mby5NZXRhZGF0YUVudHJ5Gi8KDU1ldGFkYXRhRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4AUIRCg9fc3ltbGlua190YXJnZXQiLQoOTGlzdERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRINCgVkZXB0aBgCIAEoDSI5Cg9MaXN0RGlyUmVzcG9uc2USJgoHZW50cmllcxgBIAMoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvImcKD1dhdGNoRGlyUmVxdWVzdBIMCgRwYXRoGAEgASgJEhEKCXJlY3Vyc2l2ZRgCIAEoCBIVCg1pbmNsdWRlX2VudHJ5GAMgASgIEhwKFGFsbG93X25ldHdvcmtfbW91bnRzGAQgASgIInkKD0ZpbGVzeXN0ZW1FdmVudBIMCgRuYW1lGAEgASgJEiMKBHR5cGUYAiABKA4yFS5maWxlc3lzdGVtLkV2ZW50VHlwZRIpCgVlbnRyeRgDIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvSACIAQFCCAoGX2VudHJ5IuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQibAoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgSFQoNaW5jbHVkZV9lbnRyeRgDIAEoCBIcChRhbGxvd19uZXR3b3JrX21vdW50cxgEIAEoCCIrChVDcmVhdGVXYXRjaGVyUmVzcG9uc2USEgoKd2F0Y2hlcl9pZBgBIAEoCSItChdHZXRXYXRjaGVyRXZlbnRzUmVxdWVzdBISCgp3YXRjaGVyX2lkGAEgASgJIkcKGEdldFdhdGNoZXJFdmVudHNSZXNwb25zZRIrCgZldmVudHMYASADKAsyGy5maWxlc3lzdGVtLkZpbGVzeXN0ZW1FdmVudCIqChRSZW1vdmVXYXRjaGVyUmVxdWVzdBISCgp3YXRjaGVyX2lkGAEgASgJIhcKFVJlbW92ZVdhdGNoZXJSZXNwb25zZSpSCghGaWxlVHlwZRIZChVGSUxFX1RZUEVfVU5TUEVDSUZJRUQQABISCg5GSUxFX1RZUEVfRklMRRABEhcKE0ZJTEVfVFlQRV9ESVJFQ1RPUlkQAiqYAQoJRXZlbnRUeXBlEhoKFkVWRU5UX1RZUEVfVU5TUEVDSUZJRUQQABIVChFFVkVOVF9UWVBFX0NSRUFURRABEhQKEEVWRU5UX1RZUEVfV1JJVEUQAhIVChFFVkVOVF9UWVBFX1JFTU9WRRADEhUKEUVWRU5UX1RZUEVfUkVOQU1FEAQSFAoQRVZFTlRfVFlQRV9DSE1PRBAFMp8FCgpGaWxlc3lzdGVtEjkKBFN0YXQSFy5maWxlc3lzdGVtLlN0YXRSZXF1ZXN0GhguZmlsZXN5c3RlbS5TdGF0UmVzcG9uc2USQgoHTWFrZURpchIaLmZpbGVzeXN0ZW0uTWFrZURpclJlcXVlc3QaGy5maWxlc3lzdGVtLk1ha2VEaXJSZXNwb25zZRI5CgRNb3ZlEhcuZmlsZXN5c3RlbS5Nb3ZlUmVxdWVzdBoYLmZpbGVzeXN0ZW0uTW92ZVJlc3BvbnNlEkIKB0xpc3REaXISGi5maWxlc3lzdGVtLkxpc3REaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5MaXN0RGlyUmVzcG9uc2USPwoGUmVtb3ZlEhkuZmlsZXN5c3RlbS5SZW1vdmVSZXF1ZXN0GhouZmlsZXN5c3RlbS5SZW1vdmVSZXNwb25zZRJHCghXYXRjaERpchIbLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXF1ZXN0GhwuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlMAESVAoNQ3JlYXRlV2F0Y2hlchIgLmZpbGVzeXN0ZW0uQ3JlYXRlV2F0Y2hlclJlcXVlc3QaIS5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXNwb25zZRJdChBHZXRXYXRjaGVyRXZlbnRzEiMuZmlsZXN5c3RlbS5HZXRXYXRjaGVyRXZlbnRzUmVxdWVzdBokLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1Jlc3BvbnNlElQKDVJlbW92ZVdhdGNoZXISIC5maWxlc3lzdGVtLlJlbW92ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVzcG9uc2VCaQoOY29tLmZpbGVzeXN0ZW1CD0ZpbGVzeXN0ZW1Qcm90b1ABogIDRlhYqgIKRmlsZXN5c3RlbcoCCkZpbGVzeXN0ZW3iAhZGaWxlc3lzdGVtXEdQQk1ldGFkYXRh6gIKRmlsZXN5c3RlbWIGcHJvdG8z",
[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, checkHealth) {
this.handleStop = handleStop;
this.events = events;
this.onEvent = onEvent;
this.onExit = onExit;
this.checkHealth = checkHealth;
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 yield new __await(handleRpcErrorWithHealthCheck(err, this.checkHealth));
}
});
}
async handleEvents() {
var _a3, _b, _c;
let iterationError;
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;
}
await ((_a3 = this.onEvent) == null ? void 0 : _a3.call(this, {
name: event.value.name,
type: eventType,
entry: event.value.entry ? mapEntryInfo(event.value.entry) : void 0
}));
}
} catch (temp) {
error = [temp];
} finally {
try {
more && (temp = iter.return) && await temp.call(iter);
} finally {
if (error)
throw error[0];
}
}
} catch (err) {
iterationError = err;
}
try {
if (iterationError) {
await ((_b = this.onExit) == null ? void 0 : _b.call(this, iterationError));
} else {
await ((_c = this.onExit) == null ? void 0 : _c.call(this));
}
} catch (e) {
} finally {
this.handleStop();
}
}
};
// src/sandbox/filesystem/index.ts
var import_compare_versions2 = require("compare-versions");
var FILESYSTEM_HTTP_ERROR_MAP = {
404: (message) => new FileNotFoundError(message)
};
var FILESYSTEM_RPC_ERROR_MAP = {
[import_connect3.Code.NotFound]: (message) => new FileNotFoundError(message)
};
async function handleFilesystemRpcError(err, checkHealth) {
return handleRpcErrorWithHealthCheck(
err,
checkHealth,
FILESYSTEM_RPC_ERROR_MAP
);
}
function handleFilesystemEnvdApiError(res) {
return handleEnvdApiError(res, FILESYSTEM_HTTP_ERROR_MAP);
}
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)
);
}
function mapMetadata(metadata) {
if (!metadata) return void 0;
return Object.keys(metadata).length === 0 ? void 0 : metadata;
}
var METADATA_HEADER_PREFIX = "X-Metadata-";
var METADATA_KEY_REGEX = /^[A-Za-z0-9!#$%&'*+\-.^_`|~]+$/;
var METADATA_VALUE_REGEX = /^[\x20-\x7e]*$/;
function validateMetadata(metadata) {
if (!metadata) return;
for (const [key, value] of Object.entries(metadata)) {
if (!METADATA_KEY_REGEX.test(key)) {
throw new InvalidArgumentError(
`Invalid metadata key ${JSON.stringify(
key
)}: keys must be non-empty and use only HTTP token characters (letters, digits and !#$%&'*+-.^_\`|~).`
);
}
if (!METADATA_VALUE_REGEX.test(value)) {
throw new InvalidArgumentError(
`Invalid metadata value for key ${JSON.stringify(
key
)}: values must be printable US-ASCII.`
);
}
}
}
function metadataHeaders(metadata) {
if (!metadata) return {};
const headers = {};
for (const [key, value] of Object.entries(metadata)) {
headers[`${METADATA_HEADER_PREFIX}${key}`] = value;
}
return headers;
}
function mapEntryInfo(entry) {
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,
metadata: mapMetadata(entry.metadata)
};
}
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);
this.checkHealth = () => checkSandboxHealth(this.envdApi);
}
async read(path2, opts) {
var _a3, _b, _c;
const format = (_a3 = opts == null ? void 0 : opts.format) != null ? _a3 : "text";
let user = opts == null ? void 0 : opts.user;
if (user == void 0 && (0, import_compare_versions2.compareVersions)(this.envdApi.version, ENVD_DEFAULT_USER) < 0) {
user = defaultUsername;
}
const headers = {};
if (opts == null ? void 0 : opts.gzip) {
headers["Accept-Encoding"] = "gzip";
}
if (format === "stream") {
const requestTimeoutMs = (_b = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _b : this.connectionConfig.requestTimeoutMs;
const { controller, clearStartTimeout, cleanup } = setupRequestController(
requestTimeoutMs,
opts == null ? void 0 : opts.signal
);
try {
const res2 = await this.envdApi.api.GET("/files", {
params: {
query: {
path: path2,
username: user
}
},
parseAs: "stream",
signal: controller.signal,
headers
}).catch(async (err3) => {
throw await handleEnvdApiFetchError(err3, this.checkHealth);
});
const err2 = await handleFilesystemEnvdApiError(res2);
if (err2) {
if (res2.response.body && !res2.response.bodyUsed) {
await res2.response.body.cancel().catch(() => {
});
}
cleanup();
throw err2;
}
return wrapStreamWithConnectionCleanup(
res2.data,
{
clearStartTimeout,
cleanup,
controller,
idleTimeoutMs: (_c = opts == null ? void 0 : opts.streamIdleTimeoutMs) != null ? _c : requestTimeoutMs
}
);
} catch (err2) {
cleanup();
throw err2;
}
}
const res = await this.envdApi.api.GET("/files", {
params: {
query: {
path: path2,
username: user
}
},
parseAs: format === "bytes" ? "arrayBuf