UNPKG

e2b

Version:

E2B SDK that give agents cloud environments

7,577 lines 298 kB
import createClient from "openapi-fetch";
import platform from "platform";
import { compareVersions } from "compare-versions";
import { Code, ConnectError, createClient as createClient$1 } from "@connectrpc/connect";
import { fileDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
import { createConnectTransport } from "@connectrpc/connect-web";
import fs from "node:fs";
import stream from "node:stream";
import chalk from "chalk";
import crypto$1 from "node:crypto";
import os from "node:os";
import path from "node:path";
import url from "node:url";
import { DockerfileParser } from "dockerfile-ast";
//#region package.json
var version = "2.45.0";
//#endregion
//#region src/is.ts
/**
* Class-agnostic checks for web platform objects.
*
* `value instanceof Blob` does not answer "is this a Blob", it answers "was
* this minted by *the* `Blob` class this module happens to see". In a Node
* process those are different questions: libraries replace the web globals the
* same way they replace `globalThis.fetch` — `@hono/node-server` installs its
* own `Request`, remix's `installGlobals()` swaps `Request`/`Blob`/`File`,
* `web-streams-polyfill` swaps `ReadableStream`, jsdom-based test environments
* bring their own copies of all of them — and values also cross realms
* (`node:vm`, `worker_threads`). A perfectly good Blob then fails that check —
* a *brand* check, in spec terms — and the SDK silently takes the wrong branch.
*
* The failure modes are not theoretical; each one is covered by a test:
* - a Request the current global class disowns is handed to undici verbatim and
*   every API call dies with `Failed to parse URL from [object Request]`;
* - a foreign `Blob` or `ReadableStream` body is stringified by the platform,
*   so the upload silently contains the text `[object Blob]`;
* - a foreign `ReadableStream` upload is buffered into memory instead of
*   streamed, or hangs when piped through `CompressionStream`;
* - a foreign `Blob` response body reads back as an empty file.
*
* So ask what a value *is*, not who made it: keep `instanceof` as the fast
* path, then fall back to the members and `Symbol.toStringTag` the platform
* guarantees. Detection is only half of it — see `toBlob`/`toUploadBody` in
* `utils.ts`, which convert what they detect into a native equivalent before
* handing it to the platform.
*/
function isObject(value) {
	return typeof value === "object" && value !== null;
}
/**
* The value's `Symbol.toStringTag`, e.g. `'Blob'` for anything implementing the
* `Blob` interface. Spec'd for every web platform interface and inherited by
* subclasses, so it survives both realm and class swaps. Same one-liner
* `@sindresorhus/is` uses for the types it covers (`Blob`, `ArrayBuffer`; it has
* no `Request` or `ReadableStream` check, which is why this module exists).
*/
function platformTag(value) {
	return Object.prototype.toString.call(value).slice(8, -1);
}
/**
* Whether `value` should be treated as a `Request`.
*
* Duck-typed on `url` + `method` + `clone` rather than on the tag, because
* older `fetch` ponyfills predate `Symbol.toStringTag`; `clone` is what
* separates a `Request` from other `{ url, method }` carriers such as Node's
* `IncomingMessage`.
*/
function isRequestLike(value) {
	return value instanceof Request || isObject(value) && typeof value.url === "string" && typeof value.method === "string" && typeof value.clone === "function";
}
/**
* Whether `value` should be treated as a `Blob` (or a `File`, which is a
* `Blob`).
*
* `arrayBuffer` is the only member required beyond the tag, because reading the
* bytes is all the SDK ever does with a Blob it didn't make — asking for
* `stream` too would turn implementations that lack it into corrupted uploads
* for no gain.
*/
function isBlobLike(value) {
	if (value instanceof Blob) return true;
	if (!isObject(value)) return false;
	const tag = platformTag(value);
	return (tag === "Blob" || tag === "File") && typeof value.arrayBuffer === "function";
}
/**
* Whether `value` should be treated as a `ReadableStream`.
*
* `getReader` + `tee` + `cancel` is unmistakable enough to skip the tag, which
* keeps this working for stream implementations that only got a
* `Symbol.toStringTag` in later versions.
*/
function isReadableStreamLike(value) {
	return value instanceof ReadableStream || isObject(value) && typeof value.getReader === "function" && typeof value.tee === "function" && typeof value.cancel === "function";
}
/**
* Whether `value` should be treated as an `ArrayBuffer`.
*
* Unlike the others this needs no conversion afterwards: the platform detects
* buffer sources through V8 rather than by brand, so a cross-realm
* `ArrayBuffer` is already accepted everywhere a native one is.
*/
function isArrayBufferLike(value) {
	return value instanceof ArrayBuffer || isObject(value) && platformTag(value) === "ArrayBuffer";
}
//#endregion
//#region src/utils.ts
function getRuntime() {
	var _navigator, _process;
	if (globalThis.Bun) return {
		runtime: "bun",
		version: globalThis.Bun.version
	};
	if (globalThis.Deno) return {
		runtime: "deno",
		version: globalThis.Deno.version.deno
	};
	if (typeof EdgeRuntime === "string") return {
		runtime: "vercel-edge",
		version: "unknown"
	};
	if (((_navigator = globalThis.navigator) === null || _navigator === void 0 ? void 0 : _navigator.userAgent) === "Cloudflare-Workers") return {
		runtime: "cloudflare-worker",
		version: "unknown"
	};
	if (((_process = globalThis.process) === null || _process === void 0 || (_process = _process.release) === null || _process === void 0 ? void 0 : _process.name) === "node") return {
		runtime: "node",
		version: platform.version || "unknown"
	};
	if (typeof window !== "undefined") return {
		runtime: "browser",
		version: platform.version || "unknown"
	};
	return {
		runtime: "unknown",
		version: "unknown"
	};
}
const { runtime, version: runtimeVersion } = getRuntime();
async function sha256(data) {
	const dataBuffer = new TextEncoder().encode(data);
	const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer);
	const hashArray = new Uint8Array(hashBuffer);
	return btoa(String.fromCharCode(...hashArray));
}
function timeoutToSeconds(timeout) {
	return Math.ceil(timeout / 1e3);
}
/**
* Import an optional, runtime-resolved package (e.g. `undici`, `glob`, `tar`)
* without letting downstream bundlers resolve it at build time.
*
* The variable specifier plus the `webpackIgnore`/`@vite-ignore` annotations
* keep the import opaque to bundlers, so browser/edge builds don't try to
* pull node-only packages into the bundle, while plain Node resolves it
* natively at runtime.
*/
async function dynamicImport(module) {
	if (runtime === "browser") throw new Error("Browser runtime is not supported for dynamic import");
	return await import(
		/* webpackIgnore: true */
		/* @vite-ignore */
		module
);
}
function ansiRegex({ onlyFirst = false } = {}) {
	return new RegExp(`(?:\\u001B[\\]PX^_][\\s\\S]*?(?:\\u0007|\\u001B\\u005C|\\u009C))|[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]`, onlyFirst ? void 0 : "g");
}
function stripAnsi(text) {
	return text.replace(ansiRegex(), "");
}
/**
* Adopt a stream from a polyfill, a replaced global, or another realm into the
* current `ReadableStream` class by pumping it through a new one. Reading
* through the public reader is the portable part of a stream.
*
* Needed wherever the stream is handed to another platform primitive that
* brand-checks it — `pipeThrough(new CompressionStream(…))` on a foreign stream
* never settles.
*/
function toNativeStream(stream) {
	if (stream instanceof ReadableStream) return stream;
	const reader = stream.getReader();
	return new ReadableStream({
		async pull(controller) {
			const { done, value } = await reader.read();
			if (done) {
				controller.close();
				return;
			}
			controller.enqueue(value);
		},
		cancel(reason) {
			return reader.cancel(reason);
		}
	});
}
/**
* Adopt a stream only if the platform would not accept it as a request body —
* handed one it doesn't accept, it stringifies it to
* `"[object ReadableStream]"`.
*
* Two kinds are accepted: the platform's own stream class, and any async
* iterable. Async iterability is the half that survives a replaced global — a
* native stream stays async-iterable even when `globalThis.ReadableStream` is a
* polyfill — so re-wrapping one of those would only trade a stream the platform
* accepts for one it may not.
*/
function toDispatchableStream(stream) {
	return stream instanceof ReadableStream || Symbol.asyncIterator in stream ? stream : toNativeStream(stream);
}
/**
* Convert data to a Blob, avoiding unnecessary conversions when possible.
*/
async function toBlob(data) {
	if (data instanceof Blob) return data;
	if (isBlobLike(data)) return new Blob([await data.arrayBuffer()], { type: data.type });
	if (isReadableStreamLike(data)) return new Response(toDispatchableStream(data)).blob();
	return new Blob([data]);
}
const UNSAFE_SHELL_CHAR = /[^\w@%+=:,./-]/;
/**
* Quote a string for safe interpolation into a POSIX shell command.
*
* Faithful port of Python's `shlex.quote`: an empty string becomes `''`,
* values containing only safe characters are returned unchanged (keeping
* generated commands stable and cache-friendly), and anything else is wrapped
* in single quotes with embedded single quotes escaped as `'"'"'`.
*/
function shellQuote(s) {
	if (s === "") return "''";
	if (!UNSAFE_SHELL_CHAR.test(s)) return s;
	return "'" + s.replace(/'/g, "'\"'\"'") + "'";
}
/**
* Prepare data for upload, optionally gzip-compressed.
*
* Outside the browser, streams (and gzip-compressed data) are uploaded as a
* `ReadableStream` so they don't have to be buffered in memory. Browsers don't
* support streaming request bodies, so data is buffered into a Blob there.
*/
async function toUploadBody(data, gzip) {
	if (gzip) {
		const compressed = (isReadableStreamLike(data) ? toNativeStream(data) : (await toBlob(data)).stream()).pipeThrough(new CompressionStream("gzip"));
		return runtime === "browser" ? {
			body: await new Response(compressed).blob(),
			streamed: false
		} : {
			body: compressed,
			streamed: true
		};
	}
	if (isReadableStreamLike(data) && runtime !== "browser") return {
		body: toDispatchableStream(data),
		streamed: true
	};
	return {
		body: await toBlob(data),
		streamed: false
	};
}
//#endregion
//#region src/api/metadata.ts
var _platform$os;
const defaultHeaders = {
	browser: typeof window !== "undefined" && platform.name || "unknown",
	lang: "js",
	lang_version: runtimeVersion,
	package_version: version,
	publisher: "e2b",
	sdk_runtime: runtime,
	system: ((_platform$os = platform.os) === null || _platform$os === void 0 ? void 0 : _platform$os.family) || "unknown"
};
function getEnvVar(name) {
	if (runtime === "deno") return Deno.env.get(name);
	if (typeof process === "undefined") return "";
	return process.env[name];
}
/**
* Parse an env var as a base-10 integer, falling back to `defaultValue` when
* the env var is unset. Throws on non-integer input rather than silently
* falling back so misconfiguration is surfaced loudly.
*/
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;
}
/**
* Parse an env var that must be a positive integer (>= 1). Throws on
* non-positive or non-integer input.
*/
function parsePositiveIntEnv(name, defaultValue) {
	const parsed = parseIntEnv(name, defaultValue);
	if (parsed < 1) throw new Error(`Invalid ${name}=${parsed}: expected a positive integer.`);
	return parsed;
}
/**
* Parse an inflight-limit env var. Returns `0` to disable the cap (documented
* opt-out) or a positive integer to cap concurrency. Throws on non-integer or
* negative values so misconfiguration is surfaced loudly rather than silently
* removing the cap. A return value of `0` is recognized by
* {@link limitConcurrency} as "no cap".
*/
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;
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/typeof.js
function _typeof(o) {
	"@babel/helpers - typeof";
	return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
		return typeof o;
	} : function(o) {
		return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
	}, _typeof(o);
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/toPrimitive.js
function toPrimitive(t, r) {
	if ("object" != _typeof(t) || !t) return t;
	var e = t[Symbol.toPrimitive];
	if (void 0 !== e) {
		var i = e.call(t, r || "default");
		if ("object" != _typeof(i)) return i;
		throw new TypeError("@@toPrimitive must return a primitive value.");
	}
	return ("string" === r ? String : Number)(t);
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/toPropertyKey.js
function toPropertyKey(t) {
	var i = toPrimitive(t, "string");
	return "symbol" == _typeof(i) ? i : i + "";
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/defineProperty.js
function _defineProperty(e, r, t) {
	return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
		value: t,
		enumerable: !0,
		configurable: !0,
		writable: !0
	}) : e[r] = t, e;
}
//#endregion
//#region src/api/inflight.ts
/**
* Simple FIFO semaphore used to cap the number of in-flight requests sent
* through a fetch dispatcher.
*/
var Semaphore = class {
	constructor(max) {
		this.max = max;
		_defineProperty(this, "active", 0);
		_defineProperty(this, "queue", []);
	}
	async acquire(signal) {
		var _this = this;
		if (signal === null || signal === void 0 ? 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 || signal === 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 || signal === void 0 || signal.addEventListener("abort", onAbort, { once: true });
		});
	}
	release() {
		this.active--;
		const next = this.queue.shift();
		if (next) next();
	}
};
function abortReason(signal) {
	var _signal$reason;
	return (_signal$reason = signal === null || signal === void 0 ? void 0 : signal.reason) !== null && _signal$reason !== void 0 ? _signal$reason : new DOMException("Aborted", "AbortError");
}
/**
* Wrap `fetcher` so at most `max` requests are in-flight at any time.
* Subsequent requests are FIFO-queued inside the SDK process and dispatched
* as earlier requests settle.
*
* NOTE: the slot is released as soon as `fetcher` resolves with the response
* headers, not when the response body is fully consumed. This means the
* effective concurrency can be higher than `max` while bodies are
* still streaming.
*
* TODO: release on body end (consume/cancel/error) so the
* SDK-level cap aligns with the dispatcher's connection accounting
*/
function limitConcurrency(fetcher, max) {
	if (!Number.isFinite(max) || max <= 0) return fetcher;
	const sem = new Semaphore(max);
	return (async (input, init) => {
		var _init$signal;
		const signal = (_init$signal = init === null || init === void 0 ? void 0 : init.signal) !== null && _init$signal !== void 0 ? _init$signal : isRequestLike(input) ? input.signal : void 0;
		const release = await sem.acquire(signal);
		try {
			return await fetcher(input, init);
		} finally {
			release();
		}
	});
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectSpread2.js
function ownKeys(e, r) {
	var t = Object.keys(e);
	if (Object.getOwnPropertySymbols) {
		var o = Object.getOwnPropertySymbols(e);
		r && (o = o.filter(function(r) {
			return Object.getOwnPropertyDescriptor(e, r).enumerable;
		})), t.push.apply(t, o);
	}
	return t;
}
function _objectSpread2(e) {
	for (var r = 1; r < arguments.length; r++) {
		var t = null != arguments[r] ? arguments[r] : {};
		r % 2 ? ownKeys(Object(t), !0).forEach(function(r) {
			_defineProperty(e, r, t[r]);
		}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r) {
			Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
		});
	}
	return e;
}
//#endregion
//#region src/undici.ts
const UNDICI_8_MIN_NODE = "22.19.0";
function getUndiciPackageCandidates(nodeVersion) {
	if (compareVersions(nodeVersion, UNDICI_8_MIN_NODE) >= 0) return ["undici8", "undici"];
	return ["undici"];
}
async function loadUndici() {
	for (const packageName of getUndiciPackageCandidates(process.versions.node)) try {
		return await dynamicImport(packageName);
	} catch (_unused) {}
}
/**
* Late-bind the global fetch: runtimes and tools (msw, instrumentation) may
* replace `globalThis.fetch` after the SDK builds a fetcher. A factory rather
* than a shared const so per-proxy cache entries stay distinct closures.
*/
function lateBoundGlobalFetch() {
	return ((input, init) => globalThis.fetch(input, init));
}
/**
* Create a fetch for the given runtime. Outside Node it late-binds the global
* fetch. On Node it lazily runs `build` on the first request and caches the
* built fetcher; a failed build is not cached, so the next request retries
* instead of replaying the same stale rejection forever.
*/
function createRuntimeFetch(currentRuntime, build) {
	if (currentRuntime !== "node") return lateBoundGlobalFetch();
	let fetcherPromise;
	return (async (input, init) => {
		var _fetcherPromise;
		const promise = (_fetcherPromise = fetcherPromise) !== null && _fetcherPromise !== void 0 ? _fetcherPromise : fetcherPromise = build();
		let fetcher;
		try {
			fetcher = await promise;
		} catch (err) {
			if (fetcherPromise === promise) fetcherPromise = void 0;
			throw err;
		}
		return fetcher(input, init);
	});
}
/**
* Build a fetch bound to a bounded undici dispatcher (HTTP/2 enabled,
* `connections` origin connections, optional proxy tunnel), capped at
* `inflightLimit` in-flight requests (`0` disables the cap). Falls back to
* the global fetch — still capped — when undici cannot be loaded.
*/
async function buildDispatchedFetch(options) {
	var _options$loadUndici;
	const undici = await ((_options$loadUndici = options.loadUndici) !== null && _options$loadUndici !== void 0 ? _options$loadUndici : loadUndici)();
	if (!undici) return limitConcurrency(lateBoundGlobalFetch(), options.inflightLimit);
	const { Agent, ProxyAgent, fetch: undiciFetch } = undici;
	const dispatcher = options.proxy ? new ProxyAgent({
		uri: options.proxy,
		allowH2: true,
		connections: options.connections,
		proxyTunnel: true
	}) : new Agent({
		allowH2: true,
		connections: options.connections
	});
	const fetchWithDispatcher = undiciFetch;
	const wrapped = ((input, init) => {
		const request = toUndiciRequestInput(input, init);
		return fetchWithDispatcher(request.input, _objectSpread2(_objectSpread2({}, request.init), {}, { dispatcher }));
	});
	return limitConcurrency(wrapped, options.inflightLimit);
}
function toUndiciRequestInput(input, init) {
	if (!isRequestLike(input)) return {
		input,
		init
	};
	const requestInit = _objectSpread2({
		body: isReadableStreamLike(input.body) ? toDispatchableStream(input.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
	};
}
//#endregion
//#region src/api/http2.ts
const DEFAULT_API_CONNECTION_LIMIT = 100;
const DEFAULT_API_INFLIGHT_LIMIT = 1e3;
const apiFetchers = /* @__PURE__ */ new Map();
function createApiFetch(proxy) {
	const key = proxy !== null && proxy !== void 0 ? 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 = {}) {
	return createRuntimeFetch(currentRuntime, () => {
		var _options$connectionLi, _options$inflightLimi;
		return buildDispatchedFetch({
			connections: (_options$connectionLi = options.connectionLimit) !== null && _options$connectionLi !== void 0 ? _options$connectionLi : getApiConnectionLimit(),
			inflightLimit: (_options$inflightLimi = options.inflightLimit) !== null && _options$inflightLimi !== void 0 ? _options$inflightLimi : getApiInflightLimit(),
			proxy: options.proxy,
			loadUndici: options.loadUndici
		});
	});
}
function getApiConnectionLimit() {
	return parsePositiveIntEnv("E2B_API_CONNECTIONS", DEFAULT_API_CONNECTION_LIMIT);
}
/**
* Returns the configured max number of API requests that can be in flight at
* once, or `0` to disable the cap.
*
* Defaults to `1000` ({@link DEFAULT_API_INFLIGHT_LIMIT}). Override via
* `E2B_API_INFLIGHT_REQUESTS` env var; set to `0` to disable the cap entirely.
*/
function getApiInflightLimit() {
	return parseInflightLimitEnv("E2B_API_INFLIGHT_REQUESTS", DEFAULT_API_INFLIGHT_LIMIT);
}
//#endregion
//#region 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.`);
}
/**
* Base class for all sandbox errors.
*
* Thrown when general sandbox errors occur.
*/
var SandboxError = class extends Error {
	constructor(message) {
		super(message);
		this.name = "SandboxError";
	}
};
/**
* Thrown when a timeout error occurs.
*
* The [unavailable] error type is caused by sandbox timeout.
*
* The [canceled] error type is caused by exceeding request timeout.
*
* The [deadline_exceeded] error type is caused by exceeding the timeout for command execution, watch, etc.
*
* The [unknown] error type is sometimes caused by the sandbox timeout when the request is not processed correctly.
*/
var TimeoutError = class extends SandboxError {
	constructor(message) {
		super(message);
		this.name = "TimeoutError";
	}
};
/**
* Thrown when an invalid argument is provided.
*/
var InvalidArgumentError = class extends SandboxError {
	constructor(message, stackTrace) {
		super(message);
		this.name = "InvalidArgumentError";
		if (stackTrace) this.stack = stackTrace;
	}
};
/**
* Thrown when there is not enough disk space.
*/
var NotEnoughSpaceError = class extends SandboxError {
	constructor(message) {
		super(message);
		this.name = "NotEnoughSpaceError";
	}
};
/**
* Thrown when a resource is not found.
*
* @deprecated Use {@link FileNotFoundError} or {@link SandboxNotFoundError} instead. This class will be removed in the next major version.
*/
var NotFoundError = class extends SandboxError {
	constructor(message) {
		super(message);
		this.name = "NotFoundError";
	}
};
/**
* Thrown when a file or directory is not found inside a sandbox.
*/
var FileNotFoundError = class extends NotFoundError {
	constructor(message) {
		super(message);
		this.name = "FileNotFoundError";
	}
};
/**
* Thrown when a sandbox is not found (e.g. it doesn't exist or is no longer running).
*/
var SandboxNotFoundError = class extends NotFoundError {
	constructor(message) {
		super(message);
		this.name = "SandboxNotFoundError";
	}
};
/**
* Thrown when authentication fails.
*/
var AuthenticationError = class extends Error {
	constructor(message) {
		super(message);
		this.name = "AuthenticationError";
	}
};
/**
* Thrown when git authentication fails.
*/
var GitAuthError = class extends AuthenticationError {
	constructor(message) {
		super(message);
		this.name = "GitAuthError";
	}
};
/**
* Thrown when git upstream tracking is missing.
*/
var GitUpstreamError = class extends SandboxError {
	constructor(message) {
		super(message);
		this.name = "GitUpstreamError";
	}
};
/**
* Thrown when the template uses old envd version. It isn't compatible with the new SDK.
*/
var TemplateError = class extends SandboxError {
	constructor(message, stackTrace) {
		super(message);
		this.name = "TemplateError";
		if (stackTrace) this.stack = stackTrace;
	}
};
/**
* Thrown when the API rate limit is exceeded.
*/
var RateLimitError = class extends SandboxError {
	constructor(message) {
		super(message);
		this.name = "RateLimitError";
	}
};
/**
* Thrown when the build fails.
*/
var BuildError = class extends Error {
	constructor(message, stackTrace) {
		super(message);
		this.name = "BuildError";
		if (stackTrace) this.stack = stackTrace;
	}
};
/**
* Thrown when the file upload fails.
*/
var FileUploadError = class extends BuildError {
	constructor(message, stackTrace) {
		super(message, stackTrace);
		this.name = "FileUploadError";
	}
};
/**
* Base class for all volume errors.
*
* Thrown when general volume errors occur.
*/
var VolumeError = class extends Error {
	constructor(message) {
		super(message);
		this.name = "VolumeError";
	}
};
/**
* Thrown when a volume is not found.
*/
var VolumeNotFoundError = class extends VolumeError {
	constructor(message) {
		super(message);
		this.name = "VolumeNotFoundError";
	}
};
/**
* Thrown when a file or directory is not found inside a volume.
*/
var VolumePathNotFoundError = class extends VolumeError {
	constructor(message) {
		super(message);
		this.name = "VolumePathNotFoundError";
	}
};
/**
* Base class for all secret errors.
*
* Thrown when general secret errors occur.
*/
var SecretError = class extends Error {
	constructor(message) {
		super(message);
		this.name = "SecretError";
	}
};
/**
* Thrown when a secret is not found.
*/
var SecretNotFoundError = class extends SecretError {
	constructor(message) {
		super(message);
		this.name = "SecretNotFoundError";
	}
};
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/asyncIterator.js
function _asyncIterator(r) {
	var n, t, o, e = 2;
	for ("undefined" != typeof Symbol && (t = Symbol.asyncIterator, o = Symbol.iterator); e--;) {
		if (t && null != (n = r[t])) return n.call(r);
		if (o && null != (n = r[o])) return new AsyncFromSyncIterator(n.call(r));
		t = "@@asyncIterator", o = "@@iterator";
	}
	throw new TypeError("Object is not async iterable");
}
function AsyncFromSyncIterator(r) {
	function AsyncFromSyncIteratorContinuation(r) {
		if (Object(r) !== r) return Promise.reject(/* @__PURE__ */ new TypeError(r + " is not an object."));
		var n = r.done;
		return Promise.resolve(r.value).then(function(r) {
			return {
				value: r,
				done: n
			};
		});
	}
	return AsyncFromSyncIterator = function AsyncFromSyncIterator(r) {
		this.s = r, this.n = r.next;
	}, AsyncFromSyncIterator.prototype = {
		s: null,
		n: null,
		next: function next() {
			return AsyncFromSyncIteratorContinuation(this.n.apply(this.s, arguments));
		},
		"return": function _return(r) {
			var n = this.s["return"];
			return void 0 === n ? Promise.resolve({
				value: r,
				done: !0
			}) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
		},
		"throw": function _throw(r) {
			var n = this.s["return"];
			return void 0 === n ? Promise.reject(r) : AsyncFromSyncIteratorContinuation(n.apply(this.s, arguments));
		}
	}, new AsyncFromSyncIterator(r);
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/OverloadYield.js
function _OverloadYield(e, d) {
	this.v = e, this.k = d;
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/awaitAsyncGenerator.js
function _awaitAsyncGenerator(e) {
	return new _OverloadYield(e, 0);
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/wrapAsyncGenerator.js
function _wrapAsyncGenerator(e) {
	return function() {
		return new AsyncGenerator(e.apply(this, arguments));
	};
}
function AsyncGenerator(e) {
	var r, t;
	function resume(r, t) {
		try {
			var n = e[r](t), o = n.value, u = o instanceof _OverloadYield;
			Promise.resolve(u ? o.v : o).then(function(t) {
				if (u) {
					var i = "return" === r ? "return" : "next";
					if (!o.k || t.done) return resume(i, t);
					t = e[i](t).value;
				}
				settle(n.done ? "return" : "normal", t);
			}, function(e) {
				resume("throw", e);
			});
		} catch (e) {
			settle("throw", e);
		}
	}
	function settle(e, n) {
		switch (e) {
			case "return":
				r.resolve({
					value: n,
					done: !0
				});
				break;
			case "throw":
				r.reject(n);
				break;
			default: r.resolve({
				value: n,
				done: !1
			});
		}
		(r = r.next) ? resume(r.key, r.arg) : t = null;
	}
	this._invoke = function(e, n) {
		return new Promise(function(o, u) {
			var i = {
				key: e,
				arg: n,
				resolve: o,
				reject: u,
				next: null
			};
			t ? t = t.next = i : (r = t = i, resume(e, n));
		});
	}, "function" != typeof e["return"] && (this["return"] = void 0);
}
AsyncGenerator.prototype["function" == typeof Symbol && Symbol.asyncIterator || "@@asyncIterator"] = function() {
	return this;
}, AsyncGenerator.prototype.next = function(e) {
	return this._invoke("next", e);
}, AsyncGenerator.prototype["throw"] = function(e) {
	return this._invoke("throw", e);
}, AsyncGenerator.prototype["return"] = function(e) {
	return this._invoke("return", e);
};
//#endregion
//#region src/logs.ts
function formatLog(log) {
	return JSON.parse(JSON.stringify(log, (_, value) => typeof value === "bigint" ? value.toString() : value));
}
function createRpcLogger(logger) {
	function logEach(_x) {
		return _logEach.apply(this, arguments);
	}
	function _logEach() {
		_logEach = _wrapAsyncGenerator(function* (stream) {
			var _iteratorAbruptCompletion = false;
			var _didIteratorError = false;
			var _iteratorError;
			try {
				for (var _iterator = _asyncIterator(stream), _step; _iteratorAbruptCompletion = !(_step = yield _awaitAsyncGenerator(_iterator.next())).done; _iteratorAbruptCompletion = false) {
					const m = _step.value;
					var _logger$debug;
					(_logger$debug = logger.debug) === null || _logger$debug === void 0 || _logger$debug.call(logger, "Response stream:", formatLog(m));
					yield m;
				}
			} catch (err) {
				_didIteratorError = true;
				_iteratorError = err;
			} finally {
				try {
					if (_iteratorAbruptCompletion && _iterator.return != null) yield _awaitAsyncGenerator(_iterator.return());
				} finally {
					if (_didIteratorError) throw _iteratorError;
				}
			}
		});
		return _logEach.apply(this, arguments);
	}
	return (next) => async (req) => {
		var _logger$info;
		(_logger$info = logger.info) === null || _logger$info === void 0 || _logger$info.call(logger, `Request: POST ${req.url}`);
		const res = await next(req);
		if (res.stream) return _objectSpread2(_objectSpread2({}, res), {}, { message: logEach(res.message) });
		else {
			var _logger$info2;
			(_logger$info2 = logger.info) === null || _logger$info2 === void 0 || _logger$info2.call(logger, "Response:", formatLog(res.message));
		}
		return res;
	};
}
function createApiLogger(logger) {
	return {
		async onRequest({ request }) {
			var _logger$info3;
			(_logger$info3 = logger.info) === null || _logger$info3 === void 0 || _logger$info3.call(logger, `Request ${request.method} ${request.url}`);
			return request;
		},
		async onResponse({ response }) {
			if (response.status >= 400) {
				var _logger$error;
				(_logger$error = logger.error) === null || _logger$error === void 0 || _logger$error.call(logger, "Response:", response.status, response.statusText);
			} else {
				var _logger$info4;
				(_logger$info4 = logger.info) === null || _logger$info4 === void 0 || _logger$info4.call(logger, "Response:", response.status, response.statusText);
			}
			return response;
		}
	};
}
//#endregion
//#region src/api/index.ts
const API_KEY_PATTERN = /^e2b_[0-9a-f]+$/;
const API_KEY_EXAMPLE = `e2b_${"0".repeat(40)}`;
/**
* Validates that an E2B API key has the expected `e2b_` prefix followed by
* hex characters. Throws `AuthenticationError` otherwise.
*/
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.`);
}
/**
* Map an API error code and message to the matching error class — the same
* mapping {@link handleApiError} applies to HTTP responses, usable for error
* objects embedded in response bodies (e.g. per-fork results).
*/
function apiErrorFromCode(code, content, errorClass = SandboxError, stackTrace) {
	if (code === 401) {
		const message = "Unauthorized, please check your credentials.";
		return new AuthenticationError(content ? `${message} - ${content}` : message);
	}
	if (code === 429) {
		const message = "Rate limit exceeded, please try again later";
		return new RateLimitError(content ? `${message} - ${content}` : message);
	}
	return new errorClass(`${code}: ${content}`, stackTrace);
}
function handleApiError(response, errorClass = SandboxError, stackTrace) {
	var _response$error2;
	if (response.response.ok) return;
	const status = response.response.status;
	if (status === 401 || status === 429) {
		var _response$error$messa, _response$error;
		return apiErrorFromCode(status, (_response$error$messa = (_response$error = response.error) === null || _response$error === void 0 ? void 0 : _response$error.message) !== null && _response$error$messa !== void 0 ? _response$error$messa : response.error, errorClass, stackTrace);
	}
	return apiErrorFromCode(status, ((_response$error2 = response.error) === null || _response$error2 === void 0 ? void 0 : _response$error2.message) || response.error || response.response.statusText, errorClass, stackTrace);
}
/**
* Client for interacting with the E2B API.
*/
var ApiClient = class {
	constructor(config, opts = {}) {
		var _opts$requireApiKey;
		_defineProperty(this, "api", void 0);
		if (((_opts$requireApiKey = opts.requireApiKey) !== null && _opts$requireApiKey !== void 0 ? _opts$requireApiKey : 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 = createClient({
			baseUrl: config.apiUrl,
			fetch: createApiFetch(config.proxy),
			headers: _objectSpread2(_objectSpread2(_objectSpread2({}, defaultHeaders), config.apiKey && { "X-API-KEY": config.apiKey }), config.headers),
			querySerializer: { array: {
				style: "form",
				explode: false
			} }
		});
		if (config.logger) this.api.use(createApiLogger(config.logger));
	}
};
//#endregion
//#region src/connectionConfig.ts
const supportedDomains = [
	"e2b.app",
	"e2b.dev",
	"e2b.pro",
	"e2b-staging.dev"
];
const REQUEST_TIMEOUT_MS$1 = 6e4;
const DEFAULT_SANDBOX_TIMEOUT_MS = 3e5;
const KEEPALIVE_PING_HEADER = "Keepalive-Ping-Interval";
/**
* Build an `AbortSignal` that combines an optional request-timeout signal
* (via `AbortSignal.timeout`) with an optional user-provided signal.
*
* Returns `undefined` when neither input would produce a signal.
*
* @internal
*/
function buildRequestSignal(requestTimeoutMs, userSignal) {
	const timeoutSignal = requestTimeoutMs ? AbortSignal.timeout(requestTimeoutMs) : void 0;
	if (timeoutSignal && userSignal) return AbortSignal.any([timeoutSignal, userSignal]);
	return timeoutSignal !== null && timeoutSignal !== void 0 ? timeoutSignal : userSignal;
}
/**
* Set up an internal `AbortController` for a streaming request.
*
* Until `clearStartTimeout` is called, the controller aborts when either
*  - the optional user signal aborts, or
*  - the optional request timeout elapses (used to bound the initial
*    handshake; long-lived streams should call `clearStartTimeout` once
*    the handshake succeeds).
*
* The user-signal listener stays attached for the full stream lifetime
* so the caller can cancel a long-running stream by aborting the signal.
*
* `cleanup` is idempotent and detaches the listener, clears the handshake
* timer (if still pending), and aborts the controller. Call it when the
* stream finishes or when startup fails.
*
* @internal
*/
function setupRequestController(requestTimeoutMs, userSignal) {
	const controller = new AbortController();
	const onUserAbort = () => abortWithReason(controller, userSignal === null || userSignal === void 0 ? void 0 : userSignal.reason);
	if (userSignal) if (userSignal.aborted) abortWithReason(controller, userSignal.reason);
	else userSignal.addEventListener("abort", onUserAbort, { once: true });
	let reqTimeout = requestTimeoutMs ? setTimeout(() => abortWithReason(controller, 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 || userSignal === void 0 || userSignal.removeEventListener("abort", onUserAbort);
		clearStartTimeout();
		controller.abort();
	};
	return {
		controller,
		clearStartTimeout,
		cleanup
	};
}
/**
* Create a resettable idle-timeout that aborts `controller` when no progress is
* made within `idleTimeoutMs`. `arm` (re)starts the timer; call it on each
* chunk. `clear` stops it. `0`/`undefined` disables it (both are no-ops).
*
* @internal
*/
function createIdleAbort(controller, idleTimeoutMs, label) {
	let timer;
	const clear = () => {
		if (timer) {
			clearTimeout(timer);
			timer = void 0;
		}
	};
	const arm = () => {
		if (!idleTimeoutMs) return;
		clear();
		timer = setTimeout(() => abortWithReason(controller, new DOMException(`${label} idle for ${idleTimeoutMs}ms`, "TimeoutError")), idleTimeoutMs);
	};
	return {
		arm,
		clear
	};
}
/**
* Abort with the reason pinned to the controller. Bun (observed on 1.3.14)
* holds `signal.reason` weakly: a reason that nothing else strongly
* references — e.g. a `DOMException` constructed inside a timer callback —
* can be garbage-collected, leaving `signal.reason` undefined by the time a
* consumer reads it. Pinning the reason to the controller keeps it alive for
* the signal's lifetime. No-op cost on other runtimes.
*
* @internal
*/
function abortWithReason(controller, reason) {
	if (controller.signal.aborted) return;
	controller.__e2bAbortReason = reason;
	controller.abort(reason);
}
/**
* Wrap a streaming response body so its pooled connection is released when the
* stream is fully read, cancelled, errors, or stays idle for too long.
*
* Clears the handshake timeout from {@link setupRequestController} (so
* consuming the body isn't killed by it) and replaces it with an idle-read
* timeout that bounds only the wire: it's armed while waiting on a network
* read and cleared the moment a chunk arrives, so a slow or paused consumer
* never trips it (only a server that stops sending mid-stream does). On expiry
* it aborts `controller`, tearing down the fetch and releasing the connection.
* Pass `0`/`undefined` to disable. Call once the handshake has succeeded.
*
* @internal
*/
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");
	let released = false;
	const release = () => {
		if (released) return;
		released = true;
		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();
			}
		}
	});
}
/**
* Configuration for connecting to the API.
*/
var ConnectionConfig = class ConnectionConfig {
	static buildUserAgent() {
		const userAgentParts = [`${ConnectionConfig.sdkUserAgentPrefix}${version}`];
		if (ConnectionConfig.integration) userAgentParts.push(ConnectionConfig.integration);
		return userAgentParts.join(" ");
	}
	/**
	* Set the `User-Agent` on `headers`: an explicitly provided value always
	* wins; otherwise the SDK-built one, tagged with the current integration.
	*
	* An SDK-built value carried over from an earlier config (configs are
	* rebuilt via `new ConnectionConfig({ ...config })`) is recognized by its
	* prefix and rebuilt, so it stays in sync with the current integration.
	*/
	static applyUserAgent(headers) {
		const userAgent = headers["User-Agent"];
		if (userAgent !== void 0 && !userAgent.startsWith(ConnectionConfig.sdkUserAgentPrefix)) return;
		headers["User-Agent"] = ConnectionConfig.buildUserAgent();
	}
	/**
	* Identify traffic from an integration wrapping the E2B SDK by appending
	* `integration` (e.g. `'e2b-code-interpreter/0.1.0'`) to the `User-Agent`
	* header of every request.
	*
	* Call once at startup, before any `ConnectionConfig` is constructed —
	* configs read the value at construction time. Pass `undefined` to clear.
	*
	* @internal
	* @hidden
	* @hide
	*/
	static setIntegration(integration) {
		ConnectionConfig.integration = integration;
	}
	constructor(opts) {
		var _opts$validateApiKey, _opts$debug, _opts$requestTimeoutM, _opts$headers, _opts$apiHeaders;
		_defineProperty(this, "debug", void 0);
		_defineProperty(this, "domain", void 0);
		_defineProperty(this, "apiUrl", void 0);
		_defineProperty(this, "sandboxUrl", void 0);
		_defineProperty(this, "logger", void 0);
		_defineProperty(this, "requestTimeoutMs", void 0);
		_defineProperty(this, "apiKey", void 0);
		_defineProperty(this, "validateApiKey", void 0);
		_defineProperty(this, "headers", void 0);
		_defineProperty(this, "proxy", void 0);
		this.apiKey = (opts === null || opts === void 0 ? void 0 : opts.apiKey) || ConnectionConfig.apiKey;
		this.validateApiKey = (_opts$validateApiKey = opts === null || opts === void 0 ? void 0 : opts.validateApiKey) !== null && _opts$validateApiKey !== void 0 ? _opts$validateApiKey : ConnectionConfig.validateApiKey;
		this.debug = (_opts$debug = opts === null || opts === void 0 ? void 0 : opts.debug) !== null && _opts$debug !== void 0 ? _opts$debug : ConnectionConfig.debug;
		this.domain = (opts === null || opts === void 0 ? void 0 : opts.domain) || ConnectionConfig.domain;
		this.requestTimeoutMs = (_opts$requestTimeoutM = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM !== void 0 ? _opts$requestTimeoutM : REQUEST_TIMEOUT_MS$1;
		this.logger = opts === null || opts === void 0 ? void 0 : opts.logger;
		this.headers = _objectSpread2(_objectSpread2({}, (_opts$headers = opts === null || opts === void 0 ? void 0 : opts.headers) !== null && _opts$headers !== void 0 ? _opts$headers : {}), (_opts$apiHeaders = opts === null || opts === void 0 ? void 0 : opts.apiHeaders) !== null && _opts$apiHeaders !== void 0 ? _opts$apiHeaders : {});
		ConnectionConfig.applyUserAgent(this.headers);
		this.proxy = opts === null || opts === void 0 ? void 0 : opts.proxy;
		this.apiUrl = (opts === null || opts === void 0 ? void 0 : opts.apiUrl) || ConnectionConfig.apiUrl || (this.debug ? "http://localhost:3000" : `https://api.${this.domain}`);
		this.sandboxUrl = (opts === null || opts === void 0 ? void 0 : opts.sandboxUrl) || ConnectionConfig.sandboxUrl;
	}
	/**
	* Merge connection options bound to a class (e.g. by an `E2B` client) with
	* the per-call options. Per-call options win, then the bound options, then
	* the environment variables resolved by the `ConnectionConfig` constructor.
	*
	* Explicitly `undefined` per-call values are dropped so they fall back to the
	* bound options instead of clearing them.
	*
	* @internal
	* @hidden
	* @hide
	*/
	static mergeOpts(boundOpts, opts) {
		if (!boundOpts) return opts;
		const merged = _objectSpread2({}, boundOpts);
		for (const [key, value] of Object.entries(opts !== null && opts !== void 0 ? opts : {})) if (value !== void 0) Object.defineProperty(merged, key, {
			value,
			enumerable: true,
			writable: true,
			configurable: true
		});
		return merged;
	}
	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";
	}
	getSignal(requestTimeoutMs, signal) {
		return buildRequestSignal(requestTimeoutMs !== null && requestTimeoutMs !== void 0 ? requestTimeoutMs : this.requestTimeoutMs, signal);
	}
	getSandboxUrl(sandboxId, opts) {
		var _opts$sandboxDomain;
		if (this.sandboxUrl) return this.sandboxUrl;
		if (this.debug) return `http://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`;
		const sandboxDomain = (_opts$sandboxDomain = opts.sandboxDomain) !== null && _opts$sandboxDomain !== void 0 ? _opts$sandboxDomain : 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 !== void 0 ? sandboxDomain : this.domain}`;
	}
};
_defineProperty(ConnectionConfig, "envdPort", 49983);
_defineProperty(ConnectionConfig, "integration", void 0);
_defineProperty(ConnectionConfig, "sdkUserAgentPrefix", "e2b-js-sdk/");
/**
* Base class for the resource classes (`Sandbox`, `Volume`, `Template`,
* `Secret`) whose static methods build a `ConnectionConfig` from per-call
* options. An {@link E2B} client exposes subclasses of these with its own
* options bound, and every static method resolves them through
* {@link ClientFactory.resolveOpts}.
*
* @internal
* @hidden
* @hide
*/
var ClientFactory = class {
	/**
	* Merge the connection options bound to this class with the per-call options,
	* with the per-call options taking precedence.
	*
	* @internal
	* @hidden
	* @hide
	*/
	static resolveOpts(opts) {
		return ConnectionConfig.mergeOpts(this.boundOpts, opts);
	}
};
_defineProperty(ClientFactory, "boundOpts", void 0);
/**
* User used for the operation in the sandbox.
*/
const defaultUsername = "user";
//#endregion
//#region 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 != null ? Math.floor(Date.now() / 1e3) + expirationInSeconds : null;
	let signatureRaw;
	if (user == void 0) user = "";
	if (signatureExpiration === null) signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}`;
	else signatureRaw = `${path}:${operation}:${user}:${envdAccessToken}:${signatureExpiration.toString()}`;
	return {
		signature: "v1_" + (await sha256(signatureRaw)).replace(/=+$/, ""),
		expiration: signatureExpiration
	};
}
const ENVD_DEBUG_FALLBACK = "99.99.99";
const ENVD_ENVD_CLOSE = "0.5.2";
const ENVD_OCTET_STREAM_UPLOAD = "0.5.7";
//#endregion
//#region src/envd/rpc.ts
/**
* Message fragments different JS runtimes use when the connection to the sandbox
* is dropped mid-request. The transport surfaces a dropped connection (e.g. an
* HTTP/2 stream reset) with runtime- and version-specific wording, so we match
* every known variant:
*   - Node (undici):       `terminated`
*   - Bun:                 `The socket connection was closed unexpectedly`
*   - Deno:                `error reading a body from connection`
*   - Cloudflare Workers:  `Network connection lost`
*/
const CONNECTION_TERMINATED_MESSAGES = [
	"terminated",
	"The socket connection was closed unexpectedly",
	"error reading a body from connection",
	"Network connection lost"
];
/**
* Checks whether a message matches any known runtime variant of the connection to
* the sandbox being dropped mid-request (see {@link CONNECTION_TERMINATED_MESSAGES}).
*/
function isConnectionTerminatedMessage(message) {
	if (!message) return false;
	return CONNECTION_TERMINATED_MESSAGES.some((fragment) => message.includes(fragment));
}
/**
* Checks whether the error is the signature of the connection to the sandbox being
* dropped mid-request — an HTTP/2 stream reset surfaced by connect as `Code.Unknown`
* with one of the runtime-specific connection-dropped messages.
*/
function isConnectionTerminatedError(err) {
	return err instanceof ConnectError && err.code === Code.Unknown && isConnectionTerminatedMessage(err.rawMessage);
}
const DEFAULT_ERROR_MAP$1 = {
	[Code.InvalidArgument]: (message) => new InvalidArgumentError(message),
	[Code.Unauthenticated]: (message) => new AuthenticationError(message),
	[Code.NotFound]: (message) => new NotFoundError(message),
	[Code.ResourceExhausted]: (message) => new RateLimitError(`${message}: Rate limit exceeded, please try again later.`),
	[Code.Unavailable]: formatSandboxTimeoutError,
	[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.`),
	[Code.DeadlineExceeded]: (message) => new TimeoutError(`${message}: This error is likely due to exceeding 'timeoutMs' — 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.`)
};
/**
* Handles errors from envd RPC calls by mapping gRPC status codes to specific error types.
*
* @param err - The caught error, expected to be a `ConnectError` from the gRPC transport.
* @param errorMap - Optional map of gRPC `Code` values to error factory functions that override the defaults.
* @returns The corresponding `Error` instance mapped from the gRPC status code, or the original error if it is not a `ConnectError`.
*/
function handleRpcError(err, errorMap) {
	if (err instanceof ConnectError) {
		if (errorMap && err.code in errorMap) return errorMap[err.code](err.message);
		if (err.code in DEFAULT_ERROR_MAP$1) return DEFAULT_ERROR_MAP$1[err.code](err.message);
		return new SandboxError(`${err.code}: ${err.message}`);
	}
	return err;
}
/**
* Like {@link handleRpcError}, but when the connection to the sandbox was dropped
* mid-request it probes the sandbox health to tell apart the sandbox being killed
* from a transient network failure (e.g. a load balancer dropping the connection).
* When the probe confirms the sandbox is gone, a `TimeoutError` is returned —
* consistent with how requests to an already-dead sandbox surface.
*
* @param err - The caught error, expected to be a `ConnectError` from the gRPC transport.
* @param checkHealth - Probe returning whether the sandbox is running, or `undefined` when unknown.
* @param errorMap - Optional map of gRPC `Code` values to error factory functions that override the defaults.
* @returns The corresponding `Error` instance.
*/
async function handleRpcErrorWithHealthCheck(err, checkHealth, errorMap) {
	if (isConnectionTerminatedError(err) && checkHealth) {
		if (await checkHealth().catch(() => void 0) === 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 && compareVersions(envdVersion, "0.4.0") < 0) username = defaultUsername;
	if (!username) return {};
	return { Authorization: `Basic ${encode64(`${username}:`)}` };
}
//#endregion
//#region src/envd/api.ts
const DEFAULT_ERROR_MAP = {
	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)
};
const HEALTH_CHECK_TIMEOUT_MS = 5e3;
/**
* Probes the sandbox's envd health endpoint.
*
* @param envdApi - The envd API client of the sandbox.
* @returns `true` if the sandbox is running, `false` if it is not, `undefined` if its state could not be determined.
*/
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;
	} catch (_unused) {
		return;
	}
}
/**
* Handles transport-level fetch failures from envd API calls. When the connection was
* dropped mid-request, probes the sandbox health to tell apart the sandbox being killed
* from a transient network failure (e.g. a load balancer dropping the connection).
*
* @param err - The caught error, expected to be a fetch transport failure.
* @param checkHealth - Probe returning whether the sandbox is running, or `undefined` when unknown.
* @returns A `TimeoutError` when the connection was terminated mid-request and the sandbox is confirmed gone, or the original error otherwise.
*/
async function handleEnvdApiFetchError(err, checkHealth) {
	if (err instanceof Error && isConnectionTerminatedMessage(err.message)) {
		if ((checkHealth ? await checkHealth().catch(() => void 0) : void 0) === false) return new TimeoutError(`${err.message}: The sandbox was killed or reached its end of life while the request was in flight.`);
	}
	return err;
}
/**
* Handles errors from envd API responses by mapping HTTP status codes to specific error types.
*
* @param res - The API response object containing an optional error and the raw `Response`.
* @param errorMap - Optional map of HTTP status codes to error factory functions that override the defaults.
* @returns The corresponding `Error` instance if an error is present, or `undefined` if the response is successful.
*/
async function handleEnvdApiError(res, errorMap) {
	var _ref, _res$error;
	if (res.response.ok) return;
	let message = (_ref = typeof res.error === "string" ? res.error : (_res$error = res.error) === null || _res$error === void 0 ? void 0 : _res$error.message) !== null && _ref !== void 0 ? _ref : "";
	if (!message && !res.response.bodyUsed) try {
		message = await res.response.text();
	} catch (_unused2) {}
	message = message || res.response.statusText;
	if (errorMap && res.response.status in errorMap) {
		var _errorMap$res$respons;
		return (_errorMap$res$respons = errorMap[res.response.status]) === null || _errorMap$res$respons === void 0 ? void 0 : _errorMap$res$respons.call(errorMap, message);
	}
	if (res.response.status in DEFAULT_ERROR_MAP) {
		var _DEFAULT_ERROR_MAP$re;
		return (_DEFAULT_ERROR_MAP$re = DEFAULT_ERROR_MAP[res.response.status]) === null || _DEFAULT_ERROR_MAP$re === void 0 ? void 0 : _DEFAULT_ERROR_MAP$re.call(DEFAULT_ERROR_MAP, message);
	}
	return new SandboxError(`${res.response.status}: ${message}`);
}
async function handleProcessStartEvent(events) {
	var _startEvent$event;
	let startEvent;
	try {
		startEvent = (await events[Symbol.asyncIterator]().next()).value;
	} catch (err) {
		if (err instanceof ConnectError) {
			if (err.code === Code.Unavailable) throw new SandboxNotFoundError("Sandbox is probably not running anymore");
		}
		throw err;
	}
	if (((_startEvent$event = startEvent.event) === null || _startEvent$event === void 0 ? void 0 : _startEvent$event.event.case) !== "start") throw new Error("Expected start event");
	return startEvent.event.event.value.pid;
}
async function handleWatchDirStartEvent(events) {
	var _startEvent$event2;
	let startEvent;
	try {
		startEvent = (await events[Symbol.asyncIterator]().next()).value;
	} catch (err) {
		if (err instanceof ConnectError) {
			if (err.code === Code.Unavailable) throw new SandboxNotFoundError("Sandbox is probably not running anymore");
		}
		throw err;
	}
	if (((_startEvent$event2 = startEvent.event) === null || _startEvent$event2 === void 0 ? void 0 : _startEvent$event2.case) !== "start") throw new Error("Expected start event");
	return startEvent.event.value;
}
var EnvdApiClient = class {
	constructor(config, metadata) {
		_defineProperty(this, "api", void 0);
		_defineProperty(this, "version", void 0);
		this.api = createClient({
			baseUrl: config.apiUrl,
			fetch: config === null || config === void 0 ? void 0 : config.fetch,
			headers: _objectSpread2(_objectSpread2({}, config === null || config === void 0 ? void 0 : config.headers), config.envdAccessToken && { "X-Access-Token": config.envdAccessToken })
		});
		this.version = metadata.version;
		if (config.logger) this.api.use(createApiLogger(config.logger));
	}
};
/**
* @generated from service filesystem.Filesystem
*/
const Filesystem$1 = /*@__PURE__*/ serviceDesc(/* @__PURE__ */ fileDesc("ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i5QIKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQESNQoIbWV0YWRhdGEYCyADKAsyIy5maWxlc3lzdGVtLkVudHJ5SW5mby5NZXRhZGF0YUVudHJ5Gi8KDU1ldGFkYXRhRW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgJOgI4AUIRCg9fc3ltbGlua190YXJnZXQiLQoOTGlzdERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRINCgVkZXB0aBgCIAEoDSI5Cg9MaXN0RGlyUmVzcG9uc2USJgoHZW50cmllcxgBIAMoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvImcKD1dhdGNoRGlyUmVxdWVzdBIMCgRwYXRoGAEgASgJEhEKCXJlY3Vyc2l2ZRgCIAEoCBIVCg1pbmNsdWRlX2VudHJ5GAMgASgIEhwKFGFsbG93X25ldHdvcmtfbW91bnRzGAQgASgIInkKD0ZpbGVzeXN0ZW1FdmVudBIMCgRuYW1lGAEgASgJEiMKBHR5cGUYAiABKA4yFS5maWxlc3lzdGVtLkV2ZW50VHlwZRIpCgVlbnRyeRgDIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvSACIAQFCCAoGX2VudHJ5IuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQibAoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgSFQoNaW5jbHVkZV9lbnRyeRgDIAEoCBIcChRhbGxvd19uZXR3b3JrX21vdW50cxgEIAEoCCIrChVDcmVhdGVXYXRjaGVyUmVzcG9uc2USEgoKd2F0Y2hlcl9pZBgBIAEoCSItChdHZXRXYXRjaGVyRXZlbnRzUmVxdWVzdBISCgp3YXRjaGVyX2lkGAEgASgJIkcKGEdldFdhdGNoZXJFdmVudHNSZXNwb25zZRIrCgZldmVudHMYASADKAsyGy5maWxlc3lzdGVtLkZpbGVzeXN0ZW1FdmVudCIqChRSZW1vdmVXYXRjaGVyUmVxdWVzdBISCgp3YXRjaGVyX2lkGAEgASgJIhcKFVJlbW92ZVdhdGNoZXJSZXNwb25zZSppCghGaWxlVHlwZRIZChVGSUxFX1RZUEVfVU5TUEVDSUZJRUQQABISCg5GSUxFX1RZUEVfRklMRRABEhcKE0ZJTEVfVFlQRV9ESVJFQ1RPUlkQAhIVChFGSUxFX1RZUEVfU1lNTElOSxADKpgBCglFdmVudFR5cGUSGgoWRVZFTlRfVFlQRV9VTlNQRUNJRklFRBAAEhUKEUVWRU5UX1RZUEVfQ1JFQVRFEAESFAoQRVZFTlRfVFlQRV9XUklURRACEhUKEUVWRU5UX1RZUEVfUkVNT1ZFEAMSFQoRRVZFTlRfVFlQRV9SRU5BTUUQBBIUChBFVkVOVF9UWVBFX0NITU9EEAUynwUKCkZpbGVzeXN0ZW0SOQoEU3RhdBIXLmZpbGVzeXN0ZW0uU3RhdFJlcXVlc3QaGC5maWxlc3lzdGVtLlN0YXRSZXNwb25zZRJCCgdNYWtlRGlyEhouZmlsZXN5c3RlbS5NYWtlRGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTWFrZURpclJlc3BvbnNlEjkKBE1vdmUSFy5maWxlc3lzdGVtLk1vdmVSZXF1ZXN0GhguZmlsZXN5c3RlbS5Nb3ZlUmVzcG9uc2USQgoHTGlzdERpchIaLmZpbGVzeXN0ZW0uTGlzdERpclJlcXVlc3QaGy5maWxlc3lzdGVtLkxpc3REaXJSZXNwb25zZRI/CgZSZW1vdmUSGS5maWxlc3lzdGVtLlJlbW92ZVJlcXVlc3QaGi5maWxlc3lzdGVtLlJlbW92ZVJlc3BvbnNlEkcKCFdhdGNoRGlyEhsuZmlsZXN5c3RlbS5XYXRjaERpclJlcXVlc3QaHC5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UwARJUCg1DcmVhdGVXYXRjaGVyEiAuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEl0KEEdldFdhdGNoZXJFdmVudHMSIy5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXF1ZXN0GiQuZmlsZXN5c3RlbS5HZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USVAoNUmVtb3ZlV2F0Y2hlchIgLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlcXVlc3QaIS5maWxlc3lzdGVtLlJlbW92ZVdhdGNoZXJSZXNwb25zZUJpCg5jb20uZmlsZXN5c3RlbUIPRmlsZXN5c3RlbVByb3RvUAGiAgNGWFiqAgpGaWxlc3lzdGVtygIKRmlsZXN5c3RlbeICFkZpbGVzeXN0ZW1cR1BCTWV0YWRhdGHqAgpGaWxlc3lzdGVtYgZwcm90bzM", [file_google_protobuf_timestamp]), 0);
//#endregion
//#region src/sandbox/filesystem/watchHandle.ts
/**
* Sandbox filesystem event types.
*/
let FilesystemEventType = /* @__PURE__ */ function(FilesystemEventType) {
	/**
	* Filesystem object permissions were changed.
	*/
	FilesystemEventType["CHMOD"] = "chmod";
	/**
	* Filesystem object was created.
	*/
	FilesystemEventType["CREATE"] = "create";
	/**
	* Filesystem object was removed.
	*/
	FilesystemEventType["REMOVE"] = "remove";
	/**
	* Filesystem object was renamed.
	*/
	FilesystemEventType["RENAME"] = "rename";
	/**
	* Filesystem object was written to.
	*/
	FilesystemEventType["WRITE"] = "write";
	return FilesystemEventType;
}({});
function mapEventType(type) {
	switch (type) {
		case 5: return "chmod";
		case 1: return "create";
		case 3: return "remove";
		case 4: return "rename";
		case 2: return "write";
	}
}
/**
* Handle for watching a directory in the sandbox filesystem.
*
* Use {@link WatchHandle.stop} to stop watching the directory.
*/
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() {
		var _this2 = this;
		return _wrapAsyncGenerator(function* () {
			try {
				var _iteratorAbruptCompletion = false;
				var _didIteratorError = false;
				var _iteratorError;
				try {
					for (var _iterator = _asyncIterator(_this2.events), _step; _iteratorAbruptCompletion = !(_step = yield _awaitAsyncGenerator(_iterator.next())).done; _iteratorAbruptCompletion = false) {
						const event = _step.value;
						switch (event.event.case) {
							case "filesystem":
								yield event.event;
								break;
						}
					}
				} catch (err) {
					_didIteratorError = true;
					_iteratorError = err;
				} finally {
					try {
						if (_iteratorAbruptCompletion && _iterator.return != null) yield _awaitAsyncGenerator(_iterator.return());
					} finally {
						if (_didIteratorError) throw _iteratorError;
					}
				}
			} catch (err) {
				throw yield _awaitAsyncGenerator(handleRpcErrorWithHealthCheck(err, _this2.checkHealth));
			}
		})();
	}
	async handleEvents() {
		var _this3 = this;
		let iterationError;
		try {
			var _iteratorAbruptCompletion2 = false;
			var _didIteratorError2 = false;
			var _iteratorError2;
			try {
				for (var _iterator2 = _asyncIterator(_this3.iterateEvents()), _step2; _iteratorAbruptCompletion2 = !(_step2 = await _iterator2.next()).done; _iteratorAbruptCompletion2 = false) {
					const event = _step2.value;
					{
						var _this$onEvent;
						const eventType = mapEventType(event.value.type);
						if (eventType === void 0) continue;
						await ((_this$onEvent = _this3.onEvent) === null || _this$onEvent === void 0 ? void 0 : _this$onEvent.call(_this3, {
							name: event.value.name,
							type: eventType,
							entry: event.value.entry ? mapEntryInfo(event.value.entry) : void 0
						}));
					}
				}
			} catch (err) {
				_didIteratorError2 = true;
				_iteratorError2 = err;
			} finally {
				try {
					if (_iteratorAbruptCompletion2 && _iterator2.return != null) await _iterator2.return();
				} finally {
					if (_didIteratorError2) throw _iteratorError2;
				}
			}
		} catch (err) {
			iterationError = err;
		}
		try {
			if (iterationError) {
				var _this$onExit;
				await ((_this$onExit = _this3.onExit) === null || _this$onExit === void 0 ? void 0 : _this$onExit.call(_this3, iterationError));
			} else {
				var _this$onExit2;
				await ((_this$onExit2 = _this3.onExit) === null || _this$onExit2 === void 0 ? void 0 : _this$onExit2.call(_this3));
			}
		} catch (_unused) {} finally {
			_this3.handleStop();
		}
	}
};
//#endregion
//#region src/sandbox/filesystem/index.ts
const FILESYSTEM_HTTP_ERROR_MAP = { 404: (message) => new FileNotFoundError(message) };
const FILESYSTEM_RPC_ERROR_MAP = { [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);
}
/**
* Sandbox filesystem object type.
*/
let FileType = /* @__PURE__ */ function(FileType) {
	/**
	* Filesystem object is a file.
	*/
	FileType["FILE"] = "file";
	/**
	* Filesystem object is a directory.
	*/
	FileType["DIR"] = "dir";
	/**
	* Filesystem object is a symlink.
	*/
	FileType["SYMLINK"] = "symlink";
	return FileType;
}({});
function mapFileType(fileType) {
	switch (fileType) {
		case 2: return "dir";
		case 1: return "file";
		case 3: return "symlink";
	}
}
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;
}
const METADATA_HEADER_PREFIX = "X-Metadata-";
const METADATA_KEY_REGEX = /^[A-Za-z0-9!#$%&'*+\-.^_`|~]+$/;
const 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;
}
/**
* Map a protobuf `EntryInfo` to the SDK `EntryInfo`.
*/
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)
	};
}
/**
* Module for interacting with the sandbox filesystem.
*/
var Filesystem = class {
	constructor(transport, envdApi, connectionConfig) {
		this.envdApi = envdApi;
		this.connectionConfig = connectionConfig;
		_defineProperty(this, "rpc", void 0);
		_defineProperty(this, "defaultWatchTimeout", 6e4);
		_defineProperty(this, "defaultWatchRecursive", false);
		_defineProperty(this, "checkHealth", void 0);
		this.rpc = createClient$1(Filesystem$1, transport);
		this.checkHealth = () => checkSandboxHealth(this.envdApi);
	}
	async read(path, opts) {
		var _this = this;
		var _opts$format;
		const format = (_opts$format = opts === null || opts === void 0 ? void 0 : opts.format) !== null && _opts$format !== void 0 ? _opts$format : "text";
		let user = opts === null || opts === void 0 ? void 0 : opts.user;
		if (user == void 0 && compareVersions(_this.envdApi.version, "0.4.0") < 0) user = defaultUsername;
		const headers = {};
		if (opts === null || opts === void 0 ? void 0 : opts.gzip) headers["Accept-Encoding"] = "gzip";
		if (format === "stream") {
			var _opts$requestTimeoutM;
			const requestTimeoutMs = (_opts$requestTimeoutM = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM !== void 0 ? _opts$requestTimeoutM : _this.connectionConfig.requestTimeoutMs;
			const { controller, clearStartTimeout, cleanup } = setupRequestController(requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
			try {
				var _opts$streamIdleTimeo;
				const res = await _this.envdApi.api.GET("/files", {
					params: { query: {
						path,
						username: user
					} },
					parseAs: "stream",
					signal: controller.signal,
					headers
				}).catch(async (err) => {
					throw await handleEnvdApiFetchError(err, _this.checkHealth);
				});
				const err = await handleFilesystemEnvdApiError(res);
				if (err) {
					if (res.response.body && !res.response.bodyUsed) await res.response.body.cancel().catch(() => {});
					cleanup();
					throw err;
				}
				return wrapStreamWithConnectionCleanup(res.data, {
					clearStartTimeout,
					cleanup,
					controller,
					idleTimeoutMs: (_opts$streamIdleTimeo = opts === null || opts === void 0 ? void 0 : opts.streamIdleTimeoutMs) !== null && _opts$streamIdleTimeo !== void 0 ? _opts$streamIdleTimeo : requestTimeoutMs
				});
			} catch (err) {
				cleanup();
				throw err;
			}
		}
		const res = await _this.envdApi.api.GET("/files", {
			params: { query: {
				path,
				username: user
			} },
			parseAs: format === "bytes" ? "arrayBuffer" : format,
			signal: _this.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal),
			headers
		}).catch(async (err) => {
			throw await handleEnvdApiFetchError(err, _this.checkHealth);
		});
		const err = await handleFilesystemEnvdApiError(res);
		if (err) throw err;
		if (res.response.headers.get("content-length") === "0") {
			if (format === "bytes") return /* @__PURE__ */ new Uint8Array(0);
			return format === "blob" ? new Blob([]) : "";
		}
		if (format === "bytes") return new Uint8Array(res.data);
		return res.data;
	}
	async write(pathOrFiles, dataOrOpts, opts) {
		var _this2 = this;
		var _writeOpts$useOctetSt;
		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 [];
		let user = writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.user;
		if (user == void 0 && compareVersions(_this2.envdApi.version, "0.4.0") < 0) user = defaultUsername;
		const useGzip = (writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.gzip) === true;
		const supportsOctetStream = compareVersions(_this2.envdApi.version, ENVD_OCTET_STREAM_UPLOAD) >= 0;
		const hasStreamableData = runtime !== "browser" && writeFiles.some((file) => isReadableStreamLike(file.data));
		const useOctetStream = (((_writeOpts$useOctetSt = writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.useOctetStream) !== null && _writeOpts$useOctetSt !== void 0 ? _writeOpts$useOctetSt : hasStreamableData) || useGzip) && supportsOctetStream;
		const metadata = writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.metadata;
		validateMetadata(metadata);
		if (metadata && Object.keys(metadata).length > 0 && compareVersions(_this2.envdApi.version, "0.6.2") < 0) throw new TemplateError("File metadata requires envd 0.6.2 or later.");
		const extraHeaders = metadataHeaders(metadata);
		const results = [];
		if (useOctetStream) {
			const headers = _objectSpread2({ "Content-Type": "application/octet-stream" }, extraHeaders);
			if (useGzip) headers["Content-Encoding"] = "gzip";
			const uploadResults = await Promise.all(writeFiles.map(async (file) => {
				const filePath = path !== null && path !== void 0 ? path : file.path;
				const { body, streamed } = await toUploadBody(file.data, useGzip);
				const signal = streamed ? writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.signal : _this2.connectionConfig.getSignal(writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.requestTimeoutMs, writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.signal);
				const res = await _this2.envdApi.api.POST("/files", _objectSpread2({
					params: { query: {
						path: filePath,
						username: user
					} },
					bodySerializer: () => body,
					headers,
					signal,
					body: {}
				}, streamed && { duplex: "half" })).catch(async (err) => {
					throw await handleEnvdApiFetchError(err, _this2.checkHealth);
				});
				const err = await handleFilesystemEnvdApiError(res);
				if (err) throw err;
				const files = res.data;
				if (!files || files.length === 0) throw new Error("Expected to receive information about written file");
				for (const f of files) f.metadata = mapMetadata(f.metadata);
				return files;
			}));
			for (const files of uploadResults) results.push(...files);
		} else {
			const formData = new FormData();
			for (const file of writeFiles) {
				var _path;
				formData.append("file", await toBlob(file.data), (_path = file.path) !== null && _path !== void 0 ? _path : path);
			}
			const res = await _this2.envdApi.api.POST("/files", {
				params: { query: {
					path,
					username: user
				} },
				bodySerializer: () => formData,
				headers: extraHeaders,
				signal: _this2.connectionConfig.getSignal(writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.requestTimeoutMs, writeOpts === null || writeOpts === void 0 ? void 0 : writeOpts.signal),
				body: {}
			}).catch(async (err) => {
				throw await handleEnvdApiFetchError(err, _this2.checkHealth);
			});
			const err = await handleFilesystemEnvdApiError(res);
			if (err) throw err;
			const files = res.data;
			if (!files || files.length === 0) throw new Error("Expected to receive information about written file");
			for (const f of files) f.metadata = mapMetadata(f.metadata);
			results.push(...files);
		}
		return results.length === 1 && path ? results[0] : results;
	}
	/**
	* Write multiple files.
	*
	*
	* Writing to a file that doesn't exist creates the file.
	*
	* Writing to a file that already exists overwrites the file.
	*
	* Writing to a file at path that doesn't exist creates the necessary directories.
	*
	* @param files list of files to write as `WriteEntry` objects, each containing `path` and `data`.
	* @param opts connection options.
	*
	* @returns information about the written files
	*/
	async writeFiles(files, opts) {
		return this.write(files, opts);
	}
	/**
	* 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 _this4 = this;
		if (typeof (opts === null || opts === void 0 ? void 0 : opts.depth) === "number" && opts.depth < 1) throw new InvalidArgumentError("depth should be at least one");
		try {
			var _opts$depth;
			const res = await _this4.rpc.listDir({
				path,
				depth: (_opts$depth = opts === null || opts === void 0 ? void 0 : opts.depth) !== null && _opts$depth !== void 0 ? _opts$depth : 1
			}, {
				headers: authenticationHeader(_this4.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user),
				signal: _this4.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal)
			});
			const entries = [];
			for (const e of res.entries) {
				if (!mapFileType(e.type)) continue;
				entries.push(mapEntryInfo(e));
			}
			return entries;
		} catch (err) {
			throw await handleFilesystemRpcError(err, _this4.checkHealth);
		}
	}
	/**
	* 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) {
		var _this5 = this;
		try {
			await _this5.rpc.makeDir({ path }, {
				headers: authenticationHeader(_this5.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user),
				signal: _this5.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal)
			});
			return true;
		} catch (err) {
			if (err instanceof ConnectError) {
				if (err.code === Code.AlreadyExists) return false;
			}
			throw await handleFilesystemRpcError(err, _this5.checkHealth);
		}
	}
	/**
	* 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) {
		var _this6 = this;
		try {
			const entry = (await _this6.rpc.move({
				source: oldPath,
				destination: newPath
			}, {
				headers: authenticationHeader(_this6.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user),
				signal: _this6.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal)
			})).entry;
			if (!entry) throw new Error("Expected to receive information about moved object");
			return mapEntryInfo(entry);
		} catch (err) {
			throw await handleFilesystemRpcError(err, _this6.checkHealth);
		}
	}
	/**
	* Remove a file or directory.
	*
	* @param path path to a file or directory.
	* @param opts connection options.
	*/
	async remove(path, opts) {
		var _this7 = this;
		try {
			await _this7.rpc.remove({ path }, {
				headers: authenticationHeader(_this7.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user),
				signal: _this7.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal)
			});
		} catch (err) {
			throw await handleFilesystemRpcError(err, _this7.checkHealth);
		}
	}
	/**
	* 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) {
		var _this8 = this;
		try {
			await _this8.rpc.stat({ path }, {
				headers: authenticationHeader(_this8.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user),
				signal: _this8.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal)
			});
			return true;
		} catch (err) {
			if (err instanceof ConnectError) {
				if (err.code === Code.NotFound) return false;
			}
			throw await handleFilesystemRpcError(err, _this8.checkHealth);
		}
	}
	/**
	* 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) {
		var _this9 = this;
		try {
			const res = await _this9.rpc.stat({ path }, {
				headers: authenticationHeader(_this9.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user),
				signal: _this9.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal)
			});
			if (!res.entry) throw new Error("Expected to receive information about the file or directory");
			return mapEntryInfo(res.entry);
		} catch (err) {
			throw await handleFilesystemRpcError(err, _this9.checkHealth);
		}
	}
	/**
	* 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 _this10 = this;
		var _opts$requestTimeoutM2, _opts$recursive, _opts$includeEntry, _opts$allowNetworkMou, _opts$timeoutMs;
		if ((opts === null || opts === void 0 ? void 0 : opts.recursive) && _this10.envdApi.version && compareVersions(_this10.envdApi.version, "0.1.4") < 0) throw new TemplateError("You need to update the template to use recursive watching.");
		if ((opts === null || opts === void 0 ? void 0 : opts.includeEntry) && _this10.envdApi.version && compareVersions(_this10.envdApi.version, "0.6.3") < 0) throw new TemplateError("You need to update the template to include entry info in watch events.");
		if ((opts === null || opts === void 0 ? void 0 : opts.allowNetworkMounts) && _this10.envdApi.version && compareVersions(_this10.envdApi.version, "0.6.4") < 0) throw new TemplateError("You need to update the template to watch directories on network mounts.");
		const { controller, clearStartTimeout, cleanup } = setupRequestController((_opts$requestTimeoutM2 = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM2 !== void 0 ? _opts$requestTimeoutM2 : _this10.connectionConfig.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
		const events = _this10.rpc.watchDir({
			path,
			recursive: (_opts$recursive = opts === null || opts === void 0 ? void 0 : opts.recursive) !== null && _opts$recursive !== void 0 ? _opts$recursive : _this10.defaultWatchRecursive,
			includeEntry: (_opts$includeEntry = opts === null || opts === void 0 ? void 0 : opts.includeEntry) !== null && _opts$includeEntry !== void 0 ? _opts$includeEntry : false,
			allowNetworkMounts: (_opts$allowNetworkMou = opts === null || opts === void 0 ? void 0 : opts.allowNetworkMounts) !== null && _opts$allowNetworkMou !== void 0 ? _opts$allowNetworkMou : false
		}, {
			headers: _objectSpread2(_objectSpread2({}, authenticationHeader(_this10.envdApi.version, opts === null || opts === void 0 ? void 0 : opts.user)), {}, { [KEEPALIVE_PING_HEADER]: 50 .toString() }),
			signal: controller.signal,
			timeoutMs: (_opts$timeoutMs = opts === null || opts === void 0 ? void 0 : opts.timeoutMs) !== null && _opts$timeoutMs !== void 0 ? _opts$timeoutMs : _this10.defaultWatchTimeout
		});
		try {
			await handleWatchDirStartEvent(events);
			clearStartTimeout();
			return new WatchHandle(cleanup, events, onEvent, opts === null || opts === void 0 ? void 0 : opts.onExit, _this10.checkHealth);
		} catch (err) {
			cleanup();
			throw await handleFilesystemRpcError(err, _this10.checkHealth);
		}
	}
};
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/asyncGeneratorDelegate.js
function _asyncGeneratorDelegate(t) {
	var e = {}, n = !1;
	function pump(e, r) {
		return n = !0, r = new Promise(function(n) {
			n(t[e](r));
		}), {
			done: !1,
			value: new _OverloadYield(r, 1)
		};
	}
	return e["undefined" != typeof Symbol && Symbol.iterator || "@@iterator"] = function() {
		return this;
	}, e.next = function(t) {
		return n ? (n = !1, t) : pump("next", t);
	}, "function" == typeof t["throw"] && (e["throw"] = function(t) {
		if (n) throw n = !1, t;
		return pump("throw", t);
	}), "function" == typeof t["return"] && (e["return"] = function(t) {
		return n ? (n = !1, t) : pump("return", t);
	}), e;
}
//#endregion
//#region src/sandbox/commands/commandHandle.ts
/**
* Error thrown when a command exits with a non-zero exit code.
*/
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;
	}
};
/**
* Command execution handle.
*
* It provides methods for waiting for the command to finish, retrieving stdout/stderr, and killing the command.
*
* @property {number} pid process ID of the command.
*/
var CommandHandle = class {
	/**
	* @hidden
	* @internal
	* @access protected
	*/
	constructor(pid, handleDisconnect, handleKill, events, onStdout, onStderr, onPty, handleSendStdin, handleCloseStdin, checkHealth) {
		this.pid = pid;
		this.handleDisconnect = handleDisconnect;
		this.handleKill = handleKill;
		this.events = events;
		this.onStdout = onStdout;
		this.onStderr = onStderr;
		this.onPty = onPty;
		this.handleSendStdin = handleSendStdin;
		this.handleCloseStdin = handleCloseStdin;
		this.checkHealth = checkHealth;
		_defineProperty(this, "_stdout", "");
		_defineProperty(this, "_stderr", "");
		_defineProperty(this, "stdoutDecoder", new TextDecoder());
		_defineProperty(this, "stderrDecoder", new TextDecoder());
		_defineProperty(this, "result", void 0);
		_defineProperty(this, "iterationError", void 0);
		_defineProperty(this, "disconnected", false);
		_defineProperty(this, "_wait", void 0);
		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 _this$result;
		return (_this$result = this.result) === null || _this$result === void 0 ? void 0 : _this$result.exitCode;
	}
	/**
	* Error message from command execution.
	*/
	get error() {
		var _this$result2;
		return (_this$result2 = this.result) === null || _this$result2 === void 0 ? void 0 : _this$result2.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() {
		var _this = this;
		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}.
	*
	* Once it returns, the `onStdout`/`onStderr`/`onPty` callbacks are guaranteed
	* not to fire for output produced after this call. It does not wait for the
	* event handler to drain, so it returns promptly even for an idle command
	* whose stream produces no further output.
	*/
	async disconnect() {
		var _this2 = this;
		_this2.disconnected = true;
		_this2.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();
	}
	/**
	* Send data to the command stdin.
	*
	* The command must have been started with `stdin: true`.
	*
	* @param data data to send to the command.
	* @param opts connection options.
	*/
	async sendStdin(data, opts) {
		var _this4 = this;
		if (!_this4.handleSendStdin) throw new SandboxError("Sending stdin is not supported for this command handle.");
		await _this4.handleSendStdin(data, opts);
	}
	/**
	* Close the command stdin.
	*
	* This signals EOF to the command. The command must have been started with
	* `stdin: true`.
	*
	* @param opts connection options.
	*/
	async closeStdin(opts) {
		var _this5 = this;
		if (!_this5.handleCloseStdin) throw new SandboxError("Closing stdin is not supported for this command handle.");
		await _this5.handleCloseStdin(opts);
	}
	/**
	* Flush any bytes still buffered in the stream decoders.
	*
	* Incomplete trailing UTF-8 sequences are emitted as replacement
	* characters, matching the per-chunk decoding behavior.
	*/
	*flushDecoders() {
		const stdoutRest = this.stdoutDecoder.decode();
		if (stdoutRest) {
			this._stdout += stdoutRest;
			yield [
				stdoutRest,
				null,
				null
			];
		}
		const stderrRest = this.stderrDecoder.decode();
		if (stderrRest) {
			this._stderr += stderrRest;
			yield [
				null,
				stderrRest,
				null
			];
		}
	}
	iterateEvents() {
		var _this6 = this;
		return _wrapAsyncGenerator(function* () {
			try {
				var _iteratorAbruptCompletion = false;
				var _didIteratorError = false;
				var _iteratorError;
				try {
					for (var _iterator = _asyncIterator(_this6.events), _step; _iteratorAbruptCompletion = !(_step = yield _awaitAsyncGenerator(_iterator.next())).done; _iteratorAbruptCompletion = false) {
						const event = _step.value;
						{
							var _event$event;
							const e = event === null || event === void 0 || (_event$event = event.event) === null || _event$event === void 0 ? void 0 : _event$event.event;
							let out;
							switch (e === null || e === void 0 ? void 0 : e.case) {
								case "data":
									switch (e.value.output.case) {
										case "stdout":
											out = _this6.stdoutDecoder.decode(e.value.output.value, { stream: true });
											if (out) {
												_this6._stdout += out;
												yield [
													out,
													null,
													null
												];
											}
											break;
										case "stderr":
											out = _this6.stderrDecoder.decode(e.value.output.value, { stream: true });
											if (out) {
												_this6._stderr += out;
												yield [
													null,
													out,
													null
												];
											}
											break;
										case "pty":
											yield [
												null,
												null,
												e.value.output.value
											];
											break;
									}
									break;
								case "end": {
									const flushed = [..._this6.flushDecoders()];
									_this6.result = {
										exitCode: e.value.exitCode,
										error: e.value.error,
										stdout: _this6.stdout,
										stderr: _this6.stderr
									};
									for (const chunk of flushed) yield chunk;
									break;
								}
							}
						}
					}
				} catch (err) {
					_didIteratorError = true;
					_iteratorError = err;
				} finally {
					try {
						if (_iteratorAbruptCompletion && _iterator.return != null) yield _awaitAsyncGenerator(_iterator.return());
					} finally {
						if (_didIteratorError) throw _iteratorError;
					}
				}
			} catch (e) {
				yield* _asyncGeneratorDelegate(_asyncIterator(_this6.flushDecoders()));
				throw e;
			}
			if (_this6.result === void 0) yield* _asyncGeneratorDelegate(_asyncIterator(_this6.flushDecoders()));
		})();
	}
	async handleEvents() {
		var _this7 = this;
		try {
			var _iteratorAbruptCompletion2 = false;
			var _didIteratorError2 = false;
			var _iteratorError2;
			try {
				for (var _iterator2 = _asyncIterator(_this7.iterateEvents()), _step2; _iteratorAbruptCompletion2 = !(_step2 = await _iterator2.next()).done; _iteratorAbruptCompletion2 = false) {
					const [stdout, stderr, pty] = _step2.value;
					if (_this7.disconnected) break;
					if (stdout !== null) {
						var _this$onStdout;
						await ((_this$onStdout = _this7.onStdout) === null || _this$onStdout === void 0 ? void 0 : _this$onStdout.call(_this7, stdout));
					} else if (stderr !== null) {
						var _this$onStderr;
						await ((_this$onStderr = _this7.onStderr) === null || _this$onStderr === void 0 ? void 0 : _this$onStderr.call(_this7, stderr));
					} else if (pty) {
						var _this$onPty;
						await ((_this$onPty = _this7.onPty) === null || _this$onPty === void 0 ? void 0 : _this$onPty.call(_this7, pty));
					}
				}
			} catch (err) {
				_didIteratorError2 = true;
				_iteratorError2 = err;
			} finally {
				try {
					if (_iteratorAbruptCompletion2 && _iterator2.return != null) await _iterator2.return();
				} finally {
					if (_didIteratorError2) throw _iteratorError2;
				}
			}
		} catch (e) {
			_this7.iterationError = await handleRpcErrorWithHealthCheck(e, _this7.checkHealth);
		} finally {
			_this7.handleDisconnect();
		}
	}
};
//#endregion
//#region src/paginator.ts
/**
* Generic, reusable paginator for cursor-based list endpoints.
*
* The base owns the shared pagination state — `hasNext`, `nextToken`, and the
* reading of the `x-next-token` response header (via {@link Paginator.updatePagination}).
* Each concrete paginator implements {@link Paginator.nextItems} to do the
* actual fetching for its endpoint, so any model can expose pagination by
* subclassing this without reimplementing the bookkeeping.
*
* The optional `O` type parameter is the per-call options type accepted by
* `nextItems` (e.g. connection options for a given API).
*
* @example
* ```ts
* const paginator = Sandbox.list()
* while (paginator.hasNext) {
*   const items = await paginator.nextItems()
*   console.log(items)
* }
* ```
*/
var Paginator = class {
	constructor(opts, limit, nextToken) {
		_defineProperty(this, "opts", void 0);
		_defineProperty(this, "limit", void 0);
		_defineProperty(this, "_hasNext", void 0);
		_defineProperty(this, "_nextToken", void 0);
		this.opts = opts;
		this.limit = limit;
		this._hasNext = true;
		this._nextToken = nextToken;
	}
	/**
	* Returns true if there are more items to fetch.
	*/
	get hasNext() {
		return this._hasNext;
	}
	/**
	* Returns the next token to use for pagination.
	*/
	get nextToken() {
		return this._nextToken;
	}
	/**
	* Update the pagination state from a response, reading the `x-next-token`
	* header. Concrete paginators call this from {@link Paginator.nextItems}
	* after fetching a page.
	*/
	updatePagination(response) {
		this._nextToken = response.headers.get("x-next-token") || void 0;
		this._hasNext = !!this._nextToken;
	}
};
//#endregion
//#region src/secret.ts
const INVALID_SECRET_NAME_CHARS = /* @__PURE__ */ new RegExp("[{}\\p{Cc}]", "u");
function validateSecretName(name) {
	if (name.length === 0 || INVALID_SECRET_NAME_CHARS.test(name)) throw new InvalidArgumentError(`secret name ${JSON.stringify(name)} is not usable: a secret name cannot be empty or contain '{', '}' or control characters, because it is interpolated into the '\${e2b.secrets.<name>}' placeholder the runtime resolves.`);
}
function convertSecretInfo(secret) {
	var _secret$metadata;
	return {
		secretId: secret.secretID,
		name: secret.name,
		version: secret.currentVersion,
		metadata: (_secret$metadata = secret.metadata) !== null && _secret$metadata !== void 0 ? _secret$metadata : {},
		createdAt: new Date(secret.createdAt),
		updatedAt: new Date(secret.updatedAt)
	};
}
/**
* Paginator for listing secrets.
*
* @example
* ```ts
* const paginator = Secret.list()
* while (paginator.hasNext) {
*   const secrets = await paginator.nextItems()
*   console.log(secrets)
* }
* ```
*/
var SecretPaginator = class extends Paginator {
	constructor(opts) {
		super(opts, opts === null || opts === void 0 ? void 0 : opts.limit, opts === null || opts === void 0 ? void 0 : opts.nextToken);
	}
	async nextItems(opts) {
		var _this = this;
		var _res$data;
		if (!_this.hasNext) throw new Error("No more items to fetch");
		const apiOpts = ConnectionConfig.mergeOpts(_this.opts, opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/secrets", {
			params: { query: {
				limit: _this.limit,
				nextToken: _this.nextToken
			} },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		const err = handleApiError(res, SecretError);
		if (err) throw err;
		_this.updatePagination(res.response);
		return ((_res$data = res.data) !== null && _res$data !== void 0 ? _res$data : []).map(convertSecretInfo);
	}
};
/**
* Module for managing E2B secrets and workload identity helpers.
*
* Secret values are write-only: they are accepted by {@link Secret.create}
* and {@link Secret.update} but never returned by any read surface.
*/
var Secret = class extends ClientFactory {
	/**
	* Create a new secret and its first value.
	*
	* @param name name of the secret, unique within the project.
	* @param value secret value. Write-only — never returned by the API.
	* @param opts connection options.
	*
	* @returns the secret's ID, name, current version (`1` for a new secret),
	* metadata, and creation and update times.
	*/
	static async create(name, value, opts) {
		const apiOpts = this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/secrets", {
			body: {
				name,
				value,
				metadata: apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.metadata
			},
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		const err = handleApiError(res, SecretError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertSecretInfo(res.data);
	}
	/**
	* Update a secret's value by storing it as the secret's new version.
	*
	* @param secret secret ID or name.
	* @param value new secret value. Write-only — never returned by the API.
	* @param opts connection options.
	*
	* @returns the secret's ID, name, new current version, metadata, and
	* creation and update times.
	*/
	static async update(secret, value, opts) {
		const apiOpts = this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/secrets/{secretID}", {
			params: { path: { secretID: secret } },
			body: {
				value,
				metadata: apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.metadata
			},
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (res.response.status === 404) throw new SecretNotFoundError(`Secret ${secret} not found`);
		const err = handleApiError(res, SecretError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertSecretInfo(res.data);
	}
	/**
	* Get a secret's metadata.
	*
	* @param secret secret ID or name.
	* @param opts connection options.
	*
	* @returns the secret's ID, name, current version, metadata, and creation
	* and update times.
	*/
	static async getInfo(secret, opts) {
		const apiOpts = this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/secrets/{secretID}", {
			params: { path: { secretID: secret } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (res.response.status === 404) throw new SecretNotFoundError(`Secret ${secret} not found`);
		const err = handleApiError(res, SecretError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertSecretInfo(res.data);
	}
	/**
	* List the project's secrets.
	*
	* @param opts connection options.
	*
	* @returns paginator over the project's secrets. Drain it page by page:
	* `while (paginator.hasNext) { const secrets = await paginator.nextItems() }`.
	*
	* @example
	* ```ts
	* const paginator = Secret.list({ limit: 50 })
	* while (paginator.hasNext) {
	*   const secrets = await paginator.nextItems()
	* }
	* ```
	*/
	static list(opts) {
		return new SecretPaginator(this.resolveOpts(opts));
	}
	/**
	* Check whether a secret exists.
	*
	* @param secret secret ID or name.
	* @param opts connection options.
	*
	* @returns `true` if the secret exists, `false` otherwise.
	*/
	static async exists(secret, opts) {
		var _this5 = this;
		try {
			await _this5.getInfo(secret, opts);
			return true;
		} catch (err) {
			if (err instanceof SecretNotFoundError) return false;
			throw err;
		}
	}
	/**
	* Destroy a secret, making all its versions inaccessible.
	*
	* @param secret secret ID or name.
	* @param opts connection options.
	*
	* @returns `true` if the secret was destroyed, `false` if it was not found.
	*/
	static async destroy(secret, opts) {
		const apiOpts = this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.DELETE("/secrets/{secretID}", {
			params: { path: { secretID: secret } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (res.response.status === 404) return false;
		const err = handleApiError(res, SecretError);
		if (err) throw err;
		return true;
	}
	/**
	* Format a placeholder that the runtime resolves to the secret's current
	* value.
	*
	* This is a local formatting helper and makes no network call — it does
	* not check whether the named secret exists. An unknown reference fails
	* server-side when the placeholder is resolved.
	*
	* @param secret secret name.
	*
	* @returns placeholder string resolving to the secret's value.
	*
	* @example
	* ```ts
	* Secret.fill('openai-api-key')
	* // '${e2b.secrets.openai-api-key}'
	* ```
	*/
	static fill(secret) {
		validateSecretName(secret);
		return `\${e2b.secrets.${secret}}`;
	}
	/**
	* Define a workload identity token to pass to `iam.tokens` when creating
	* a sandbox.
	*
	* @param token workload token definition.
	*
	* @returns a token definition passable to `iam.tokens`.
	*
	* @example
	* ```ts
	* const sandbox = await Sandbox.create({
	*   iam: {
	*     tokens: {
	*       aws: Secret.iamToken({
	*         audience: 'sts.amazonaws.com',
	*         tokenType: 'JWT-SVID',
	*       }),
	*     },
	*   },
	* })
	* ```
	*/
	static iamToken(token) {
		return _objectSpread2({}, token);
	}
};
//#endregion
//#region src/sandbox/network.ts
/**
* CIDR range that represents all traffic.
*/
const ALL_TRAFFIC = "0.0.0.0/0";
//#endregion
//#region src/sandbox/git/utils.ts
/**
* Add HTTP(S) credentials to a Git URL.
*
* @param url Git repository URL.
* @param username Username for HTTP(S) authentication.
* @param password Password or token for HTTP(S) authentication.
* @returns URL with embedded credentials.
*/
function withCredentials(url, username, password) {
	if (!username && !password) return url;
	if (!username || !password) throw new InvalidArgumentError("Both username and password are required when using Git credentials.");
	let parsed;
	try {
		parsed = new URL(url);
	} catch (_unused) {
		throw new InvalidArgumentError(`Invalid Git URL: ${url}`);
	}
	if (parsed.protocol !== "http:" && parsed.protocol !== "https:") throw new InvalidArgumentError("Only http(s) Git URLs support username/password credentials.");
	parsed.username = username;
	parsed.password = password;
	return parsed.toString();
}
/**
* Strip HTTP(S) credentials from a Git URL.
*
* @param url Git repository URL.
* @returns URL without embedded credentials.
*/
function stripCredentials(url) {
	let parsed;
	try {
		parsed = new URL(url);
	} catch (_unused2) {
		return url;
	}
	if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return url;
	if (!parsed.username && !parsed.password) return url;
	parsed.username = "";
	parsed.password = "";
	return parsed.toString();
}
/**
* Derive the default repository directory name from a Git URL.
*
* @param url Git repository URL.
* @returns Repository directory name, if it can be determined.
*/
function deriveRepoDirFromUrl(url) {
	let parsed;
	try {
		parsed = new URL(url);
	} catch (_unused3) {
		return;
	}
	const lastSegment = parsed.pathname.replace(/\/+$/, "").split("/").pop();
	if (!lastSegment) return;
	return lastSegment.endsWith(".git") ? lastSegment.slice(0, -4) : lastSegment;
}
/**
* Build a shell-safe git command string.
*
* @param args Git command arguments.
* @param repoPath Repository path for `git -C`, if provided.
* @returns Shell-safe git command.
*/
function buildGitCommand(args, repoPath) {
	const parts = ["git"];
	if (repoPath) parts.push("-C", repoPath);
	parts.push(...args);
	return parts.map((part) => shellQuote(part)).join(" ");
}
function buildPushArgs(remoteName, opts) {
	const { remote, branch, setUpstream } = opts;
	const args = ["push"];
	const targetRemote = remoteName !== null && remoteName !== void 0 ? remoteName : remote;
	if (setUpstream && targetRemote) args.push("--set-upstream");
	if (targetRemote) args.push(targetRemote);
	if (branch) args.push(branch);
	return args;
}
function parseAheadBehind(segment) {
	if (!segment) return {
		ahead: 0,
		behind: 0
	};
	let ahead = 0;
	let behind = 0;
	if (segment.includes("ahead")) try {
		ahead = Number.parseInt(segment.split("ahead")[1].split(",")[0].trim(), 10);
	} catch (_unused4) {
		ahead = 0;
	}
	if (segment.includes("behind")) try {
		behind = Number.parseInt(segment.split("behind")[1].split(",")[0].trim(), 10);
	} catch (_unused5) {
		behind = 0;
	}
	return {
		ahead,
		behind
	};
}
function normalizeBranchName(name) {
	if (name.startsWith("HEAD (detached at ")) return name.replace("HEAD (detached at ", "").replace(/\)$/, "");
	return name.replace("HEAD (no branch)", "HEAD").replace("No commits yet on ", "").replace("Initial commit on ", "");
}
function deriveStatus(indexStatus, workingStatus) {
	const statuses = /* @__PURE__ */ new Set([indexStatus, workingStatus]);
	if (statuses.has("U")) return "conflict";
	if (statuses.has("R")) return "renamed";
	if (statuses.has("C")) return "copied";
	if (statuses.has("D")) return "deleted";
	if (statuses.has("A")) return "added";
	if (statuses.has("M")) return "modified";
	if (statuses.has("T")) return "typechange";
	if (statuses.has("?")) return "untracked";
	return "unknown";
}
/**
* Parse `git status --porcelain=1 -b` output into a structured object.
*
* @param output Git status output.
* @returns Parsed {@link GitStatus}.
*/
function parseGitStatus(output) {
	const lines = output.split("\n").map((line) => line.replace(/\r$/, "")).filter((line) => line.trim().length > 0);
	let currentBranch;
	let upstream;
	let ahead = 0;
	let behind = 0;
	let detached = false;
	const fileStatus = [];
	if (lines.length === 0) return {
		currentBranch,
		upstream,
		ahead,
		behind,
		detached,
		fileStatus,
		isClean: true,
		hasChanges: false,
		hasStaged: false,
		hasUntracked: false,
		hasConflicts: false,
		totalCount: 0,
		stagedCount: 0,
		unstagedCount: 0,
		untrackedCount: 0,
		conflictCount: 0
	};
	const branchLine = lines[0];
	if (branchLine.startsWith("## ")) {
		const branchInfo = branchLine.slice(3);
		const aheadStart = branchInfo.indexOf(" [");
		const branchPart = aheadStart === -1 ? branchInfo : branchInfo.slice(0, aheadStart);
		const aheadPart = aheadStart === -1 ? void 0 : branchInfo.slice(aheadStart + 2, -1);
		const normalizedBranch = normalizeBranchName(branchPart);
		const rawBranch = branchPart;
		if (rawBranch.startsWith("HEAD (detached at ") || rawBranch.includes("detached") || normalizedBranch.startsWith("HEAD")) detached = true;
		else if (normalizedBranch.includes("...")) {
			const [branch, upstreamBranch] = normalizedBranch.split("...");
			currentBranch = branch || void 0;
			upstream = upstreamBranch || void 0;
		} else currentBranch = normalizedBranch || void 0;
		const aheadBehind = parseAheadBehind(aheadPart);
		ahead = aheadBehind.ahead;
		behind = aheadBehind.behind;
	}
	for (const line of lines.slice(1)) {
		if (line.startsWith("?? ")) {
			const name = line.slice(3);
			fileStatus.push({
				name,
				status: "untracked",
				indexStatus: "?",
				workingTreeStatus: "?",
				staged: false
			});
			continue;
		}
		if (line.length < 3) continue;
		const indexStatus = line[0];
		const workingTreeStatus = line[1];
		const path = line.slice(3);
		let renamedFrom;
		let name = path;
		if (path.includes(" -> ")) {
			const parts = path.split(" -> ");
			renamedFrom = parts[0];
			name = parts.slice(1).join(" -> ");
		}
		fileStatus.push(_objectSpread2({
			name,
			status: deriveStatus(indexStatus, workingTreeStatus),
			indexStatus,
			workingTreeStatus,
			staged: indexStatus !== " " && indexStatus !== "?"
		}, renamedFrom ? { renamedFrom } : {}));
	}
	const totalCount = fileStatus.length;
	const stagedCount = fileStatus.filter((item) => item.staged).length;
	const untrackedCount = fileStatus.filter((item) => item.status === "untracked").length;
	const conflictCount = fileStatus.filter((item) => item.status === "conflict").length;
	const unstagedCount = totalCount - stagedCount;
	return {
		currentBranch,
		upstream,
		ahead,
		behind,
		detached,
		fileStatus,
		isClean: totalCount === 0,
		hasChanges: totalCount > 0,
		hasStaged: stagedCount > 0,
		hasUntracked: untrackedCount > 0,
		hasConflicts: conflictCount > 0,
		totalCount,
		stagedCount,
		unstagedCount,
		untrackedCount,
		conflictCount
	};
}
/**
* Parse `git branch --format=%(refname:short)\t%(HEAD)` output.
*
* @param output Git branch output.
* @returns Parsed {@link GitBranches}.
*/
function parseGitBranches(output) {
	const branches = [];
	let currentBranch;
	const lines = output.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
	for (const line of lines) {
		const parts = line.split("	");
		const name = parts[0];
		branches.push(name);
		if (parts.length > 1 && parts[1] === "*") currentBranch = name;
	}
	return {
		branches,
		currentBranch
	};
}
function isAuthFailure(err) {
	if (!(err instanceof CommandExitError)) return false;
	const message = `${err.stderr}\n${err.stdout}`.toLowerCase();
	return [
		"authentication failed",
		"terminal prompts disabled",
		"could not read username",
		"invalid username or password",
		"access denied",
		"permission denied",
		"not authorized"
	].some((snippet) => message.includes(snippet));
}
function getScopeFlag(scope) {
	if (scope !== "global" && scope !== "local" && scope !== "system") throw new InvalidArgumentError("Git config scope must be one of: global, local, system.");
	return `--${scope}`;
}
function isMissingUpstream(err) {
	if (!(err instanceof CommandExitError)) return false;
	const message = `${err.stderr}\n${err.stdout}`.toLowerCase();
	return [
		"has no upstream branch",
		"no upstream branch",
		"no upstream configured",
		"no tracking information for the current branch",
		"no tracking information",
		"set the remote as upstream",
		"set the upstream branch",
		"please specify which branch you want to merge with"
	].some((snippet) => message.includes(snippet));
}
function buildAuthErrorMessage(action, missingPassword) {
	if (missingPassword) return `Git ${action} requires a password/token for private repositories.`;
	return `Git ${action} requires credentials for private repositories.`;
}
function buildUpstreamErrorMessage(action) {
	if (action === "push") return "Git push failed because no upstream branch is configured. Set upstream once with { setUpstream: true } (and optional remote/branch), or pass remote and branch explicitly.";
	return "Git pull failed because no upstream branch is configured. Pass remote and branch explicitly, or set upstream once (push with { setUpstream: true } or run: git branch --set-upstream-to=origin/<branch> <branch>).";
}
function getRepoPathForScope(scope, path) {
	if (scope !== "local") return;
	if (!path) throw new InvalidArgumentError("A repository path is required when using scope \"local\".");
	return path;
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectWithoutPropertiesLoose.js
function _objectWithoutPropertiesLoose(r, e) {
	if (null == r) return {};
	var t = {};
	for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
		if (e.includes(n)) continue;
		t[n] = r[n];
	}
	return t;
}
//#endregion
//#region \0@oxc-project+runtime@0.139.0/helpers/esm/objectWithoutProperties.js
function _objectWithoutProperties(e, t) {
	if (null == e) return {};
	var o, r, i = _objectWithoutPropertiesLoose(e, t);
	if (Object.getOwnPropertySymbols) {
		var s = Object.getOwnPropertySymbols(e);
		for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
	}
	return i;
}
//#endregion
//#region src/sandbox/git/index.ts
const _excluded$1 = [
	"username",
	"password",
	"branch",
	"depth",
	"path",
	"dangerouslyStoreCredentials"
];
const _excluded2 = ["bare", "initialBranch"];
const _excluded3 = ["fetch", "overwrite"];
const _excluded4 = ["force"];
const _excluded5 = ["files", "all"];
const _excluded6 = [
	"authorName",
	"authorEmail",
	"allowEmpty"
];
const _excluded7 = [
	"mode",
	"target",
	"paths"
];
const _excluded8 = [
	"paths",
	"staged",
	"worktree",
	"source"
];
const _excluded9 = [
	"remote",
	"branch",
	"setUpstream",
	"username",
	"password"
];
const _excluded10 = [
	"remote",
	"branch",
	"username",
	"password"
];
const _excluded11 = [
	"username",
	"password",
	"host",
	"protocol"
];
const _excluded12 = ["envs"];
const _excluded13 = ["envs"];
const DEFAULT_GIT_ENV = { GIT_TERMINAL_PROMPT: "0" };
/**
* Module for running git operations in the sandbox.
*/
var Git = class {
	constructor(commands) {
		this.commands = commands;
	}
	/**
	* Clone a git repository into the sandbox.
	*
	* @param url Git repository URL.
	* @param opts Clone options.
	* @returns Command result from the command runner.
	*/
	async clone(url, opts) {
		var _this = this;
		const _ref = opts !== null && opts !== void 0 ? opts : {}, { username, password, branch, depth, path, dangerouslyStoreCredentials } = _ref, rest = _objectWithoutProperties(_ref, _excluded$1);
		if (password && !username) throw new InvalidArgumentError("Username is required when using a password or token for git clone.");
		const attemptClone = async (authUsername, authPassword) => {
			const urlWithCreds = authUsername && authPassword ? withCredentials(url, authUsername, authPassword) : url;
			const sanitizedUrl = stripCredentials(urlWithCreds);
			const stripInlineCreds = !dangerouslyStoreCredentials && sanitizedUrl !== urlWithCreds;
			const repoPath = stripInlineCreds ? path !== null && path !== void 0 ? path : deriveRepoDirFromUrl(url) : path;
			if (stripInlineCreds && !repoPath) throw new InvalidArgumentError("A destination path is required when using credentials without storing them.");
			const args = ["clone", urlWithCreds];
			if (branch) args.push("--branch", branch, "--single-branch");
			if (depth) args.push("--depth", depth.toString());
			if (repoPath) args.push(repoPath);
			const result = await _this.runGit(args, void 0, rest);
			if (stripInlineCreds) await _this.runGit([
				"remote",
				"set-url",
				"origin",
				sanitizedUrl
			], repoPath, rest);
			return result;
		};
		try {
			return await attemptClone(username, password);
		} catch (err) {
			if (isAuthFailure(err)) throw new GitAuthError(buildAuthErrorMessage("clone", Boolean(username) && !password));
			throw err;
		}
	}
	/**
	* Initialize a new git repository.
	*
	* @param path Destination path for the repository.
	* @param opts Init options.
	* @returns Command result from the command runner.
	*/
	async init(path, opts) {
		var _this2 = this;
		const _ref2 = opts !== null && opts !== void 0 ? opts : {}, { bare, initialBranch } = _ref2, rest = _objectWithoutProperties(_ref2, _excluded2);
		const args = ["init"];
		if (initialBranch) args.push("--initial-branch", initialBranch);
		if (bare) args.push("--bare");
		args.push(path);
		return _this2.runGit(args, void 0, rest);
	}
	/**
	* Add (or update) a remote for a repository.
	*
	* @param path Repository path.
	* @param name Remote name (for example, `"origin"`).
	* @param url Remote URL.
	* @param opts Remote add options.
	* @returns Command result from the command runner.
	*/
	async remoteAdd(path, name, url, opts) {
		var _this3 = this;
		if (!name || !url) throw new InvalidArgumentError("Both remote name and URL are required to add a git remote.");
		const _ref3 = opts !== null && opts !== void 0 ? opts : {}, { fetch, overwrite } = _ref3, rest = _objectWithoutProperties(_ref3, _excluded3);
		const addArgs = ["remote", "add"];
		if (fetch) addArgs.push("-f");
		addArgs.push(name, url);
		if (!overwrite) return _this3.runGit(addArgs, path, rest);
		let cmd = `${buildGitCommand(addArgs, path)} || ${buildGitCommand([
			"remote",
			"set-url",
			name,
			url
		], path)}`;
		if (fetch) {
			const fetchCmd = buildGitCommand(["fetch", name], path);
			cmd = `(${cmd}) && ${fetchCmd}`;
		}
		return _this3.runShell(cmd, rest);
	}
	/**
	* Get the URL for a git remote.
	*
	* Returns `undefined` when the remote does not exist.
	*
	* @param path Repository path.
	* @param name Remote name (for example, `"origin"`).
	* @param opts Command execution options.
	* @returns Remote URL if present.
	*/
	async remoteGet(path, name, opts) {
		var _this4 = this;
		if (!name) throw new InvalidArgumentError("Remote name is required.");
		const cmd = `${buildGitCommand([
			"remote",
			"get-url",
			name
		], path)} || true`;
		const trimmed = (await _this4.runShell(cmd, opts)).stdout.trim();
		return trimmed.length > 0 ? trimmed : void 0;
	}
	/**
	* Get repository status information.
	*
	* @param path Repository path.
	* @param opts Command execution options.
	* @returns Parsed git status.
	*/
	async status(path, opts) {
		return parseGitStatus((await this.runGit([
			"status",
			"--porcelain=1",
			"-b"
		], path, opts)).stdout);
	}
	/**
	* List branches in a repository.
	*
	* @param path Repository path.
	* @param opts Command execution options.
	* @returns Parsed branch list.
	*/
	async branches(path, opts) {
		return parseGitBranches((await this.runGit(["branch", "--format=%(refname:short)	%(HEAD)"], path, opts)).stdout);
	}
	/**
	* Create and check out a new branch.
	*
	* @param path Repository path.
	* @param branch Branch name to create.
	* @param opts Command execution options.
	* @returns Command result from the command runner.
	*/
	async createBranch(path, branch, opts) {
		return this.runGit([
			"checkout",
			"-b",
			branch
		], path, opts);
	}
	/**
	* Check out an existing branch.
	*
	* @param path Repository path.
	* @param branch Branch name to check out.
	* @param opts Command execution options.
	* @returns Command result from the command runner.
	*/
	async checkoutBranch(path, branch, opts) {
		return this.runGit(["checkout", branch], path, opts);
	}
	/**
	* Delete a branch.
	*
	* @param path Repository path.
	* @param branch Branch name to delete.
	* @param opts Delete options.
	* @returns Command result from the command runner.
	*/
	async deleteBranch(path, branch, opts) {
		var _this9 = this;
		const _ref4 = opts !== null && opts !== void 0 ? opts : {}, { force } = _ref4, rest = _objectWithoutProperties(_ref4, _excluded4);
		const args = [
			"branch",
			force ? "-D" : "-d",
			branch
		];
		return _this9.runGit(args, path, rest);
	}
	/**
	* Stage files for commit.
	*
	* @param path Repository path.
	* @param opts Add options.
	* @returns Command result from the command runner.
	*/
	async add(path, opts) {
		var _this10 = this;
		const _ref5 = opts !== null && opts !== void 0 ? opts : {}, { files, all = true } = _ref5, rest = _objectWithoutProperties(_ref5, _excluded5);
		const args = ["add"];
		if (!files || files.length === 0) args.push(all ? "-A" : ".");
		else args.push("--", ...files);
		return _this10.runGit(args, path, rest);
	}
	/**
	* Create a commit in the repository.
	*
	* @param path Repository path.
	* @param message Commit message.
	* @param opts Commit options.
	* @returns Command result from the command runner.
	*/
	async commit(path, message, opts) {
		var _this11 = this;
		const _ref6 = opts !== null && opts !== void 0 ? opts : {}, { authorName, authorEmail, allowEmpty } = _ref6, rest = _objectWithoutProperties(_ref6, _excluded6);
		const args = [
			"commit",
			"-m",
			message
		];
		if (allowEmpty) args.push("--allow-empty");
		const authorArgs = [];
		if (authorName) authorArgs.push("-c", `user.name=${authorName}`);
		if (authorEmail) authorArgs.push("-c", `user.email=${authorEmail}`);
		return _this11.runGit([...authorArgs, ...args], path, rest);
	}
	/**
	* Reset the current HEAD to a specified state.
	*
	* @param path Repository path.
	* @param opts Reset options.
	* @returns Command result from the command runner.
	*/
	async reset(path, opts) {
		var _this12 = this;
		const _ref7 = opts !== null && opts !== void 0 ? opts : {}, { mode, target, paths } = _ref7, rest = _objectWithoutProperties(_ref7, _excluded7);
		const allowedModes = [
			"soft",
			"mixed",
			"hard",
			"merge",
			"keep"
		];
		if (mode && !allowedModes.includes(mode)) throw new InvalidArgumentError(`Reset mode must be one of ${allowedModes.join(", ")}.`);
		const args = ["reset"];
		if (mode) args.push(`--${mode}`);
		if (target) args.push(target);
		if (paths && paths.length > 0) args.push("--", ...paths);
		return _this12.runGit(args, path, rest);
	}
	/**
	* Restore working tree files or unstage changes.
	*
	* @param path Repository path.
	* @param opts Restore options.
	* @returns Command result from the command runner.
	*/
	async restore(path, opts) {
		var _this13 = this;
		const { paths, staged, worktree, source } = opts, rest = _objectWithoutProperties(opts, _excluded8);
		if (!paths || paths.length === 0) throw new InvalidArgumentError("At least one path is required.");
		let resolvedStaged = staged;
		let resolvedWorktree = worktree;
		if (staged === void 0 && worktree === void 0) resolvedWorktree = true;
		else if (staged === true && worktree === void 0) resolvedWorktree = false;
		else if (staged === void 0 && worktree !== void 0) resolvedStaged = false;
		if (resolvedStaged === false && resolvedWorktree === false) throw new InvalidArgumentError("At least one of staged or worktree must be true.");
		const args = ["restore"];
		if (resolvedWorktree) args.push("--worktree");
		if (resolvedStaged) args.push("--staged");
		if (source) args.push("--source", source);
		args.push("--", ...paths);
		return _this13.runGit(args, path, rest);
	}
	/**
	* Push commits to a remote.
	*
	* @param path Repository path.
	* @param opts Push options.
	* @returns Command result from the command runner.
	*/
	async push(path, opts) {
		var _this14 = this;
		const _ref8 = opts !== null && opts !== void 0 ? opts : {}, { remote, branch, setUpstream = true, username, password } = _ref8, rest = _objectWithoutProperties(_ref8, _excluded9);
		if (password && !username) throw new InvalidArgumentError("Username is required when using a password or token for git push.");
		if (username && password) {
			const remoteName = await _this14.resolveRemoteName(path, remote, rest);
			return _this14.withRemoteCredentials(path, remoteName, username, password, rest, () => _this14.runGit(buildPushArgs(remoteName, {
				remote,
				branch,
				setUpstream
			}), path, rest));
		}
		try {
			return await _this14.runGit(buildPushArgs(void 0, {
				remote,
				branch,
				setUpstream
			}), path, rest);
		} catch (err) {
			if (isAuthFailure(err)) throw new GitAuthError(buildAuthErrorMessage("push", Boolean(username) && !password));
			if (isMissingUpstream(err)) throw new GitUpstreamError(buildUpstreamErrorMessage("push"));
			throw err;
		}
	}
	/**
	* Pull changes from a remote.
	*
	* @param path Repository path.
	* @param opts Pull options.
	* @returns Command result from the command runner.
	*/
	async pull(path, opts) {
		var _this15 = this;
		const _ref9 = opts !== null && opts !== void 0 ? opts : {}, { remote, branch, username, password } = _ref9, rest = _objectWithoutProperties(_ref9, _excluded10);
		if (password && !username) throw new InvalidArgumentError("Username is required when using a password or token for git pull.");
		if (!remote && !branch) {
			if (!await _this15.hasUpstream(path, rest)) throw new GitUpstreamError(buildUpstreamErrorMessage("pull"));
		}
		const buildArgs = (remoteName) => {
			const args = ["pull"];
			const targetRemote = remoteName !== null && remoteName !== void 0 ? remoteName : remote;
			if (targetRemote) args.push(targetRemote);
			if (branch) args.push(branch);
			return args;
		};
		if (username && password) {
			const remoteName = await _this15.resolveRemoteName(path, remote, rest);
			return _this15.withRemoteCredentials(path, remoteName, username, password, rest, () => _this15.runGit(buildArgs(remoteName), path, rest));
		}
		try {
			return await _this15.runGit(buildArgs(), path, rest);
		} catch (err) {
			if (isAuthFailure(err)) throw new GitAuthError(buildAuthErrorMessage("pull", Boolean(username) && !password));
			if (isMissingUpstream(err)) throw new GitUpstreamError(buildUpstreamErrorMessage("pull"));
			throw err;
		}
	}
	/**
	* Set a git config value.
	*
	* Use `scope: "local"` together with `path` to configure a specific repository.
	*
	* @param key Git config key (for example, `"pull.rebase"`).
	* @param value Git config value.
	* @param opts Config options.
	* @returns Command result from the command runner.
	*/
	async setConfig(key, value, opts) {
		var _this16 = this;
		var _opts$scope;
		if (!key) throw new InvalidArgumentError("Git config key is required.");
		const scope = (_opts$scope = opts === null || opts === void 0 ? void 0 : opts.scope) !== null && _opts$scope !== void 0 ? _opts$scope : "global";
		const scopeFlag = getScopeFlag(scope);
		const repoPath = getRepoPathForScope(scope, opts === null || opts === void 0 ? void 0 : opts.path);
		return _this16.runGit([
			"config",
			scopeFlag,
			key,
			value
		], repoPath, opts);
	}
	/**
	* Get a git config value.
	*
	* Returns `undefined` when the key is not set in the requested scope.
	*
	* @param key Git config key (for example, `"pull.rebase"`).
	* @param opts Config options.
	* @returns The config value if present.
	*/
	async getConfig(key, opts) {
		var _this17 = this;
		var _opts$scope2;
		if (!key) throw new InvalidArgumentError("Git config key is required.");
		const scope = (_opts$scope2 = opts === null || opts === void 0 ? void 0 : opts.scope) !== null && _opts$scope2 !== void 0 ? _opts$scope2 : "global";
		const scopeFlag = getScopeFlag(scope);
		const repoPath = getRepoPathForScope(scope, opts === null || opts === void 0 ? void 0 : opts.path);
		const cmd = `${buildGitCommand([
			"config",
			scopeFlag,
			"--get",
			key
		], repoPath)} || true`;
		const trimmed = (await _this17.runShell(cmd, opts)).stdout.trim();
		return trimmed.length > 0 ? trimmed : void 0;
	}
	/**
	* Dangerously authenticate git globally via the credential helper.
	*
	* This persists credentials in the credential store.
	* Prefer short-lived credentials when possible.
	*
	* @param opts Authentication options.
	* @returns Command result from the command runner.
	*/
	async dangerouslyAuthenticate(opts) {
		var _this18 = this;
		const { username, password, host, protocol } = opts, rest = _objectWithoutProperties(opts, _excluded11);
		if (!username || !password) throw new InvalidArgumentError("Both username and password are required to authenticate git.");
		const targetHost = (host !== null && host !== void 0 ? host : "github.com").trim();
		const credentialInput = [
			`protocol=${(protocol !== null && protocol !== void 0 ? protocol : "https").trim()}`,
			`host=${targetHost}`,
			`username=${username}`,
			`password=${password}`,
			"",
			""
		].join("\n");
		await _this18.runGit([
			"config",
			"--global",
			"credential.helper",
			"store"
		], void 0, rest);
		const approveCmd = `printf %s ${shellQuote(credentialInput)} | ${buildGitCommand(["credential", "approve"])}`;
		return _this18.runShell(approveCmd, rest);
	}
	/**
	* Configure git user name and email.
	*
	* @param name Git user name.
	* @param email Git user email.
	* @param opts Config options.
	* @returns Command result from the command runner.
	*/
	async configureUser(name, email, opts) {
		var _this19 = this;
		var _opts$scope3;
		if (!name || !email) throw new InvalidArgumentError("Both name and email are required.");
		const scope = (_opts$scope3 = opts === null || opts === void 0 ? void 0 : opts.scope) !== null && _opts$scope3 !== void 0 ? _opts$scope3 : "global";
		const configOpts = _objectSpread2(_objectSpread2({}, opts), {}, { scope });
		await _this19.setConfig("user.name", name, configOpts);
		return _this19.setConfig("user.email", email, configOpts);
	}
	/**
	* Build and execute a git command inside the sandbox.
	*
	* @param args Git arguments to pass to the git binary.
	* @param repoPath Repository path used with `git -C`, if provided.
	* @param opts Command execution options.
	* @returns Command result from the command runner.
	*/
	async runGit(args, repoPath, opts) {
		var _this20 = this;
		const _ref10 = opts !== null && opts !== void 0 ? opts : {}, { envs } = _ref10, rest = _objectWithoutProperties(_ref10, _excluded12);
		const cmd = buildGitCommand(args, repoPath);
		const mergedEnvs = _objectSpread2(_objectSpread2({}, DEFAULT_GIT_ENV), envs !== null && envs !== void 0 ? envs : {});
		return _this20.commands.run(cmd, _objectSpread2(_objectSpread2({}, rest), {}, { envs: mergedEnvs }));
	}
	/**
	* Execute a raw shell command while applying default git environment variables.
	* 
	Note: We can likely just modify runGit later to allow appending commands to the git but for now it's separate.
	*/
	async runShell(cmd, opts) {
		var _this21 = this;
		const _ref11 = opts !== null && opts !== void 0 ? opts : {}, { envs } = _ref11, rest = _objectWithoutProperties(_ref11, _excluded13);
		const mergedEnvs = _objectSpread2(_objectSpread2({}, DEFAULT_GIT_ENV), envs !== null && envs !== void 0 ? envs : {});
		return _this21.commands.run(cmd, _objectSpread2(_objectSpread2({}, rest), {}, { envs: mergedEnvs }));
	}
	async getRemoteUrl(path, remote, opts) {
		const url = (await this.runGit([
			"remote",
			"get-url",
			remote
		], path, opts)).stdout.trim();
		if (!url) throw new InvalidArgumentError(`Remote "${remote}" URL not found in repository.`);
		return url;
	}
	async resolveRemoteName(path, remote, opts) {
		var _this23 = this;
		if (remote) return remote;
		const remotes = (await _this23.runGit(["remote"], path, opts)).stdout.split("\n").map((line) => line.trim()).filter(Boolean);
		if (remotes.length === 1) return remotes[0];
		throw new InvalidArgumentError("Remote is required when using username/password and the repository has multiple remotes.");
	}
	async withRemoteCredentials(path, remote, username, password, opts, operation) {
		var _this24 = this;
		const originalUrl = await _this24.getRemoteUrl(path, remote, opts);
		const credentialUrl = withCredentials(originalUrl, username, password);
		await _this24.runGit([
			"remote",
			"set-url",
			remote,
			credentialUrl
		], path, opts);
		let result;
		let operationError;
		try {
			result = await operation();
		} catch (err) {
			operationError = err;
		}
		let restoreError;
		try {
			await _this24.runGit([
				"remote",
				"set-url",
				remote,
				originalUrl
			], path, opts);
		} catch (err) {
			restoreError = err;
		}
		if (operationError) throw operationError;
		if (restoreError) throw restoreError;
		return result;
	}
	async hasUpstream(path, opts) {
		var _this25 = this;
		try {
			return (await _this25.runGit([
				"rev-parse",
				"--abbrev-ref",
				"--symbolic-full-name",
				"@{u}"
			], path, opts)).stdout.trim().length > 0;
		} catch (_unused) {
			return false;
		}
	}
};
//#endregion
//#region src/volume/client.ts
const REQUEST_TIMEOUT_MS = 6e4;
const FILE_TIMEOUT_MS = 36e5;
var VolumeConnectionConfig = class VolumeConnectionConfig {
	constructor(volume, opts) {
		var _ref, _opts$debug, _opts$requestTimeoutM;
		_defineProperty(this, "domain", void 0);
		_defineProperty(this, "debug", void 0);
		_defineProperty(this, "apiUrl", void 0);
		_defineProperty(this, "token", void 0);
		_defineProperty(this, "headers", void 0);
		_defineProperty(this, "logger", void 0);
		_defineProperty(this, "requestTimeoutMs", void 0);
		_defineProperty(this, "signal", void 0);
		_defineProperty(this, "proxy", void 0);
		this.domain = (opts === null || opts === void 0 ? void 0 : opts.domain) || volume.domain || VolumeConnectionConfig.domain;
		this.debug = (_ref = (_opts$debug = opts === null || opts === void 0 ? void 0 : opts.debug) !== null && _opts$debug !== void 0 ? _opts$debug : volume.debug) !== null && _ref !== void 0 ? _ref : VolumeConnectionConfig.debug;
		this.apiUrl = (opts === null || opts === void 0 ? void 0 : opts.apiUrl) || VolumeConnectionConfig.volumeApiUrl || (this.debug ? "http://localhost:8080" : `https://api.${this.domain}`);
		this.token = (opts === null || opts === void 0 ? void 0 : opts.token) || volume.token;
		this.headers = opts === null || opts === void 0 ? void 0 : opts.headers;
		this.logger = opts === null || opts === void 0 ? void 0 : opts.logger;
		this.requestTimeoutMs = (_opts$requestTimeoutM = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM !== void 0 ? _opts$requestTimeoutM : REQUEST_TIMEOUT_MS;
		this.signal = opts === null || opts === void 0 ? void 0 : opts.signal;
		this.proxy = (opts === null || opts === void 0 ? void 0 : opts.proxy) || volume.proxy;
	}
	static get domain() {
		return getEnvVar("E2B_DOMAIN") || "e2b.app";
	}
	static get debug() {
		return (getEnvVar("E2B_DEBUG") || "false").toLowerCase() === "true";
	}
	static get volumeApiUrl() {
		return getEnvVar("E2B_VOLUME_API_URL");
	}
	getSignal(requestTimeoutMs, signal) {
		return buildRequestSignal(requestTimeoutMs !== null && requestTimeoutMs !== void 0 ? requestTimeoutMs : this.requestTimeoutMs, signal !== null && signal !== void 0 ? signal : this.signal);
	}
};
/**
* Client for interacting with the E2B Volume API.
*/
var VolumeApiClient = class {
	constructor(config) {
		_defineProperty(this, "api", void 0);
		this.api = createClient({
			baseUrl: config.apiUrl,
			fetch: createApiFetch(config.proxy),
			headers: _objectSpread2(_objectSpread2(_objectSpread2({}, defaultHeaders), config.token && { Authorization: `Bearer ${config.token}` }), config.headers)
		});
		if (config.logger) this.api.use(createApiLogger(config.logger));
	}
};
//#endregion
//#region src/volume/types.ts
/**
* File type enum.
*/
let VolumeFileType = /* @__PURE__ */ function(VolumeFileType) {
	VolumeFileType["UNKNOWN"] = "unknown";
	VolumeFileType["FILE"] = "file";
	VolumeFileType["DIRECTORY"] = "directory";
	VolumeFileType["SYMLINK"] = "symlink";
	return VolumeFileType;
}({});
//#endregion
//#region src/volume/index.ts
/**
* Convert API VolumeEntryStat to SDK VolumeEntryStat.
*/
function convertVolumeEntryStat(entry) {
	return _objectSpread2(_objectSpread2({}, entry), {}, {
		type: entry.type,
		atime: new Date(entry.atime),
		mtime: new Date(entry.mtime),
		ctime: new Date(entry.ctime)
	});
}
/**
* Module for interacting with E2B volumes.
*
* Create a `Volume` instance to interact with a volume by its ID,
* or use the static methods to manage volumes.
*/
var Volume = class extends ClientFactory {
	/**
	* Create a local Volume instance with no API call.
	*
	* @param volumeId volume ID.
	* @param name volume name.
	* @param token volume auth token.
	* @param domain domain for the volume API.
	* @param debug whether to use debug mode.
	* @param proxy proxy URL for the volume content API.
	*/
	constructor(volumeId, name, token, domain, debug, proxy) {
		super();
		_defineProperty(this, "volumeId", void 0);
		_defineProperty(this, "name", void 0);
		_defineProperty(this, "token", void 0);
		_defineProperty(this, "domain", void 0);
		_defineProperty(this, "debug", void 0);
		_defineProperty(this, "proxy", void 0);
		this.volumeId = volumeId;
		this.name = name;
		this.token = token;
		this.domain = domain;
		this.debug = debug;
		this.proxy = proxy;
	}
	/**
	* Create a new volume.
	*
	* @param name name of the volume.
	* @param opts connection options.
	*
	* @returns new Volume instance.
	*/
	static async create(name, opts) {
		var _this = this;
		const apiOpts = _this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/volumes", {
			body: { name },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return new _this(res.data.volumeID, res.data.name, res.data.token, res.data.domain || config.domain, config.debug, config.proxy);
	}
	/**
	* Connect to an existing volume by ID.
	*
	* @param volumeId volume ID.
	* @param opts connection options.
	*
	* @returns Volume instance.
	*/
	static async connect(volumeId, opts) {
		var _this2 = this;
		const apiOpts = _this2.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const { name, token, domain } = await _this2.getInfo(volumeId, apiOpts);
		return new _this2(volumeId, name, token, domain !== null && domain !== void 0 ? domain : config.domain, config.debug, config.proxy);
	}
	/**
	* Get volume information.
	*
	* @param volumeId volume ID.
	* @param opts connection options.
	*
	* @returns volume information.
	*/
	static async getInfo(volumeId, opts) {
		const apiOpts = this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/volumes/{volumeID}", {
			params: { path: { volumeID: volumeId } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (res.response.status === 404) throw new VolumeNotFoundError(`Volume ${volumeId} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		return {
			volumeId: res.data.volumeID,
			name: res.data.name,
			token: res.data.token,
			domain: res.data.domain || void 0
		};
	}
	/**
	* List all volumes.
	*
	* @param opts connection options.
	*
	* @returns list of volume information.
	*/
	static async list(opts) {
		var _this4 = this;
		var _res$data;
		const apiOpts = _this4.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/volumes", { signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal) });
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		return ((_res$data = res.data) !== null && _res$data !== void 0 ? _res$data : []).map((vol) => ({
			volumeId: vol.volumeID,
			name: vol.name
		}));
	}
	/**
	* Destroy a volume.
	*
	* @param volumeId volume ID.
	* @param opts connection options.
	*/
	static async destroy(volumeId, opts) {
		const apiOpts = this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.DELETE("/volumes/{volumeID}", {
			params: { path: { volumeID: volumeId } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (res.response.status === 404) return false;
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		return true;
	}
	/**
	* List directory contents.
	*
	* @param path path to the directory.
	* @param opts connection options.
	* @param [opts.depth] number of layers deep to recurse into the directory (default: 1).
	*
	* @returns list of entries in the directory.
	*/
	async list(path, opts) {
		var _this6 = this;
		const config = new VolumeConnectionConfig(_this6, opts);
		const res = await new VolumeApiClient(config).api.GET("/volumecontent/{volumeID}/dir", {
			params: {
				path: { volumeID: _this6.volumeId },
				query: {
					path,
					depth: opts === null || opts === void 0 ? void 0 : opts.depth
				}
			},
			signal: config.getSignal()
		});
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		return (Array.isArray(res.data) ? res.data : []).map(convertVolumeEntryStat);
	}
	/**
	* Create a directory.
	*
	* @param path path to the directory to create.
	* @param options directory creation options.
	* @param opts connection options.
	*/
	async makeDir(path, opts) {
		var _this7 = this;
		const config = new VolumeConnectionConfig(_this7, opts);
		const res = await new VolumeApiClient(config).api.POST("/volumecontent/{volumeID}/dir", {
			params: {
				path: { volumeID: _this7.volumeId },
				query: {
					path,
					uid: opts === null || opts === void 0 ? void 0 : opts.uid,
					gid: opts === null || opts === void 0 ? void 0 : opts.gid,
					mode: opts === null || opts === void 0 ? void 0 : opts.mode,
					force: opts === null || opts === void 0 ? void 0 : opts.force
				}
			},
			signal: config.getSignal()
		});
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertVolumeEntryStat(res.data);
	}
	/**
	* Get information about a file or directory.
	*
	* @param path path to the file or directory.
	* @param opts connection options.
	*
	* @returns information about the entry.
	*/
	async getInfo(path, opts) {
		var _this8 = this;
		const config = new VolumeConnectionConfig(_this8, opts);
		const res = await new VolumeApiClient(config).api.GET("/volumecontent/{volumeID}/path", {
			params: {
				path: { volumeID: _this8.volumeId },
				query: { path }
			},
			signal: config.getSignal()
		});
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertVolumeEntryStat(res.data);
	}
	/**
	* Check whether a file or directory exists.
	*
	* Uses {@link getInfo} under the hood. Returns `true` if the path exists,
	* `false` if it does not (404). Other errors are rethrown.
	*
	* @param path path to the file or directory.
	* @param opts connection options.
	*
	* @returns `true` if the path exists, `false` otherwise.
	*/
	async exists(path, opts) {
		var _this9 = this;
		try {
			await _this9.getInfo(path, opts);
			return true;
		} catch (err) {
			if (err instanceof VolumePathNotFoundError) return false;
			throw err;
		}
	}
	/**
	* Update file or directory metadata.
	*
	* @param path path to the file or directory.
	* @param metadata metadata to update (uid, gid, mode).
	* @param opts connection options.
	*
	* @returns updated entry information.
	*/
	async updateMetadata(path, metadata, opts) {
		var _this10 = this;
		const config = new VolumeConnectionConfig(_this10, opts);
		const res = await new VolumeApiClient(config).api.PATCH("/volumecontent/{volumeID}/path", {
			params: {
				path: { volumeID: _this10.volumeId },
				query: { path }
			},
			body: {
				uid: metadata.uid,
				gid: metadata.gid,
				mode: metadata.mode
			},
			signal: config.getSignal()
		});
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertVolumeEntryStat(res.data);
	}
	async readFile(path, opts) {
		var _this11 = this;
		var _opts$format, _opts$requestTimeoutM;
		const format = (_opts$format = opts === null || opts === void 0 ? void 0 : opts.format) !== null && _opts$format !== void 0 ? _opts$format : "text";
		const config = new VolumeConnectionConfig(_this11, _objectSpread2(_objectSpread2({}, opts), {}, { requestTimeoutMs: (_opts$requestTimeoutM = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM !== void 0 ? _opts$requestTimeoutM : FILE_TIMEOUT_MS }));
		const client = new VolumeApiClient(config);
		if (format === "stream") {
			const { controller, clearStartTimeout, cleanup } = setupRequestController(config.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
			try {
				var _opts$streamIdleTimeo;
				const res = await client.api.GET("/volumecontent/{volumeID}/file", {
					params: {
						path: { volumeID: _this11.volumeId },
						query: { path }
					},
					parseAs: "stream",
					signal: controller.signal
				});
				if (res.response.status === 404) {
					if (res.response.body && !res.response.bodyUsed) await res.response.body.cancel().catch(() => {});
					cleanup();
					throw new VolumePathNotFoundError(`Path ${path} not found`);
				}
				const err = handleApiError(res, VolumeError);
				if (err) {
					if (res.response.body && !res.response.bodyUsed) await res.response.body.cancel().catch(() => {});
					cleanup();
					throw err;
				}
				return wrapStreamWithConnectionCleanup(res.data, {
					clearStartTimeout,
					cleanup,
					controller,
					idleTimeoutMs: (_opts$streamIdleTimeo = opts === null || opts === void 0 ? void 0 : opts.streamIdleTimeoutMs) !== null && _opts$streamIdleTimeo !== void 0 ? _opts$streamIdleTimeo : config.requestTimeoutMs
				});
			} catch (err) {
				cleanup();
				throw err;
			}
		}
		const res = await client.api.GET("/volumecontent/{volumeID}/file", {
			params: {
				path: { volumeID: _this11.volumeId },
				query: { path }
			},
			parseAs: format === "bytes" ? "arrayBuffer" : format,
			signal: config.getSignal()
		});
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		if (format === "bytes") return isArrayBufferLike(res.data) ? new Uint8Array(res.data) : /* @__PURE__ */ new Uint8Array();
		if (format === "text") return typeof res.data === "string" ? res.data : "";
		return isBlobLike(res.data) ? res.data : new Blob([]);
	}
	/**
	* Write content to a file.
	*
	* Writing to a file that doesn't exist creates the file.
	*
	* Writing to a file that already exists overwrites the file.
	*
	* @param path path to the file.
	* @param data data to write to the file. Data can be a string, `ArrayBuffer`, `Blob`, or `ReadableStream`. Outside the browser, `ReadableStream` data is streamed to the API instead of being buffered in memory.
	* @param options file creation options.
	* @param opts connection options.
	*
	* @returns information about the written file
	*/
	async writeFile(path, data, opts) {
		var _this12 = this;
		var _opts$requestTimeoutM2;
		const config = new VolumeConnectionConfig(_this12, _objectSpread2(_objectSpread2({}, opts), {}, { requestTimeoutMs: (_opts$requestTimeoutM2 = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM2 !== void 0 ? _opts$requestTimeoutM2 : FILE_TIMEOUT_MS }));
		const client = new VolumeApiClient(config);
		const { body, streamed } = await toUploadBody(data);
		const signal = streamed ? opts === null || opts === void 0 ? void 0 : opts.signal : config.getSignal();
		const res = await client.api.PUT("/volumecontent/{volumeID}/file", _objectSpread2({
			params: {
				path: { volumeID: _this12.volumeId },
				query: {
					path,
					uid: opts === null || opts === void 0 ? void 0 : opts.uid,
					gid: opts === null || opts === void 0 ? void 0 : opts.gid,
					mode: opts === null || opts === void 0 ? void 0 : opts.mode,
					force: opts === null || opts === void 0 ? void 0 : opts.force
				}
			},
			bodySerializer: () => body,
			body: {},
			headers: { "Content-Type": "application/octet-stream" },
			signal
		}, streamed && { duplex: "half" }));
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
		if (!res.data) throw new Error("Response data is missing");
		return convertVolumeEntryStat(res.data);
	}
	/**
	* Remove a file or directory.
	*
	* @param path path to the file or directory to remove.
	* @param opts connection options.
	*/
	async remove(path, opts) {
		var _this13 = this;
		const config = new VolumeConnectionConfig(_this13, opts);
		const res = await new VolumeApiClient(config).api.DELETE("/volumecontent/{volumeID}/path", {
			params: {
				path: { volumeID: _this13.volumeId },
				query: { path }
			},
			signal: config.getSignal()
		});
		if (res.response.status === 404) throw new VolumePathNotFoundError(`Path ${path} not found`);
		const err = handleApiError(res, VolumeError);
		if (err) throw err;
	}
};
//#endregion
//#region src/envd/http2.ts
const envdFetchers = /* @__PURE__ */ new Map();
const envdRpcFetchers = /* @__PURE__ */ new Map();
const DEFAULT_ENVD_CONNECTION_LIMIT = 10;
const DEFAULT_ENVD_RPC_CONNECTION_LIMIT = 200;
const DEFAULT_ENVD_INFLIGHT_LIMIT = 2e3;
const DEFAULT_ENVD_RPC_INFLIGHT_LIMIT = 2e3;
function createEnvdFetchForRuntime(currentRuntime = runtime, options = {}) {
	return createRuntimeFetch(currentRuntime, () => {
		var _options$connectionLi, _options$inflightLimi;
		return buildDispatchedFetch({
			connections: (_options$connectionLi = options.connectionLimit) !== null && _options$connectionLi !== void 0 ? _options$connectionLi : DEFAULT_ENVD_CONNECTION_LIMIT,
			inflightLimit: (_options$inflightLimi = options.inflightLimit) !== null && _options$inflightLimi !== void 0 ? _options$inflightLimi : 0,
			proxy: options.proxy,
			loadUndici: options.loadUndici
		});
	});
}
function createEnvdFetch(proxy) {
	const key = proxy !== null && proxy !== void 0 ? proxy : "";
	const cached = envdFetchers.get(key);
	if (cached) return cached;
	const envdFetch = createEnvdFetchForRuntime(runtime, {
		inflightLimit: getEnvdInflightLimit(),
		proxy
	});
	envdFetchers.set(key, envdFetch);
	return envdFetch;
}
function createEnvdRpcFetch(proxy) {
	const key = proxy !== null && proxy !== void 0 ? proxy : "";
	const cached = envdRpcFetchers.get(key);
	if (cached) return cached;
	const envdRpcFetch = createEnvdFetchForRuntime(runtime, {
		connectionLimit: getEnvdRpcConnectionLimit(),
		inflightLimit: getEnvdRpcInflightLimit(),
		proxy
	});
	envdRpcFetchers.set(key, envdRpcFetch);
	return envdRpcFetch;
}
function getEnvdRpcConnectionLimit() {
	return parsePositiveIntEnv("E2B_ENVD_RPC_CONNECTIONS", DEFAULT_ENVD_RPC_CONNECTION_LIMIT);
}
/**
* Returns the configured max number of envd REST requests (e.g.
* `files.read`/`files.write`) that can be in flight at once across all
* sandboxes in this SDK process, or `0` to disable the cap.
*
* Defaults to `2000` ({@link DEFAULT_ENVD_INFLIGHT_LIMIT}). Override
* via `E2B_ENVD_INFLIGHT_REQUESTS` env var; set to `0` to disable the cap
* entirely.
*/
function getEnvdInflightLimit() {
	return parseInflightLimitEnv("E2B_ENVD_INFLIGHT_REQUESTS", DEFAULT_ENVD_INFLIGHT_LIMIT);
}
/**
* Returns the configured max number of envd RPC requests that
* can be in flight at once across all sandboxes in this SDK process,
* or `0` to disable the cap.
*
* Defaults to `2000` ({@link DEFAULT_ENVD_RPC_INFLIGHT_LIMIT}). Override
* via `E2B_ENVD_RPC_INFLIGHT_REQUESTS` env var; set to `0` to disable the cap
* entirely.
*/
function getEnvdRpcInflightLimit() {
	return parseInflightLimitEnv("E2B_ENVD_RPC_INFLIGHT_REQUESTS", DEFAULT_ENVD_RPC_INFLIGHT_LIMIT);
}
/**
* @generated from service process.Process
*/
const Process = /*@__PURE__*/ serviceDesc(/* @__PURE__ */ fileDesc("ChVwcm9jZXNzL3Byb2Nlc3MucHJvdG8SB3Byb2Nlc3MiSgoDUFRZEh8KBHNpemUYASABKAsyES5wcm9jZXNzLlBUWS5TaXplGiIKBFNpemUSDAoEY29scxgBIAEoDRIMCgRyb3dzGAIgASgNIqEBCg1Qcm9jZXNzQ29uZmlnEgsKA2NtZBgBIAEoCRIMCgRhcmdzGAIgAygJEi4KBGVudnMYAyADKAsyIC5wcm9jZXNzLlByb2Nlc3NDb25maWcuRW52c0VudHJ5EhAKA2N3ZBgEIAEoCUgAiAEBGisKCUVudnNFbnRyeRILCgNrZXkYASABKAkSDQoFdmFsdWUYAiABKAk6AjgBQgYKBF9jd2QiDQoLTGlzdFJlcXVlc3QiXAoLUHJvY2Vzc0luZm8SJgoGY29uZmlnGAEgASgLMhYucHJvY2Vzcy5Qcm9jZXNzQ29uZmlnEgsKA3BpZBgCIAEoDRIQCgN0YWcYAyABKAlIAIgBAUIGCgRfdGFnIjcKDExpc3RSZXNwb25zZRInCglwcm9jZXNzZXMYASADKAsyFC5wcm9jZXNzLlByb2Nlc3NJbmZvIpcBCgxTdGFydFJlcXVlc3QSJwoHcHJvY2VzcxgBIAEoCzIWLnByb2Nlc3MuUHJvY2Vzc0NvbmZpZxIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBEhAKA3RhZxgDIAEoCUgBiAEBEhIKBXN0ZGluGAQgASgISAKIAQFCBgoEX3B0eUIGCgRfdGFnQggKBl9zdGRpbiJiCg1VcGRhdGVSZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchIeCgNwdHkYAiABKAsyDC5wcm9jZXNzLlBUWUgAiAEBQgYKBF9wdHkiEAoOVXBkYXRlUmVzcG9uc2UirwMKDFByb2Nlc3NFdmVudBIxCgVzdGFydBgBIAEoCzIgLnByb2Nlc3MuUHJvY2Vzc0V2ZW50LlN0YXJ0RXZlbnRIABIvCgRkYXRhGAIgASgLMh8ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRGF0YUV2ZW50SAASLQoDZW5kGAMgASgLMh4ucHJvY2Vzcy5Qcm9jZXNzRXZlbnQuRW5kRXZlbnRIABI0CglrZWVwYWxpdmUYBCABKAsyHy5wcm9jZXNzLlByb2Nlc3NFdmVudC5LZWVwQWxpdmVIABoZCgpTdGFydEV2ZW50EgsKA3BpZBgBIAEoDRpICglEYXRhRXZlbnQSEAoGc3Rkb3V0GAEgASgMSAASEAoGc3RkZXJyGAIgASgMSAASDQoDcHR5GAMgASgMSABCCAoGb3V0cHV0GlsKCEVuZEV2ZW50EhEKCWV4aXRfY29kZRgBIAEoERIOCgZleGl0ZWQYAiABKAgSDgoGc3RhdHVzGAMgASgJEhIKBWVycm9yGAQgASgJSACIAQFCCAoGX2Vycm9yGgsKCUtlZXBBbGl2ZUIHCgVldmVudCI1Cg1TdGFydFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiNwoPQ29ubmVjdFJlc3BvbnNlEiQKBWV2ZW50GAEgASgLMhUucHJvY2Vzcy5Qcm9jZXNzRXZlbnQiYwoQU2VuZElucHV0UmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dCITChFTZW5kSW5wdXRSZXNwb25zZSI3CgxQcm9jZXNzSW5wdXQSDwoFc3RkaW4YASABKAxIABINCgNwdHkYAiABKAxIAEIHCgVpbnB1dCLCAgoSU3RyZWFtSW5wdXRSZXF1ZXN0EjcKBXN0YXJ0GAEgASgLMiYucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QuU3RhcnRFdmVudEgAEjUKBGRhdGEYAiABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5EYXRhRXZlbnRIABI6CglrZWVwYWxpdmUYAyABKAsyJS5wcm9jZXNzLlN0cmVhbUlucHV0UmVxdWVzdC5LZWVwQWxpdmVIABo3CgpTdGFydEV2ZW50EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvchoxCglEYXRhRXZlbnQSJAoFaW5wdXQYAiABKAsyFS5wcm9jZXNzLlByb2Nlc3NJbnB1dBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiFQoTU3RyZWFtSW5wdXRSZXNwb25zZSJfChFTZW5kU2lnbmFsUmVxdWVzdBIpCgdwcm9jZXNzGAEgASgLMhgucHJvY2Vzcy5Qcm9jZXNzU2VsZWN0b3ISHwoGc2lnbmFsGAIgASgOMg8ucHJvY2Vzcy5TaWduYWwiFAoSU2VuZFNpZ25hbFJlc3BvbnNlIj4KEUNsb3NlU3RkaW5SZXF1ZXN0EikKB3Byb2Nlc3MYASABKAsyGC5wcm9jZXNzLlByb2Nlc3NTZWxlY3RvciIUChJDbG9zZVN0ZGluUmVzcG9uc2UiOwoOQ29ubmVjdFJlcXVlc3QSKQoHcHJvY2VzcxgBIAEoCzIYLnByb2Nlc3MuUHJvY2Vzc1NlbGVjdG9yIjsKD1Byb2Nlc3NTZWxlY3RvchINCgNwaWQYASABKA1IABINCgN0YWcYAiABKAlIAEIKCghzZWxlY3RvcipICgZTaWduYWwSFgoSU0lHTkFMX1VOU1BFQ0lGSUVEEAASEgoOU0lHTkFMX1NJR1RFUk0QDxISCg5TSUdOQUxfU0lHS0lMTBAJMpEECgdQcm9jZXNzEjMKBExpc3QSFC5wcm9jZXNzLkxpc3RSZXF1ZXN0GhUucHJvY2Vzcy5MaXN0UmVzcG9uc2USPgoHQ29ubmVjdBIXLnByb2Nlc3MuQ29ubmVjdFJlcXVlc3QaGC5wcm9jZXNzLkNvbm5lY3RSZXNwb25zZTABEjgKBVN0YXJ0EhUucHJvY2Vzcy5TdGFydFJlcXVlc3QaFi5wcm9jZXNzLlN0YXJ0UmVzcG9uc2UwARI5CgZVcGRhdGUSFi5wcm9jZXNzLlVwZGF0ZVJlcXVlc3QaFy5wcm9jZXNzLlVwZGF0ZVJlc3BvbnNlEkoKC1N0cmVhbUlucHV0EhsucHJvY2Vzcy5TdHJlYW1JbnB1dFJlcXVlc3QaHC5wcm9jZXNzLlN0cmVhbUlucHV0UmVzcG9uc2UoARJCCglTZW5kSW5wdXQSGS5wcm9jZXNzLlNlbmRJbnB1dFJlcXVlc3QaGi5wcm9jZXNzLlNlbmRJbnB1dFJlc3BvbnNlEkUKClNlbmRTaWduYWwSGi5wcm9jZXNzLlNlbmRTaWduYWxSZXF1ZXN0GhsucHJvY2Vzcy5TZW5kU2lnbmFsUmVzcG9uc2USRQoKQ2xvc2VTdGRpbhIaLnByb2Nlc3MuQ2xvc2VTdGRpblJlcXVlc3QaGy5wcm9jZXNzLkNsb3NlU3RkaW5SZXNwb25zZUJXCgtjb20ucHJvY2Vzc0IMUHJvY2Vzc1Byb3RvUAGiAgNQWFiqAgdQcm9jZXNzygIHUHJvY2Vzc+ICE1Byb2Nlc3NcR1BCTWV0YWRhdGHqAgdQcm9jZXNzYgZwcm90bzM"), 0);
//#endregion
//#region src/sandbox/commands/pty.ts
/**
* Module for interacting with PTYs (pseudo-terminals) in the sandbox.
*/
var Pty = class {
	constructor(transport, envdApi, connectionConfig) {
		this.transport = transport;
		this.envdApi = envdApi;
		this.connectionConfig = connectionConfig;
		_defineProperty(this, "rpc", void 0);
		_defineProperty(this, "envdVersion", void 0);
		_defineProperty(this, "checkHealth", void 0);
		_defineProperty(this, "defaultPtyConnectionTimeout", 6e4);
		this.rpc = createClient$1(Process, this.transport);
		this.envdVersion = envdApi.version;
		this.checkHealth = () => checkSandboxHealth(this.envdApi);
	}
	/**
	* Create a new PTY (pseudo-terminal).
	*
	* @param opts options for creating the PTY.
	*
	* @returns handle to interact with the PTY.
	*/
	async create(opts) {
		var _this = this;
		var _opts$requestTimeoutM, _opts$envs, _envs$TERM, _envs$LANG, _envs$LC_ALL, _opts$timeoutMs;
		const requestTimeoutMs = (_opts$requestTimeoutM = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM !== void 0 ? _opts$requestTimeoutM : _this.connectionConfig.requestTimeoutMs;
		const envs = _objectSpread2({}, (_opts$envs = opts === null || opts === void 0 ? void 0 : opts.envs) !== null && _opts$envs !== void 0 ? _opts$envs : {});
		envs.TERM = (_envs$TERM = envs.TERM) !== null && _envs$TERM !== void 0 ? _envs$TERM : "xterm-256color";
		envs.LANG = (_envs$LANG = envs.LANG) !== null && _envs$LANG !== void 0 ? _envs$LANG : "C.UTF-8";
		envs.LC_ALL = (_envs$LC_ALL = envs.LC_ALL) !== null && _envs$LC_ALL !== void 0 ? _envs$LC_ALL : "C.UTF-8";
		const { controller, clearStartTimeout, cleanup } = setupRequestController(requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
		const events = _this.rpc.start({
			process: {
				cmd: "/bin/bash",
				args: ["-i", "-l"],
				envs,
				cwd: opts === null || opts === void 0 ? void 0 : opts.cwd
			},
			pty: { size: {
				cols: opts.cols,
				rows: opts.rows
			} }
		}, {
			headers: _objectSpread2(_objectSpread2({}, authenticationHeader(_this.envdVersion, opts === null || opts === void 0 ? void 0 : opts.user)), {}, { [KEEPALIVE_PING_HEADER]: 50 .toString() }),
			signal: controller.signal,
			timeoutMs: (_opts$timeoutMs = opts === null || opts === void 0 ? void 0 : opts.timeoutMs) !== null && _opts$timeoutMs !== void 0 ? _opts$timeoutMs : _this.defaultPtyConnectionTimeout
		});
		try {
			const pid = await handleProcessStartEvent(events);
			clearStartTimeout();
			return new CommandHandle(pid, cleanup, () => _this.kill(pid), events, void 0, void 0, opts.onData, void 0, void 0, _this.checkHealth);
		} catch (err) {
			cleanup();
			throw await handleRpcErrorWithHealthCheck(err, _this.checkHealth);
		}
	}
	/**
	* Connect to a running PTY.
	*
	* @param pid process ID of the PTY to connect to. You can get the list of running PTYs using {@link Commands.list}.
	* @param opts connection options.
	*
	* @returns handle to interact with the PTY.
	*/
	async connect(pid, opts) {
		var _this2 = this;
		var _opts$requestTimeoutM2, _opts$timeoutMs2;
		const { controller, clearStartTimeout, cleanup } = setupRequestController((_opts$requestTimeoutM2 = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM2 !== void 0 ? _opts$requestTimeoutM2 : _this2.connectionConfig.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
		const events = _this2.rpc.connect({ process: { selector: {
			case: "pid",
			value: pid
		} } }, {
			signal: controller.signal,
			headers: { [KEEPALIVE_PING_HEADER]: 50 .toString() },
			timeoutMs: (_opts$timeoutMs2 = opts === null || opts === void 0 ? void 0 : opts.timeoutMs) !== null && _opts$timeoutMs2 !== void 0 ? _opts$timeoutMs2 : _this2.defaultPtyConnectionTimeout
		});
		try {
			const pid = await handleProcessStartEvent(events);
			clearStartTimeout();
			return new CommandHandle(pid, cleanup, () => _this2.kill(pid), events, void 0, void 0, opts === null || opts === void 0 ? void 0 : opts.onData, void 0, void 0, _this2.checkHealth);
		} catch (err) {
			cleanup();
			throw await handleRpcErrorWithHealthCheck(err, _this2.checkHealth);
		}
	}
	/**
	* 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) {
		var _this3 = this;
		try {
			await _this3.rpc.sendInput({
				input: { input: {
					case: "pty",
					value: data
				} },
				process: { selector: {
					case: "pid",
					value: pid
				} }
			}, { signal: _this3.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) });
		} catch (err) {
			throw await handleRpcErrorWithHealthCheck(err, _this3.checkHealth);
		}
	}
	/**
	* 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) {
		var _this4 = this;
		try {
			await _this4.rpc.update({
				process: { selector: {
					case: "pid",
					value: pid
				} },
				pty: { size }
			}, { signal: _this4.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) });
		} catch (err) {
			throw await handleRpcErrorWithHealthCheck(err, _this4.checkHealth);
		}
	}
	/**
	* 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) {
		var _this5 = this;
		try {
			await _this5.rpc.sendSignal({
				process: { selector: {
					case: "pid",
					value: pid
				} },
				signal: 9
			}, { signal: _this5.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) });
			return true;
		} catch (err) {
			if (err instanceof ConnectError) {
				if (err.code === Code.NotFound) return false;
			}
			throw await handleRpcErrorWithHealthCheck(err, _this5.checkHealth);
		}
	}
};
//#endregion
//#region src/sandbox/commands/index.ts
/**
* Module for starting and interacting with commands in the sandbox.
*/
var Commands = class {
	constructor(transport, envdApi, connectionConfig) {
		this.envdApi = envdApi;
		this.connectionConfig = connectionConfig;
		_defineProperty(this, "rpc", void 0);
		_defineProperty(this, "defaultProcessConnectionTimeout", 6e4);
		_defineProperty(this, "envdVersion", void 0);
		_defineProperty(this, "checkHealth", void 0);
		this.rpc = createClient$1(Process, transport);
		this.envdVersion = envdApi.version;
		this.checkHealth = () => checkSandboxHealth(this.envdApi);
	}
	/**
	* @hidden
	* @internal
	*/
	get supportsStdinClose() {
		return compareVersions(this.envdVersion, ENVD_ENVD_CLOSE) >= 0;
	}
	/**
	* List all running commands and PTY sessions.
	*
	* @param opts connection options.
	*
	* @returns list of running commands and PTY sessions.
	*/
	async list(opts) {
		var _this = this;
		try {
			return (await _this.rpc.list({}, { signal: _this.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) })).processes.map((p) => _objectSpread2(_objectSpread2({ 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 await handleRpcErrorWithHealthCheck(err, _this.checkHealth);
		}
	}
	/**
	* 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) {
		var _this2 = this;
		try {
			const payload = typeof data === "string" ? new TextEncoder().encode(data) : data;
			await _this2.rpc.sendInput({
				process: { selector: {
					case: "pid",
					value: pid
				} },
				input: { input: {
					case: "stdin",
					value: payload
				} }
			}, { signal: _this2.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) });
		} catch (err) {
			throw await handleRpcErrorWithHealthCheck(err, _this2.checkHealth);
		}
	}
	/**
	* Close command stdin.
	*
	* This signals EOF to the command. The command must have been started with `stdin: true`.
	*
	* @param pid process ID of the command. You can get the list of running commands using {@link Commands.list}.
	* @param opts connection options.
	*/
	async closeStdin(pid, opts) {
		var _this3 = this;
		if (!_this3.supportsStdinClose) throw new SandboxError(`Sandbox envd version ${_this3.envdVersion} doesn't support closeStdin. Please rebuild your template to pick up the latest sandbox version.`);
		try {
			await _this3.rpc.closeStdin({ process: { selector: {
				case: "pid",
				value: pid
			} } }, { signal: _this3.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) });
		} catch (err) {
			throw await handleRpcErrorWithHealthCheck(err, _this3.checkHealth);
		}
	}
	/**
	* 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) {
		var _this4 = this;
		try {
			await _this4.rpc.sendSignal({
				process: { selector: {
					case: "pid",
					value: pid
				} },
				signal: 9
			}, { signal: _this4.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal) });
			return true;
		} catch (err) {
			if (err instanceof ConnectError) {
				if (err.code === Code.NotFound) return false;
			}
			throw await handleRpcErrorWithHealthCheck(err, _this4.checkHealth);
		}
	}
	/**
	* 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 _this5 = this;
		var _opts$requestTimeoutM, _opts$timeoutMs;
		const { controller, clearStartTimeout, cleanup } = setupRequestController((_opts$requestTimeoutM = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM !== void 0 ? _opts$requestTimeoutM : _this5.connectionConfig.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
		const events = _this5.rpc.connect({ process: { selector: {
			case: "pid",
			value: pid
		} } }, {
			signal: controller.signal,
			headers: { [KEEPALIVE_PING_HEADER]: 50 .toString() },
			timeoutMs: (_opts$timeoutMs = opts === null || opts === void 0 ? void 0 : opts.timeoutMs) !== null && _opts$timeoutMs !== void 0 ? _opts$timeoutMs : _this5.defaultProcessConnectionTimeout
		});
		try {
			const pid = await handleProcessStartEvent(events);
			clearStartTimeout();
			return new CommandHandle(pid, cleanup, () => _this5.kill(pid), events, opts === null || opts === void 0 ? void 0 : opts.onStdout, opts === null || opts === void 0 ? void 0 : opts.onStderr, void 0, (data, stdinOpts) => _this5.sendStdin(pid, data, stdinOpts), (stdinOpts) => _this5.closeStdin(pid, stdinOpts), _this5.checkHealth);
		} catch (err) {
			cleanup();
			throw await handleRpcErrorWithHealthCheck(err, _this5.checkHealth);
		}
	}
	async run(cmd, opts) {
		const proc = await this.start(cmd, opts);
		return (opts === null || opts === void 0 ? void 0 : opts.background) ? proc : proc.wait();
	}
	async start(cmd, opts) {
		var _this7 = this;
		var _opts$requestTimeoutM2, _opts$timeoutMs2;
		if ((opts === null || opts === void 0 ? void 0 : opts.stdin) === false && compareVersions(_this7.envdVersion, "0.3.0") < 0) throw new SandboxError(`Sandbox envd version ${_this7.envdVersion} can't specify stdin, it's always turned on. Please rebuild your template if you need this feature.`);
		const { controller, clearStartTimeout, cleanup } = setupRequestController((_opts$requestTimeoutM2 = opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs) !== null && _opts$requestTimeoutM2 !== void 0 ? _opts$requestTimeoutM2 : _this7.connectionConfig.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
		const events = _this7.rpc.start({
			process: {
				cmd: "/bin/bash",
				cwd: opts === null || opts === void 0 ? void 0 : opts.cwd,
				envs: opts === null || opts === void 0 ? void 0 : opts.envs,
				args: [
					"-l",
					"-c",
					cmd
				]
			},
			stdin: (opts === null || opts === void 0 ? void 0 : opts.stdin) || false
		}, {
			headers: _objectSpread2(_objectSpread2({}, authenticationHeader(_this7.envdVersion, opts === null || opts === void 0 ? void 0 : opts.user)), {}, { [KEEPALIVE_PING_HEADER]: 50 .toString() }),
			signal: controller.signal,
			timeoutMs: (_opts$timeoutMs2 = opts === null || opts === void 0 ? void 0 : opts.timeoutMs) !== null && _opts$timeoutMs2 !== void 0 ? _opts$timeoutMs2 : _this7.defaultProcessConnectionTimeout
		});
		try {
			const pid = await handleProcessStartEvent(events);
			clearStartTimeout();
			return new CommandHandle(pid, cleanup, () => _this7.kill(pid), events, opts === null || opts === void 0 ? void 0 : opts.onStdout, opts === null || opts === void 0 ? void 0 : opts.onStderr, void 0, (data, stdinOpts) => _this7.sendStdin(pid, data, stdinOpts), (stdinOpts) => _this7.closeStdin(pid, stdinOpts), _this7.checkHealth);
		} catch (err) {
			cleanup();
			throw await handleRpcErrorWithHealthCheck(err, _this7.checkHealth);
		}
	}
};
//#endregion
//#region src/sandbox/iam.ts
/**
* Characters a workload token name cannot carry.
*
* The egress proxy reads a placeholder as everything between
* `'${e2b.identity.tokens.'` and the next `}`, then looks that name up in the
* registered tokens. A brace in the name breaks that in both directions: `}`
* ends the placeholder early, so `'a}b'` resolves the unrelated token `'a'` and
* leaves `'b}'` as literal text, and `{` lets a name close its own placeholder
* and open another one, minting a token the caller never referenced. Control
* characters are rejected separately because they cannot appear in an HTTP
* header value at all — the API would answer with an opaque 400.
*/
const INVALID_IAM_TOKEN_NAME_CHARS = /* @__PURE__ */ new RegExp("[{}\\p{Cc}]", "u");
/**
* Properties the language and the runtime read off any object they serialize,
* await, or coerce to a string. A token is never named after them, so reading
* one cannot throw — otherwise `JSON.stringify(iam.tokens)` inside a callback
* would.
*/
const RUNTIME_PROBED_PROPS = /* @__PURE__ */ new Set([
	"toJSON",
	"then",
	"toString",
	"valueOf"
]);
/**
* Stand-in for a runtime-probed name that is not a registered token: it answers
* the probe, and `resolve` decides what using it as a token does — a probe never
* coerces or serializes what it reads, a token reference does one or the other.
*/
function runtimeProbeValue(prop, tokens, resolve) {
	const value = prop === "toString" ? () => Object.prototype.toString.call(tokens()) : prop === "valueOf" ? () => tokens() : {};
	Object.defineProperty(value, Symbol.toPrimitive, { value: resolve });
	return Object.defineProperty(value, "toJSON", {
		value: resolve,
		enumerable: true
	});
}
/**
* Reject a token name that cannot survive the placeholder grammar.
*
* @param name workload token name.
*
* @throws {@link InvalidArgumentError} if the name is empty or carries a brace
* or control character.
*/
function validateIamTokenName(name) {
	if (name.length === 0 || INVALID_IAM_TOKEN_NAME_CHARS.test(name)) throw new InvalidArgumentError(`iam token name ${JSON.stringify(name)} is not usable: a token name cannot be empty or contain '{', '}' or control characters, because it is interpolated into the '\${e2b.identity.tokens.<name>}' placeholder the egress proxy resolves.`);
}
/**
* The placeholder the egress proxy replaces with a freshly minted token. The
* spelling is fixed by the backend: a placeholder can only select a persisted
* named token, never an inline audience or claim.
*/
function iamTokenPlaceholder(name) {
	validateIamTokenName(name);
	return `\${e2b.identity.tokens.${name}}`;
}
/**
* Token name to placeholder map, as exposed to a network `transform` callback.
*
* `tokenNames` are the workload tokens the request registers. Referencing any
* other name throws: the proxy never turns an unregistered name into a token, so
* a typo would surface as a confusing auth failure at the destination instead of
* an error here.
*
* `validate: false` is for the update-network endpoint, whose payload carries no
* `iam` config — the sandbox's registered token names are not known client-side
* there, so any name resolves to its placeholder.
*/
function iamTokenPlaceholders(tokenNames, { validate }) {
	const tokens = {};
	for (const name of tokenNames) tokens[name] = iamTokenPlaceholder(name);
	/** Placeholder when names cannot be checked, otherwise the guard's error. */
	const resolveUnregistered = (prop) => {
		if (!validate) return iamTokenPlaceholder(prop);
		throw new InvalidArgumentError(`Network transform references iam token '${prop}', which is not registered. ${tokenNames.length === 0 ? `Pass it to Sandbox.create as iam: { tokens: { '${prop}': Secret.iamToken({ audience, tokenType }) } }.` : `Registered tokens: ${tokenNames.map((name) => `'${name}'`).join(", ")}.`}`);
	};
	const proxy = new Proxy(tokens, {
		get(target, prop, receiver) {
			if (typeof prop === "string" && !Object.hasOwn(target, prop)) {
				if (RUNTIME_PROBED_PROPS.has(prop)) return runtimeProbeValue(prop, () => proxy, () => resolveUnregistered(prop));
				return resolveUnregistered(prop);
			}
			return Reflect.get(target, prop, receiver);
		},
		has(target, prop) {
			return Object.hasOwn(target, prop);
		}
	});
	return proxy;
}
//#endregion
//#region src/sandbox/sandboxApi.ts
function resolveNetworkSelector(selector, rules) {
	if (selector === void 0) return;
	if (typeof selector === "function") return selector({
		allTraffic: ALL_TRAFFIC,
		rules
	});
	return selector;
}
/**
* Build the context handed to `transform` callbacks. See
* {@link iamTokenPlaceholders} for what `validate` controls.
*/
function buildTransformContext(tokenNames, { validate }) {
	return { iam: { tokens: iamTokenPlaceholders(tokenNames, { validate }) } };
}
function isPlainObject(value) {
	if (typeof value !== "object" || value === null) return false;
	const proto = Object.getPrototypeOf(value);
	return proto === Object.prototype || proto === null;
}
/** Name the shape a `transform` callback returned, for the error message. */
function describeValue(value) {
	var _value$constructor$na, _value$constructor;
	if (value === null) return "null";
	if (typeof value !== "object") return typeof value;
	return Array.isArray(value) ? "array" : (_value$constructor$na = (_value$constructor = value.constructor) === null || _value$constructor === void 0 ? void 0 : _value$constructor.name) !== null && _value$constructor$na !== void 0 ? _value$constructor$na : "object";
}
function resolveRulesForBody(rules, ctx) {
	const out = {};
	for (const [host, hostRules] of rules) out[host] = hostRules.map((rule) => {
		if (rule.transform == null) return {};
		if (typeof rule.transform !== "function") return { transform: rule.transform };
		const transform = rule.transform(ctx);
		if (typeof (transform === null || transform === void 0 ? void 0 : transform.then) === "function") {
			Promise.resolve(transform).catch(() => {});
			throw new InvalidArgumentError(`Network transform callback for '${host}' must be synchronous, it returned a promise. Resolve the value before creating the sandbox.`);
		}
		if (!isPlainObject(transform)) throw new InvalidArgumentError(`Network transform callback for '${host}' must return a transform object, got ${describeValue(transform)}.`);
		return { transform };
	});
	return out;
}
/**
* Rebuild the proxy config from the known fields so stray properties on the
* caller's object never reach the wire and a later mutation of it cannot alter
* the in-flight request. Validation is the server's — it is the only side that
* can tell whether the address resolves, and to where.
*/
function buildEgressProxyBody(egressProxy) {
	return _objectSpread2(_objectSpread2({ address: egressProxy.address }, egressProxy.username !== void 0 ? { username: egressProxy.username } : {}), egressProxy.password !== void 0 ? { password: egressProxy.password } : {});
}
function buildNetworkEgress(network, transformContext) {
	var _network$rules;
	const rules = network.rules instanceof Map ? network.rules : new Map(Object.entries((_network$rules = network.rules) !== null && _network$rules !== void 0 ? _network$rules : {}));
	const allowOut = resolveNetworkSelector(network.allowOut, rules);
	const denyOut = resolveNetworkSelector(network.denyOut, rules);
	return _objectSpread2(_objectSpread2(_objectSpread2(_objectSpread2({}, allowOut !== void 0 ? { allowOut } : {}), denyOut !== void 0 ? { denyOut } : {}), network.egressProxy != null ? { egressProxy: buildEgressProxyBody(network.egressProxy) } : {}), network.rules !== void 0 ? { rules: resolveRulesForBody(rules, transformContext) } : {});
}
/**
* Map the wire proxy config into the SDK-owned shape: `password` is dropped
* because the API never returns it, and the wire's `null` for "no proxy" is
* normalized so the union never reaches a consumer.
*/
function fromApiEgressProxy(egressProxy) {
	if (!egressProxy) return;
	return _objectSpread2({ address: egressProxy.address }, egressProxy.username !== void 0 ? { username: egressProxy.username } : {});
}
function buildNetworkBody(network, iam) {
	var _iam$tokens;
	if (!network) return;
	return _objectSpread2(_objectSpread2(_objectSpread2({}, buildNetworkEgress(network, buildTransformContext(Object.keys((_iam$tokens = iam === null || iam === void 0 ? void 0 : iam.tokens) !== null && _iam$tokens !== void 0 ? _iam$tokens : {}), { validate: true }))), network.allowPublicTraffic !== void 0 ? { allowPublicTraffic: network.allowPublicTraffic } : {}), network.maskRequestHost !== void 0 ? { maskRequestHost: network.maskRequestHost } : {});
}
function buildIamBody(iam) {
	var _iam$tokens2;
	const tokens = {};
	for (const [name, token] of Object.entries((_iam$tokens2 = iam === null || iam === void 0 ? void 0 : iam.tokens) !== null && _iam$tokens2 !== void 0 ? _iam$tokens2 : {})) {
		if (!token) continue;
		if (typeof token.audience !== "string" || typeof token.tokenType !== "string") throw new InvalidArgumentError(`iam token '${name}' must have string 'audience' and 'tokenType' properties.`);
		validateIamTokenName(name);
		tokens[name] = {
			audience: token.audience,
			tokenType: token.tokenType
		};
	}
	if (Object.keys(tokens).length === 0) return;
	return { tokens };
}
function buildNetworkUpdateBody(network) {
	return _objectSpread2(_objectSpread2({}, buildNetworkEgress(network, buildTransformContext([], { validate: false }))), network.allowInternetAccess !== void 0 ? { allow_internet_access: network.allowInternetAccess } : {});
}
var SandboxApi = class extends ClientFactory {
	constructor() {
		super();
	}
	/**
	* 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 _this = this;
		var _res$error;
		const apiOpts = _this.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		if (config.debug) return true;
		const res = await new ApiClient(config).api.DELETE("/sandboxes/{sandboxID}", {
			params: { path: { sandboxID: sandboxId } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error = res.error) === null || _res$error === void 0 ? void 0 : _res$error.code) === 404) return false;
		const err = handleApiError(res);
		if (err) throw err;
		return true;
	}
	/**
	* 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 _this2 = this;
		var _res$error2, _res$data$metadata, _res$data$allowIntern, _res$data$network$rul, _res$data$volumeMount;
		const apiOpts = _this2.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/sandboxes/{sandboxID}", {
			params: { path: { sandboxID: sandboxId } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error2 = res.error) === null || _res$error2 === void 0 ? void 0 : _res$error2.code) === 404) throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`);
		const err = handleApiError(res);
		if (err) throw err;
		if (!res.data) throw new Error("Sandbox not found");
		return _objectSpread2(_objectSpread2({
			sandboxId: res.data.sandboxID,
			templateId: res.data.templateID
		}, res.data.alias && { name: res.data.alias }), {}, {
			metadata: (_res$data$metadata = res.data.metadata) !== null && _res$data$metadata !== void 0 ? _res$data$metadata : {},
			allowInternetAccess: (_res$data$allowIntern = res.data.allowInternetAccess) !== null && _res$data$allowIntern !== void 0 ? _res$data$allowIntern : void 0,
			envdVersion: res.data.envdVersion,
			startedAt: new Date(res.data.startedAt),
			endAt: new Date(res.data.endAt),
			state: res.data.state,
			cpuCount: res.data.cpuCount,
			memoryMB: res.data.memoryMB,
			network: res.data.network ? {
				allowOut: res.data.network.allowOut,
				denyOut: res.data.network.denyOut,
				rules: (_res$data$network$rul = res.data.network.rules) !== null && _res$data$network$rul !== void 0 ? _res$data$network$rul : void 0,
				egressProxy: fromApiEgressProxy(res.data.network.egressProxy),
				allowPublicTraffic: res.data.network.allowPublicTraffic,
				maskRequestHost: res.data.network.maskRequestHost
			} : void 0,
			lifecycle: res.data.lifecycle ? {
				onTimeout: res.data.lifecycle.onTimeout,
				autoResume: res.data.lifecycle.autoResume
			} : void 0,
			sandboxDomain: res.data.domain || void 0,
			volumeMounts: (_res$data$volumeMount = res.data.volumeMounts) !== null && _res$data$volumeMount !== void 0 ? _res$data$volumeMount : []
		});
	}
	/**
	* @deprecated Use {@link Sandbox.getInfo} instead.
	*
	* @param sandboxId sandbox ID.
	* @param opts connection options.
	*
	* @returns sandbox information.
	*/
	static async getFullInfo(sandboxId, opts) {
		return await this.getInfo(sandboxId, opts);
	}
	/**
	* 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 _this4 = this;
		var _res$error3, _res$data$map, _res$data;
		const apiOpts = _this4.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		if (config.debug) return [];
		const client = new ApiClient(config);
		const start = (apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.start) ? Math.round(apiOpts.start.getTime() / 1e3) : void 0;
		const end = (apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.end) ? Math.round(apiOpts.end.getTime() / 1e3) : void 0;
		const res = await client.api.GET("/sandboxes/{sandboxID}/metrics", {
			params: {
				path: { sandboxID: sandboxId },
				query: {
					start,
					end
				}
			},
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error3 = res.error) === null || _res$error3 === void 0 ? void 0 : _res$error3.code) === 404) throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`);
		const err = handleApiError(res);
		if (err) throw err;
		return (_res$data$map = (_res$data = res.data) === null || _res$data === void 0 ? void 0 : _res$data.map((metric) => ({
			timestamp: new Date(metric.timestamp),
			cpuUsedPct: metric.cpuUsedPct,
			cpuCount: metric.cpuCount,
			memUsed: metric.memUsed,
			memTotal: metric.memTotal,
			memCache: metric.memCache,
			diskUsed: metric.diskUsed,
			diskTotal: metric.diskTotal
		}))) !== null && _res$data$map !== void 0 ? _res$data$map : [];
	}
	/**
	* 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) {
		var _this5 = this;
		var _res$error4;
		const apiOpts = _this5.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/sandboxes/{sandboxID}/timeout", {
			params: { path: { sandboxID: sandboxId } },
			body: { timeout: timeoutToSeconds(timeoutMs) },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error4 = res.error) === null || _res$error4 === void 0 ? void 0 : _res$error4.code) === 404) throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`);
		const err = handleApiError(res);
		if (err) throw err;
	}
	/**
	* Update the network configuration of a running sandbox.
	*
	* Replaces the current egress configuration atomically — fields that are
	* omitted are cleared on the server.
	*
	* @param sandboxId sandbox ID.
	* @param network new network configuration.
	* @param opts connection options.
	*/
	static async updateNetwork(sandboxId, network, opts) {
		var _this6 = this;
		var _res$error5;
		const apiOpts = _this6.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.PUT("/sandboxes/{sandboxID}/network", {
			params: { path: { sandboxID: sandboxId } },
			body: buildNetworkUpdateBody(network),
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error5 = res.error) === null || _res$error5 === void 0 ? void 0 : _res$error5.code) === 404) throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`);
		const err = handleApiError(res);
		if (err) throw err;
	}
	/**
	* Pause the sandbox specified by sandbox ID.
	*
	* @param sandboxId sandbox ID.
	* @param opts pause options, including `keepMemory` and connection options.
	*
	* @returns `true` if the sandbox got paused, `false` if the sandbox was already paused.
	*/
	static async pause(sandboxId, opts) {
		var _this7 = this;
		var _apiOpts$keepMemory, _res$error6, _res$error7;
		const apiOpts = _this7.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/sandboxes/{sandboxID}/pause", {
			params: { path: { sandboxID: sandboxId } },
			body: { memory: (_apiOpts$keepMemory = apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.keepMemory) !== null && _apiOpts$keepMemory !== void 0 ? _apiOpts$keepMemory : true },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error6 = res.error) === null || _res$error6 === void 0 ? void 0 : _res$error6.code) === 404) throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`);
		if (((_res$error7 = res.error) === null || _res$error7 === void 0 ? void 0 : _res$error7.code) === 409) return false;
		const err = handleApiError(res);
		if (err) throw err;
		return true;
	}
	/**
	* @deprecated Use {@link SandboxApi.pause} instead.
	*/
	static async betaPause(sandboxId, opts) {
		return this.pause(sandboxId, opts);
	}
	/**
	* Create a snapshot from a sandbox.
	*
	* The sandbox will be paused while the snapshot is being created.
	* The snapshot can be used to create new sandboxes with the same state.
	* The snapshot is a persistent image that survives sandbox deletion.
	*
	* @param sandboxId sandbox ID to create snapshot from.
	* @param opts snapshot creation options including optional name and connection options.
	*
	* @returns snapshot information including the snapshot name that can be used with Sandbox.create().
	*/
	static async createSnapshot(sandboxId, opts) {
		var _this9 = this;
		var _res$error8, _names;
		const apiOpts = _this9.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/sandboxes/{sandboxID}/snapshots", {
			params: { path: { sandboxID: sandboxId } },
			body: (apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.name) ? { name: apiOpts.name } : {},
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error8 = res.error) === null || _res$error8 === void 0 ? void 0 : _res$error8.code) === 404) throw new SandboxNotFoundError(`Sandbox ${sandboxId} not found`);
		const err = handleApiError(res);
		if (err) throw err;
		return {
			snapshotId: res.data.snapshotID,
			names: (_names = res.data.names) !== null && _names !== void 0 ? _names : []
		};
	}
	/**
	* List all snapshots.
	*
	* @param opts list options including filters and pagination.
	*
	* @returns paginator for listing snapshots.
	*/
	static listSnapshots(opts) {
		return new SnapshotPaginator(this.resolveOpts(opts));
	}
	/**
	* Delete a snapshot.
	*
	* @param snapshotId snapshot ID.
	* @param opts connection options.
	*
	* @returns `true` if the snapshot was deleted, `false` if it was not found.
	*/
	static async deleteSnapshot(snapshotId, opts) {
		var _this10 = this;
		var _res$error9;
		const apiOpts = _this10.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.DELETE("/templates/{templateID}", {
			params: { path: { templateID: snapshotId } },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error9 = res.error) === null || _res$error9 === void 0 ? void 0 : _res$error9.code) === 404) return false;
		const err = handleApiError(res);
		if (err) throw err;
		return true;
	}
	static async createSandbox(template, timeoutMs, opts) {
		var _this11 = this;
		var _opts$lifecycle, _onTimeout$keepMemory, _opts$lifecycle$autoR, _opts$lifecycle2, _opts$secure, _opts$allowInternetAc;
		const apiOpts = _this11.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const client = new ApiClient(config);
		const requestedOnTimeout = opts === null || opts === void 0 || (_opts$lifecycle = opts.lifecycle) === null || _opts$lifecycle === void 0 ? void 0 : _opts$lifecycle.onTimeout;
		const onTimeoutConfigured = requestedOnTimeout != null;
		const onTimeout = requestedOnTimeout !== null && requestedOnTimeout !== void 0 ? requestedOnTimeout : "kill";
		const action = typeof onTimeout === "string" ? onTimeout : onTimeout.action;
		const hasKeepMemory = typeof onTimeout !== "string" && "keepMemory" in onTimeout;
		const keepMemory = typeof onTimeout !== "string" && "keepMemory" in onTimeout ? (_onTimeout$keepMemory = onTimeout.keepMemory) !== null && _onTimeout$keepMemory !== void 0 ? _onTimeout$keepMemory : true : true;
		const autoResume = (_opts$lifecycle$autoR = opts === null || opts === void 0 || (_opts$lifecycle2 = opts.lifecycle) === null || _opts$lifecycle2 === void 0 ? void 0 : _opts$lifecycle2.autoResume) !== null && _opts$lifecycle$autoR !== void 0 ? _opts$lifecycle$autoR : void 0;
		if (hasKeepMemory && action !== "pause") throw new InvalidArgumentError("onTimeout.keepMemory is only allowed when action is 'pause'.");
		if (autoResume && action !== "pause") throw new InvalidArgumentError("autoResume can only be true when onTimeout action is 'pause'.");
		if (!keepMemory && autoResume) throw new InvalidArgumentError("autoResume: true is not a valid value when keepMemory: false - a filesystem-only snapshot cannot be auto-resumed by traffic and must be resumed explicitly using Sandbox.connect().");
		const iam = buildIamBody(opts === null || opts === void 0 ? void 0 : opts.iam);
		const body = {
			templateID: template,
			metadata: opts === null || opts === void 0 ? void 0 : opts.metadata,
			mcp: opts === null || opts === void 0 ? void 0 : opts.mcp,
			envVars: opts === null || opts === void 0 ? void 0 : opts.envs,
			timeout: timeoutToSeconds(timeoutMs),
			secure: (_opts$secure = opts === null || opts === void 0 ? void 0 : opts.secure) !== null && _opts$secure !== void 0 ? _opts$secure : true,
			allow_internet_access: (_opts$allowInternetAc = opts === null || opts === void 0 ? void 0 : opts.allowInternetAccess) !== null && _opts$allowInternetAc !== void 0 ? _opts$allowInternetAc : true,
			network: buildNetworkBody(opts === null || opts === void 0 ? void 0 : opts.network, iam),
			iam,
			autoPause: onTimeoutConfigured ? action === "pause" : void 0,
			autoPauseMemory: action === "pause" && hasKeepMemory ? keepMemory : void 0,
			autoResume: autoResume === void 0 ? void 0 : { enabled: autoResume }
		};
		if (opts === null || opts === void 0 ? void 0 : opts.volumeMounts) body.volumeMounts = Object.entries(opts.volumeMounts).map(([mountPath, vol]) => ({
			name: typeof vol === "string" ? vol : vol.name,
			path: mountPath
		}));
		const res = await client.api.POST("/sandboxes", {
			body,
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		const err = handleApiError(res);
		if (err) throw err;
		if (compareVersions(res.data.envdVersion, "0.1.0") < 0) {
			await _this11.kill(res.data.sandboxID, apiOpts);
			throw new TemplateError("You need to update the template to use the new SDK.");
		}
		return {
			sandboxId: res.data.sandboxID,
			sandboxDomain: res.data.domain || void 0,
			envdVersion: res.data.envdVersion,
			envdAccessToken: res.data.envdAccessToken,
			trafficAccessToken: res.data.trafficAccessToken || void 0
		};
	}
	static async forkSandbox(sandboxId, timeoutMs, count, opts) {
		var _this12 = this;
		var _res$data2;
		if (count < 1) throw new InvalidArgumentError("count must be at least 1");
		const apiOpts = _this12.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/sandboxes/{sandboxID}/fork", {
			params: { path: { sandboxID: sandboxId } },
			body: {
				timeout: timeoutToSeconds(timeoutMs),
				count
			},
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (res.response.status === 404) {
			var _res$error$message, _res$error10;
			throw new SandboxNotFoundError((_res$error$message = (_res$error10 = res.error) === null || _res$error10 === void 0 ? void 0 : _res$error10.message) !== null && _res$error$message !== void 0 ? _res$error$message : `Sandbox ${sandboxId} not found`);
		}
		const err = handleApiError(res);
		if (err) throw err;
		return ((_res$data2 = res.data) !== null && _res$data2 !== void 0 ? _res$data2 : []).map((result) => {
			if (result.error || !result.sandbox) {
				if (!result.error) return new SandboxError("Failed to start forked sandbox");
				if (result.error.code === 404) return new NotFoundError(`${result.error.code}: ${result.error.message}`);
				return apiErrorFromCode(result.error.code, result.error.message);
			}
			return {
				sandboxId: result.sandbox.sandboxID,
				sandboxDomain: result.sandbox.domain || void 0,
				envdVersion: result.sandbox.envdVersion,
				envdAccessToken: result.sandbox.envdAccessToken,
				trafficAccessToken: result.sandbox.trafficAccessToken || void 0
			};
		});
	}
	static async connectSandbox(sandboxId, opts) {
		var _this13 = this;
		var _apiOpts$timeoutMs, _res$error11;
		const apiOpts = _this13.resolveOpts(opts);
		const timeoutMs = (_apiOpts$timeoutMs = apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.timeoutMs) !== null && _apiOpts$timeoutMs !== void 0 ? _apiOpts$timeoutMs : DEFAULT_SANDBOX_TIMEOUT_MS;
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.POST("/sandboxes/{sandboxID}/connect", {
			params: { path: { sandboxID: sandboxId } },
			body: { timeout: timeoutToSeconds(timeoutMs) },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		if (((_res$error11 = res.error) === null || _res$error11 === void 0 ? void 0 : _res$error11.code) === 404) throw new SandboxNotFoundError(`Paused sandbox ${sandboxId} not found`);
		const err = handleApiError(res);
		if (err) throw err;
		return {
			sandboxId: res.data.sandboxID,
			sandboxDomain: res.data.domain || void 0,
			envdVersion: res.data.envdVersion,
			envdAccessToken: res.data.envdAccessToken,
			trafficAccessToken: res.data.trafficAccessToken || void 0
		};
	}
};
/**
* Paginator for listing sandboxes.
*
* @example
* ```ts
* const paginator = Sandbox.list()
* while (paginator.hasNext) {
*   const sandboxes = await paginator.nextItems()
*   console.log(sandboxes)
* }
* ```
*/
var SandboxPaginator = class extends Paginator {
	constructor(opts) {
		super(opts, opts === null || opts === void 0 ? void 0 : opts.limit, opts === null || opts === void 0 ? void 0 : opts.nextToken);
		_defineProperty(this, "query", void 0);
		_defineProperty(this, "order", void 0);
		this.query = opts === null || opts === void 0 ? void 0 : opts.query;
		this.order = opts === null || opts === void 0 ? void 0 : opts.order;
	}
	async nextItems(opts) {
		var _this14 = this;
		var _this$query, _this$query2, _this$query3, _this$query4, _res$data3;
		if (!_this14.hasNext) throw new Error("No more items to fetch");
		let metadata = void 0;
		if ((_this$query = _this14.query) === null || _this$query === void 0 ? void 0 : _this$query.metadata) {
			const encodedPairs = Object.fromEntries(Object.entries(_this14.query.metadata).map(([key, value]) => [encodeURIComponent(key), encodeURIComponent(value)]));
			metadata = new URLSearchParams(encodedPairs).toString();
		}
		const apiOpts = ConnectionConfig.mergeOpts(_this14.opts, opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/v2/sandboxes", {
			params: { query: {
				metadata,
				state: (_this$query2 = _this14.query) === null || _this$query2 === void 0 ? void 0 : _this$query2.state,
				startedAfter: (_this$query3 = _this14.query) === null || _this$query3 === void 0 || (_this$query3 = _this$query3.startedAfter) === null || _this$query3 === void 0 ? void 0 : _this$query3.toISOString(),
				template: ((_this$query4 = _this14.query) === null || _this$query4 === void 0 ? void 0 : _this$query4.template) || void 0,
				order: _this14.order,
				limit: _this14.limit,
				nextToken: _this14.nextToken
			} },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		const err = handleApiError(res);
		if (err) throw err;
		_this14.updatePagination(res.response);
		return ((_res$data3 = res.data) !== null && _res$data3 !== void 0 ? _res$data3 : []).map((sandbox) => {
			var _sandbox$metadata, _sandbox$volumeMounts;
			return _objectSpread2(_objectSpread2({
				sandboxId: sandbox.sandboxID,
				templateId: sandbox.templateID
			}, sandbox.alias && { name: sandbox.alias }), {}, {
				metadata: (_sandbox$metadata = sandbox.metadata) !== null && _sandbox$metadata !== void 0 ? _sandbox$metadata : {},
				startedAt: new Date(sandbox.startedAt),
				endAt: new Date(sandbox.endAt),
				state: sandbox.state,
				cpuCount: sandbox.cpuCount,
				memoryMB: sandbox.memoryMB,
				envdVersion: sandbox.envdVersion,
				volumeMounts: (_sandbox$volumeMounts = sandbox.volumeMounts) !== null && _sandbox$volumeMounts !== void 0 ? _sandbox$volumeMounts : []
			});
		});
	}
};
/**
* Paginator for listing snapshots.
*
* @example
* ```ts
* const paginator = Sandbox.listSnapshots()
* while (paginator.hasNext) {
*   const snapshots = await paginator.nextItems()
*   console.log(snapshots)
* }
* ```
*/
var SnapshotPaginator = class extends Paginator {
	constructor(opts) {
		super(opts, opts === null || opts === void 0 ? void 0 : opts.limit, opts === null || opts === void 0 ? void 0 : opts.nextToken);
		_defineProperty(this, "sandboxId", void 0);
		_defineProperty(this, "name", void 0);
		this.sandboxId = opts === null || opts === void 0 ? void 0 : opts.sandboxId;
		this.name = opts === null || opts === void 0 ? void 0 : opts.name;
	}
	async nextItems(opts) {
		var _this15 = this;
		var _res$data4;
		if (!_this15.hasNext) throw new Error("No more items to fetch");
		const apiOpts = ConnectionConfig.mergeOpts(_this15.opts, opts);
		const config = new ConnectionConfig(apiOpts);
		const res = await new ApiClient(config).api.GET("/snapshots", {
			params: { query: {
				sandboxID: _this15.sandboxId,
				name: _this15.name,
				limit: _this15.limit,
				nextToken: _this15.nextToken
			} },
			signal: config.getSignal(apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.requestTimeoutMs, apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.signal)
		});
		const err = handleApiError(res);
		if (err) throw err;
		_this15.updatePagination(res.response);
		return ((_res$data4 = res.data) !== null && _res$data4 !== void 0 ? _res$data4 : []).map((snapshot) => {
			var _snapshot$names;
			return {
				snapshotId: snapshot.snapshotID,
				names: (_snapshot$names = snapshot.names) !== null && _snapshot$names !== void 0 ? _snapshot$names : []
			};
		});
	}
};
//#endregion
//#region src/sandbox/index.ts
/**
* E2B cloud sandbox is a secure and isolated cloud environment.
*
* The sandbox allows you to:
* - Access Linux OS
* - Create, list, and delete files and directories
* - Run commands
* - Run git operations
* - Run isolated code
* - Access the internet
*
* Check docs [here](https://e2b.dev/docs).
*
* Use {@link Sandbox.create} to create a new sandbox.
*
* @example
* ```ts
* import { Sandbox } from 'e2b'
*
* const sandbox = await Sandbox.create()
* ```
*/
var Sandbox = class extends SandboxApi {
	/**
	* Use {@link Sandbox.create} to create a new Sandbox instead.
	*
	* @hidden
	* @hide
	* @internal
	* @access protected
	*/
	constructor(opts) {
		var _opts$sandboxDomain, _this$connectionConfi3, _this$connectionConfi4;
		super();
		_defineProperty(this, "files", void 0);
		_defineProperty(this, "commands", void 0);
		_defineProperty(this, "pty", void 0);
		_defineProperty(this, "git", void 0);
		_defineProperty(this, "sandboxId", void 0);
		_defineProperty(this, "sandboxDomain", void 0);
		_defineProperty(this, "trafficAccessToken", void 0);
		_defineProperty(this, "envdPort", 49983);
		_defineProperty(this, "mcpPort", 50005);
		_defineProperty(this, "connectionConfig", void 0);
		_defineProperty(this, "envdAccessToken", void 0);
		_defineProperty(this, "envdApiUrl", void 0);
		_defineProperty(this, "envdDirectUrl", void 0);
		_defineProperty(this, "envdApi", void 0);
		_defineProperty(this, "mcpToken", void 0);
		this.connectionConfig = new ConnectionConfig(opts);
		this.sandboxId = opts.sandboxId;
		this.sandboxDomain = (_opts$sandboxDomain = opts.sandboxDomain) !== null && _opts$sandboxDomain !== void 0 ? _opts$sandboxDomain : this.connectionConfig.domain;
		this.envdAccessToken = opts.envdAccessToken;
		this.trafficAccessToken = opts.trafficAccessToken;
		this.envdApiUrl = this.connectionConfig.getSandboxUrl(this.sandboxId, {
			sandboxDomain: this.sandboxDomain,
			envdPort: this.envdPort
		});
		this.envdDirectUrl = this.connectionConfig.getSandboxDirectUrl(this.sandboxId, {
			sandboxDomain: this.sandboxDomain,
			envdPort: this.envdPort
		});
		const sandboxHeaders = {
			"E2b-Sandbox-Id": this.sandboxId,
			"E2b-Sandbox-Port": this.envdPort.toString()
		};
		const envdFetch = createEnvdFetch(this.connectionConfig.proxy);
		const envdRpcFetch = createEnvdRpcFetch(this.connectionConfig.proxy);
		const rpcTransport = createConnectTransport({
			baseUrl: this.envdApiUrl,
			useBinaryFormat: false,
			interceptors: (opts === null || opts === void 0 ? void 0 : opts.logger) ? [createRpcLogger(opts.logger)] : void 0,
			fetch: (url, options) => {
				var _this$connectionConfi, _this$connectionConfi2, _options;
				const headers = new Headers({ "User-Agent": (_this$connectionConfi = (_this$connectionConfi2 = this.connectionConfig.headers) === null || _this$connectionConfi2 === void 0 ? void 0 : _this$connectionConfi2["User-Agent"]) !== null && _this$connectionConfi !== void 0 ? _this$connectionConfi : "" });
				new Headers(options === null || options === void 0 ? void 0 : options.headers).forEach((value, key) => headers.append(key, value));
				new Headers(sandboxHeaders).forEach((value, key) => headers.append(key, value));
				if (this.envdAccessToken) headers.append("X-Access-Token", this.envdAccessToken);
				options = _objectSpread2(_objectSpread2({}, (_options = options) !== null && _options !== void 0 ? _options : {}), {}, {
					headers,
					redirect: "follow"
				});
				return envdRpcFetch(url, options);
			}
		});
		this.envdApi = new EnvdApiClient({
			apiUrl: this.envdApiUrl,
			logger: opts === null || opts === void 0 ? void 0 : opts.logger,
			envdAccessToken: this.envdAccessToken,
			headers: _objectSpread2({ "User-Agent": (_this$connectionConfi3 = (_this$connectionConfi4 = this.connectionConfig.headers) === null || _this$connectionConfi4 === void 0 ? void 0 : _this$connectionConfi4["User-Agent"]) !== null && _this$connectionConfi3 !== void 0 ? _this$connectionConfi3 : "" }, sandboxHeaders),
			fetch: (request) => envdFetch(request)
		}, { version: opts.envdVersion });
		this.files = new Filesystem(rpcTransport, this.envdApi, this.connectionConfig);
		this.commands = new Commands(rpcTransport, this.envdApi, this.connectionConfig);
		this.pty = new Pty(rpcTransport, this.envdApi, this.connectionConfig);
		this.git = new Git(this.commands);
	}
	/**
	* List sandboxes.
	*
	* By default (no `query.state` set in `opts`), returns sandboxes in both
	* `running` and `paused` states. To filter by state, pass
	* `opts.query.state = [...]`.
	*
	* @param opts connection options, plus optional `query` to filter by
	*   metadata / state / start time / template, `order` to sort by start
	*   time across the whole result set (not within a page), and `limit` /
	*   `nextToken` for pagination.
	*
	* @returns a {@link SandboxPaginator} that yields pages of sandboxes
	*   (running and paused by default). Iterate pages via
	*   `await paginator.nextItems()` while `paginator.hasNext` is `true`.
	*/
	static list(opts) {
		return new SandboxPaginator(this.resolveOpts(opts));
	}
	static async create(templateOrOpts, opts) {
		var _this = this;
		var _templateOrOpts$templ, _apiOpts$timeoutMs;
		const { template, sandboxOpts } = typeof templateOrOpts === "string" ? {
			template: templateOrOpts,
			sandboxOpts: opts
		} : {
			template: (_templateOrOpts$templ = templateOrOpts === null || templateOrOpts === void 0 ? void 0 : templateOrOpts.template) !== null && _templateOrOpts$templ !== void 0 ? _templateOrOpts$templ : (templateOrOpts === null || templateOrOpts === void 0 ? void 0 : templateOrOpts.mcp) ? _this.defaultMcpTemplate : _this.defaultTemplate,
			sandboxOpts: templateOrOpts
		};
		const apiOpts = _this.resolveOpts(sandboxOpts);
		const config = new ConnectionConfig(apiOpts);
		if (config.debug) return new _this(_objectSpread2({
			sandboxId: "debug_sandbox_id",
			envdVersion: ENVD_DEBUG_FALLBACK
		}, config));
		const sandbox = new _this(_objectSpread2(_objectSpread2({}, await _this.createSandbox(template, (_apiOpts$timeoutMs = apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.timeoutMs) !== null && _apiOpts$timeoutMs !== void 0 ? _apiOpts$timeoutMs : _this.defaultSandboxTimeoutMs, apiOpts)), config));
		if (sandboxOpts === null || sandboxOpts === void 0 ? void 0 : sandboxOpts.mcp) {
			sandbox.mcpToken = crypto.randomUUID();
			try {
				var _sandbox$mcpToken;
				await sandbox.commands.run(`mcp-gateway --config ${shellQuote(JSON.stringify(sandboxOpts.mcp))}`, {
					user: "root",
					envs: { GATEWAY_ACCESS_TOKEN: (_sandbox$mcpToken = sandbox.mcpToken) !== null && _sandbox$mcpToken !== void 0 ? _sandbox$mcpToken : "" }
				});
			} catch (error) {
				await sandbox.kill().catch(() => void 0);
				if (error instanceof CommandExitError) throw new SandboxError(`Failed to start MCP gateway: ${error.stderr}`);
				throw error;
			}
		}
		return sandbox;
	}
	/**
	* Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.
	* Sandbox must be either running or be paused.
	*
	* 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 A running sandbox instance
	*
	* @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) {
		var _this2 = this;
		const apiOpts = _this2.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		if (config.debug) return new _this2(_objectSpread2({
			sandboxId,
			envdVersion: ENVD_DEBUG_FALLBACK
		}, config));
		const sandbox = await _this2.connectSandbox(sandboxId, apiOpts);
		return new _this2(_objectSpread2({
			sandboxId,
			sandboxDomain: sandbox.sandboxDomain,
			envdAccessToken: sandbox.envdAccessToken,
			trafficAccessToken: sandbox.trafficAccessToken,
			envdVersion: sandbox.envdVersion
		}, config));
	}
	/**
	* Fork a running sandbox specified by sandbox ID.
	*
	* The sandbox is checkpointed in place (briefly paused, snapshotted with its
	* full memory state, and resumed — its ID and expiration stay untouched) and
	* `count` new sandboxes are created from that snapshot. All forks boot from
	* the same snapshot, so the snapshot is captured once regardless of count.
	*
	* Each fork succeeds or fails independently — the returned array contains
	* one entry per requested fork, either a running {@link Sandbox} instance or
	* an `Error` describing why that fork failed to start
	* (`Promise.allSettled`-style). Per-fork error codes map to the same error
	* classes as other API errors (e.g. 429 to `RateLimitError`).
	*
	* @param sandboxId sandbox ID.
	* @param opts fork options — `count`, `timeoutMs` and connection options.
	*
	* @returns array with one entry per requested fork — a sandbox instance or an error.
	*
	* @example
	* ```ts
	* const sandbox = await Sandbox.create()
	*
	* const [fork1, fork2] = await Sandbox.fork(sandbox.sandboxId, { count: 2 })
	* if (fork1 instanceof Sandbox) {
	*   await fork1.commands.run('echo "hello from fork"')
	* }
	* ```
	*/
	static async fork(sandboxId, opts) {
		var _this3 = this;
		var _apiOpts$timeoutMs2, _apiOpts$count;
		const apiOpts = _this3.resolveOpts(opts);
		const config = new ConnectionConfig(apiOpts);
		return (await _this3.forkSandbox(sandboxId, (_apiOpts$timeoutMs2 = apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.timeoutMs) !== null && _apiOpts$timeoutMs2 !== void 0 ? _apiOpts$timeoutMs2 : _this3.defaultSandboxTimeoutMs, (_apiOpts$count = apiOpts === null || apiOpts === void 0 ? void 0 : apiOpts.count) !== null && _apiOpts$count !== void 0 ? _apiOpts$count : 1, apiOpts)).map((result) => result instanceof Error ? result : new _this3(_objectSpread2(_objectSpread2({}, result), config)));
	}
	/**
	* Connect to a sandbox. If the sandbox is paused, it will be automatically resumed.
	* Sandbox must be either running or be paused.
	*
	* With sandbox ID you can connect to the same sandbox from different places or environments (serverless functions, etc).
	*
	* @param opts connection options.
	*
	* @returns A running sandbox instance
	*
	* @example
	* ```ts
	* const sandbox = await Sandbox.create()
	* await sandbox.betaPause()
	*
	* // Connect to the same sandbox.
	* const sameSandbox = await sandbox.connect()
	* ```
	*/
	async connect(opts) {
		var _this4 = this;
		if (_this4.connectionConfig.debug) return _this4;
		await SandboxApi.connectSandbox(_this4.sandboxId, _this4.resolveApiOpts(opts));
		return _this4;
	}
	/**
	* Fork the sandbox.
	*
	* The sandbox is checkpointed in place (briefly paused, snapshotted with its
	* full memory state, and resumed — its ID and expiration stay untouched) and
	* `count` new sandboxes are created from that snapshot. All forks boot from
	* the same snapshot, so the snapshot is captured once regardless of count.
	*
	* Each fork succeeds or fails independently — the returned array contains
	* one entry per requested fork, either a running {@link Sandbox} instance or
	* an `Error` describing why that fork failed to start
	* (`Promise.allSettled`-style). Per-fork error codes map to the same error
	* classes as other API errors (e.g. 429 to `RateLimitError`).
	*
	* @param opts fork options — `count`, `timeoutMs` and connection options.
	*
	* @returns array with one entry per requested fork — a sandbox instance or an error.
	*
	* @example
	* ```ts
	* const sandbox = await Sandbox.create()
	*
	* const [fork1, fork2] = await sandbox.fork({ count: 2 })
	* if (fork1 instanceof Sandbox) {
	*   await fork1.commands.run('echo "hello from fork"')
	* }
	* ```
	*/
	async fork(opts) {
		var _this5 = this;
		return await _this5.constructor.fork(_this5.sandboxId, _this5.resolveApiOpts(opts));
	}
	/**
	* 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.run('python3 -m http.server 3000', { background: true })
	* // Get the hostname of the HTTP server
	* const serverURL = sandbox.getHost(3000)
	* ```
	*/
	getHost(port) {
		return this.connectionConfig.getHost(this.sandboxId, port, 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) {
		var _this6 = this;
		const signal = _this6.connectionConfig.getSignal(opts === null || opts === void 0 ? void 0 : opts.requestTimeoutMs, opts === null || opts === void 0 ? void 0 : opts.signal);
		const res = await _this6.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.
	*
	* 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) {
		var _this7 = this;
		if (_this7.connectionConfig.debug) return;
		await SandboxApi.setTimeout(_this7.sandboxId, timeoutMs, _this7.resolveApiOpts(opts));
	}
	/**
	* Update the network configuration of the sandbox.
	*
	* Replaces the current egress configuration atomically — fields that are
	* omitted are cleared on the server.
	*
	* @param network new network configuration.
	* @param opts connection options.
	*/
	async updateNetwork(network, opts) {
		var _this8 = this;
		await SandboxApi.updateNetwork(_this8.sandboxId, network, _this8.resolveApiOpts(opts));
	}
	/**
	* Kill the sandbox.
	*
	* @param opts connection options.
	*
	* @returns `true` if the sandbox was killed, `false` if the sandbox was not found.
	*/
	async kill(opts) {
		var _this9 = this;
		if (_this9.connectionConfig.debug) return true;
		return await SandboxApi.kill(_this9.sandboxId, _this9.resolveApiOpts(opts));
	}
	/**
	* Pause a sandbox by its ID.
	*
	* @param opts connection options, plus `keepMemory` to control the snapshot
	* kind. When `opts.keepMemory` is `false`, the in-memory state is dropped and
	* only the filesystem is persisted (a filesystem-only snapshot); resuming such
	* a sandbox cold-boots (reboots) it from disk, losing running processes and
	* open connections. Defaults to `true` (full memory snapshot).
	*
	* @returns `true` if the sandbox got paused, `false` if the sandbox was already paused.
	*
	* @example
	* ```ts
	* const sandbox = await Sandbox.create()
	* await sandbox.pause()
	*
	* // filesystem-only snapshot (resume reboots the sandbox)
	* await sandbox.pause({ keepMemory: false })
	* ```
	*/
	async pause(opts) {
		var _this10 = this;
		return await SandboxApi.pause(_this10.sandboxId, _this10.resolveApiOpts(opts));
	}
	/**
	* @deprecated Use {@link Sandbox.pause} instead.
	*/
	async betaPause(opts) {
		var _this11 = this;
		return await SandboxApi.betaPause(_this11.sandboxId, _this11.resolveApiOpts(opts));
	}
	/**
	* Create a snapshot of the sandbox's current state.
	*
	* The sandbox will be paused while the snapshot is being created.
	* The snapshot can be used to create new sandboxes with the same filesystem and state.
	* Snapshots are persistent and survive sandbox deletion.
	*
	* Use the returned `snapshotId` with `Sandbox.create(snapshotId)` to create a new sandbox from the snapshot.
	*
	* @param opts snapshot creation options including optional name and connection options.
	*
	* @returns snapshot information including the snapshot ID.
	*
	* @example
	* ```ts
	* const sandbox = await Sandbox.create()
	* await sandbox.files.write('/app/state.json', '{"step": 1}')
	*
	* // Create a snapshot
	* const snapshot = await sandbox.createSnapshot({ name: 'my-snapshot' })
	*
	* // Create a new sandbox from the snapshot
	* const newSandbox = await Sandbox.create(snapshot.snapshotId)
	* ```
	*/
	async createSnapshot(opts) {
		var _this12 = this;
		return await SandboxApi.createSnapshot(_this12.sandboxId, _objectSpread2(_objectSpread2({}, _this12.resolveApiOpts(opts)), {}, { name: opts === null || opts === void 0 ? void 0 : opts.name }));
	}
	/**
	* List all snapshots created from this sandbox.
	*
	* @param opts list options.
	*
	* @returns paginator for listing snapshots from this sandbox.
	*/
	listSnapshots(opts) {
		return SandboxApi.listSnapshots(_objectSpread2(_objectSpread2({}, this.resolveApiOpts(opts)), {}, { sandboxId: this.sandboxId }));
	}
	/**
	*
	* Get the MCP URL for the sandbox.
	*
	* @returns MCP URL for the sandbox.
	*/
	getMcpUrl() {
		return `https://${this.getHost(this.mcpPort)}/mcp`;
	}
	/**
	* Get the MCP token for the sandbox.
	*
	* @returns MCP token for the sandbox, or undefined if MCP is not enabled.
	*/
	async getMcpToken() {
		var _this13 = this;
		if (!_this13.mcpToken) _this13.mcpToken = await _this13.files.read("/etc/mcp-gateway/.token", { user: "root" });
		return _this13.mcpToken;
	}
	/**
	* 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 _this14 = this;
		var _opts;
		opts = (_opts = opts) !== null && _opts !== void 0 ? _opts : {};
		const useSignature = !!_this14.envdAccessToken;
		if (!useSignature && opts.useSignatureExpiration != void 0) throw new InvalidArgumentError("Signature expiration can be used only when sandbox is created as secured.");
		let username = opts.user;
		if (username == void 0 && compareVersions(_this14.envdApi.version, "0.4.0") < 0) username = defaultUsername;
		const filePath = path !== null && path !== void 0 ? path : "";
		const fileUrl = _this14.fileUrl(filePath, username);
		if (useSignature) {
			const url = new URL(fileUrl);
			const sig = await getSignature({
				path: filePath,
				operation: "write",
				user: username,
				expirationInSeconds: opts.useSignatureExpiration,
				envdAccessToken: _this14.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 _this15 = this;
		var _opts2;
		opts = (_opts2 = opts) !== null && _opts2 !== void 0 ? _opts2 : {};
		const useSignature = !!_this15.envdAccessToken;
		if (!useSignature && opts.useSignatureExpiration != void 0) throw new InvalidArgumentError("Signature expiration can be used only when sandbox is created as secured.");
		let username = opts.user;
		if (username == void 0 && compareVersions(_this15.envdApi.version, "0.4.0") < 0) username = defaultUsername;
		const fileUrl = _this15.fileUrl(path, username);
		if (useSignature) {
			const url = new URL(fileUrl);
			const sig = await getSignature({
				path,
				operation: "read",
				user: username,
				expirationInSeconds: opts.useSignatureExpiration,
				envdAccessToken: _this15.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) {
		var _this16 = this;
		return await SandboxApi.getInfo(_this16.sandboxId, _this16.resolveApiOpts(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 _this17 = this;
		if (_this17.connectionConfig.debug) return [];
		if (_this17.envdApi.version) {
			if (compareVersions(_this17.envdApi.version, "0.1.5") < 0) throw new TemplateError("You need to update the template to use the new SDK.");
			if (compareVersions(_this17.envdApi.version, "0.2.4") < 0) {
				var _this$connectionConfi5, _this$connectionConfi6;
				(_this$connectionConfi5 = _this17.connectionConfig.logger) === null || _this$connectionConfi5 === void 0 || (_this$connectionConfi6 = _this$connectionConfi5.warn) === null || _this$connectionConfi6 === void 0 || _this$connectionConfi6.call(_this$connectionConfi5, "Disk metrics are not supported in this version of the sandbox, please rebuild the template to get disk metrics.");
			}
		}
		return await SandboxApi.getMetrics(_this17.sandboxId, _this17.resolveApiOpts(opts));
	}
	resolveApiOpts(opts) {
		return ConnectionConfig.mergeOpts(this.connectionConfig, opts);
	}
	fileUrl(path, username) {
		const url = new URL("/files", this.envdDirectUrl);
		if (username) url.searchParams.set("username", username);
		if (path) url.searchParams.set("path", path);
		return url.toString();
	}
};
_defineProperty(Sandbox, "defaultTemplate", "base");
_defineProperty(Sandbox, "defaultMcpTemplate", "mcp-gateway");
_defineProperty(Sandbox, "defaultSandboxTimeoutMs", DEFAULT_SANDBOX_TIMEOUT_MS);
//#endregion
//#region src/template/callable.ts
/**
* Make a template class callable as a factory, so `Template(opts)` keeps
* returning a builder, and keep the statics usable when they are pulled off the
* class on their own (`const { build } = Template`). Everything else —
* construction, `instanceof`, subclassing — goes straight to the class.
*
* @internal
* @hidden
* @hide
*/
function callableTemplate(cls) {
	const bound = /* @__PURE__ */ new WeakMap();
	return new Proxy(cls, {
		apply(target, _thisArg, args) {
			return new target(...args);
		},
		get(target, prop, receiver) {
			const value = Reflect.get(target, prop, receiver);
			if (prop === "prototype" || typeof value !== "function") return value;
			const self = typeof receiver === "function" ? receiver : target;
			let methods = bound.get(self);
			if (!methods) {
				methods = /* @__PURE__ */ new Map();
				bound.set(self, methods);
			}
			let method = methods.get(prop);
			if (!method) {
				method = value.bind(self);
				methods.set(prop, method);
			}
			return method;
		}
	});
}
/**
* Default per-request timeout (in milliseconds) for the file-upload phase
* (PUT to S3 presigned URL) when the caller hasn't supplied
* `requestTimeoutMs`. Large archives can take well over the 60s API
* default, so we use a generous 1-hour bound here.
* @internal
*/
const FILE_UPLOAD_TIMEOUT_MS = 36e5;
//#endregion
//#region src/template/logger.ts
/**
* Represents a single log entry from the template build process.
*/
var LogEntry = class {
	constructor(timestamp, level, message) {
		_defineProperty(this, "timestamp", void 0);
		_defineProperty(this, "level", void 0);
		_defineProperty(this, "message", void 0);
		this.timestamp = timestamp;
		this.level = level;
		this.message = stripAnsi(message);
	}
	toString() {
		return `[${this.timestamp.toISOString()}] [${this.level}] ${this.message}`;
	}
};
/**
* Special log entry indicating the start of a build process.
*/
var LogEntryStart = class extends LogEntry {
	constructor(timestamp, message) {
		super(timestamp, "debug", message);
	}
};
/**
* Special log entry indicating the end of a build process.
*/
var LogEntryEnd = class extends LogEntry {
	constructor(timestamp, message) {
		super(timestamp, "debug", message);
	}
};
/**
* Interval in milliseconds for updating the build timer display.
* @internal
*/
const TIMER_UPDATE_INTERVAL_MS = 150;
/**
* Default minimum log level to display.
* @internal
*/
const DEFAULT_LEVEL = "info";
/**
* Colored labels for each log level.
* @internal
*/
const levels = {
	error: chalk.red("ERROR"),
	warn: chalk.hex("#FF4400")("WARN "),
	info: chalk.hex("#FF8800")("INFO "),
	debug: chalk.gray("DEBUG")
};
/**
* Numeric ordering of log levels for comparison (lower = less severe).
* @internal
*/
const level_order = {
	debug: 0,
	info: 1,
	warn: 2,
	error: 3
};
var DefaultBuildLogger = class {
	constructor(minLevel) {
		_defineProperty(this, "minLevel", void 0);
		_defineProperty(this, "state", void 0);
		this.minLevel = minLevel !== null && minLevel !== void 0 ? minLevel : DEFAULT_LEVEL;
		this.state = this.getInitialState();
	}
	logger(logEntry) {
		if (logEntry instanceof LogEntryStart) {
			this.startTimer();
			return;
		}
		if (logEntry instanceof LogEntryEnd) {
			clearInterval(this.state.timerInterval);
			return;
		}
		if (level_order[logEntry.level] < level_order[this.minLevel]) return;
		const formattedLine = this.formatLogLine(logEntry);
		process.stdout.write(`${formattedLine}\n`);
		this.updateTimer();
	}
	getInitialState(timerInterval) {
		return {
			startTime: Date.now(),
			animationFrame: 0,
			timerInterval
		};
	}
	formatTimerLine() {
		return `${((Date.now() - this.state.startTime) / 1e3).toFixed(1)}s`;
	}
	animateStatus() {
		const frames = [
			"⣾",
			"⣽",
			"⣻",
			"⢿",
			"⡿",
			"⣟",
			"⣯",
			"⣷"
		];
		return `${frames[this.state.animationFrame % frames.length]}`;
	}
	formatLogLine(line) {
		return `${this.formatTimerLine().padEnd(5)} | ${chalk.dim(line.timestamp.toLocaleTimeString(void 0, {
			hour: "2-digit",
			minute: "2-digit",
			second: "2-digit"
		}))} ${levels[line.level] || levels[DEFAULT_LEVEL]} ${line.message}`;
	}
	startTimer() {
		if (!process.stdout.isTTY) return;
		const timerInterval = setInterval(this.updateTimer.bind(this), TIMER_UPDATE_INTERVAL_MS);
		this.state = this.getInitialState(timerInterval);
		this.updateTimer();
	}
	updateTimer() {
		if (!process.stdout.isTTY) return;
		this.state.animationFrame++;
		const jumpingSquares = this.animateStatus();
		process.stdout.write(`${jumpingSquares} Building ${this.formatTimerLine()}\r`);
	}
};
/**
* Create a default build logger with animated timer display.
*
* @param options Logger configuration options
* @param options.minLevel Minimum log level to display (default: 'info')
* @returns Logger function that accepts LogEntry instances
*
* @example
* ```ts
* import { Template, defaultBuildLogger } from 'e2b'
*
* const template = Template().fromPythonImage()
*
* await Template.build(template, {
*   alias: 'my-template',
*   onBuildLogs: defaultBuildLogger({ minLevel: 'debug' })
* })
* ```
*/
function defaultBuildLogger(options) {
	const buildLogger = new DefaultBuildLogger(options === null || options === void 0 ? void 0 : options.minLevel);
	return buildLogger.logger.bind(buildLogger);
}
//#endregion
//#region ../../node_modules/.pnpm/error-stack-parser-es@2.0.1/node_modules/error-stack-parser-es/dist/lite.mjs
const FIREFOX_SAFARI_STACK_REGEXP = /(^|@)\S+:\d+/;
const CHROME_IE_STACK_REGEXP = /^\s*at .*(\S+:\d+|\(native\))/m;
const SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code\])?$/;
/**
* Given an Error object, extract the most information from it.
*
* @param {Error} error object
* @param {ParseOptions} options
* @return {Array} of StackFrames
*/
function parse$1(error, options) {
	if (typeof error.stacktrace !== "undefined" || typeof error["opera#sourceloc"] !== "undefined") return parseOpera(error, options);
	else if (error.stack && CHROME_IE_STACK_REGEXP.test(error.stack)) return parseV8OrIE(error, options);
	else if (error.stack) return parseFFOrSafari(error, options);
	else if (options === null || options === void 0 ? void 0 : options.allowEmpty) return [];
	else throw new Error("Cannot parse given Error object");
}
/**
* Separate line and column numbers from a string of the form: (URI:Line:Column)
*/
function extractLocation(urlLike) {
	if (!urlLike.includes(":")) return [
		urlLike,
		void 0,
		void 0
	];
	const parts = /(.+?)(?::(\d+))?(?::(\d+))?$/.exec(urlLike.replace(/[()]/g, ""));
	return [
		parts[1],
		parts[2] || void 0,
		parts[3] || void 0
	];
}
function applySlice(lines, options) {
	if (options && options.slice != null) {
		if (Array.isArray(options.slice)) return lines.slice(options.slice[0], options.slice[1]);
		return lines.slice(0, options.slice);
	}
	return lines;
}
function parseV8OrIE(error, options) {
	return parseV8OrIeString(error.stack, options);
}
function parseV8OrIeString(stack, options) {
	return applySlice(stack.split("\n").filter((line) => {
		return !!line.match(CHROME_IE_STACK_REGEXP);
	}), options).map((line) => {
		if (line.includes("(eval ")) line = line.replace(/eval code/g, "eval").replace(/(\(eval at [^()]*)|(,.*$)/g, "");
		let sanitizedLine = line.replace(/^\s+/, "").replace(/\(eval code/g, "(").replace(/^.*?\s+/, "");
		const location = sanitizedLine.match(/ (\(.+\)$)/);
		sanitizedLine = location ? sanitizedLine.replace(location[0], "") : sanitizedLine;
		const locationParts = extractLocation(location ? location[1] : sanitizedLine);
		return {
			function: location && sanitizedLine || void 0,
			file: ["eval", "<anonymous>"].includes(locationParts[0]) ? void 0 : locationParts[0],
			line: locationParts[1] ? +locationParts[1] : void 0,
			col: locationParts[2] ? +locationParts[2] : void 0,
			raw: line
		};
	});
}
function parseFFOrSafari(error, options) {
	return parseFFOrSafariString(error.stack, options);
}
function parseFFOrSafariString(stack, options) {
	return applySlice(stack.split("\n").filter((line) => {
		return !line.match(SAFARI_NATIVE_CODE_REGEXP);
	}), options).map((line) => {
		if (line.includes(" > eval")) line = line.replace(/ line (\d+)(?: > eval line \d+)* > eval:\d+:\d+/g, ":$1");
		if (!line.includes("@") && !line.includes(":")) return { function: line };
		else {
			const functionNameRegex = /(([^\n\r"\u2028\u2029]*".[^\n\r"\u2028\u2029]*"[^\n\r@\u2028\u2029]*(?:@[^\n\r"\u2028\u2029]*"[^\n\r@\u2028\u2029]*)*(?:[\n\r\u2028\u2029][^@]*)?)?[^@]*)@/;
			const matches = line.match(functionNameRegex);
			const functionName = matches && matches[1] ? matches[1] : void 0;
			const locationParts = extractLocation(line.replace(functionNameRegex, ""));
			return {
				function: functionName,
				file: locationParts[0],
				line: locationParts[1] ? +locationParts[1] : void 0,
				col: locationParts[2] ? +locationParts[2] : void 0,
				raw: line
			};
		}
	});
}
function parseOpera(e, options) {
	if (!e.stacktrace || e.message.includes("\n") && e.message.split("\n").length > e.stacktrace.split("\n").length) return parseOpera9(e);
	else if (!e.stack) return parseOpera10(e);
	else return parseOpera11(e, options);
}
function parseOpera9(e, options) {
	const lineRE = /Line (\d+).*script (?:in )?(\S+)/i;
	const lines = e.message.split("\n");
	const result = [];
	for (let i = 2, len = lines.length; i < len; i += 2) {
		const match = lineRE.exec(lines[i]);
		if (match) result.push({
			file: match[2],
			line: +match[1],
			raw: lines[i]
		});
	}
	return applySlice(result, options);
}
function parseOpera10(e, options) {
	const lineRE = /Line (\d+).*script (?:in )?(\S+)(?:: In function (\S+))?$/i;
	const lines = e.stacktrace.split("\n");
	const result = [];
	for (let i = 0, len = lines.length; i < len; i += 2) {
		const match = lineRE.exec(lines[i]);
		if (match) result.push({
			function: match[3] || void 0,
			file: match[2],
			line: match[1] ? +match[1] : void 0,
			raw: lines[i]
		});
	}
	return applySlice(result, options);
}
function parseOpera11(error, options) {
	return applySlice(error.stack.split("\n").filter((line) => {
		return !!line.match(FIREFOX_SAFARI_STACK_REGEXP) && !line.match(/^Error created at/);
	}), options).map((line) => {
		const tokens = line.split("@");
		const locationParts = extractLocation(tokens.pop());
		const functionCall = tokens.shift() || "";
		const functionName = functionCall.replace(/<anonymous function(: (\w+))?>/, "$2").replace(/\([^)]*\)/g, "") || void 0;
		let argsRaw;
		if (/\([^)]*\)/.test(functionCall)) argsRaw = functionCall.replace(/^[^(]+\(([^)]*)\)$/, "$1");
		return {
			function: functionName,
			args: argsRaw === void 0 || argsRaw === "[arguments not available]" ? void 0 : argsRaw.split(","),
			file: locationParts[0],
			line: locationParts[1] ? +locationParts[1] : void 0,
			col: locationParts[2] ? +locationParts[2] : void 0,
			raw: line
		};
	});
}
//#endregion
//#region ../../node_modules/.pnpm/error-stack-parser-es@2.0.1/node_modules/error-stack-parser-es/dist/index.mjs
function stackframesLiteToStackframes(liteStackframes) {
	return liteStackframes.map((liteStackframe) => {
		return {
			functionName: liteStackframe.function,
			args: liteStackframe.args,
			fileName: liteStackframe.file,
			lineNumber: liteStackframe.line,
			columnNumber: liteStackframe.col,
			source: liteStackframe.raw
		};
	});
}
/**
* Given an Error object, extract the most information from it.
*
* @param {Error} error object
* @return {Array} of StackFrames
*/
function parse(error, options) {
	return stackframesLiteToStackframes(parse$1(error, options));
}
//#endregion
//#region src/template/utils.ts
const _excluded = ["alias"];
/**
* Validate that a source path for copy operations is a relative path that stays
* within the context directory. This prevents path traversal attacks and ensures
* files are copied from within the expected directory.
*
* @param src The source path to validate
* @param stackTrace Optional stack trace for error reporting
* @throws TemplateError if the path is absolute or escapes the context directory
*
* Invalid paths:
* - Absolute paths: /absolute/path, C:\Windows\path
* - Parent directory escapes: ../foo, foo/../../bar, ./foo/../../../bar
*
* Valid paths:
* - Simple relative: foo, foo/bar
* - Current directory prefix: ./foo, ./foo/bar
* - Internal parent refs that don't escape: foo/../bar (stays within context)
*/
function validateRelativePath(src, stackTrace) {
	if (path.isAbsolute(src)) throw new TemplateError(`Invalid source path "${src}": absolute paths are not allowed. Use a relative path within the context directory.`, stackTrace);
	const normalized = path.normalize(src);
	if (normalized === ".." || normalized.startsWith(".." + path.sep)) throw new TemplateError(`Invalid source path "${src}": path escapes the context directory. The path must stay within the context directory.`, stackTrace);
}
/**
* Normalize build arguments from different overload signatures.
* Handles string name or legacy options object with alias.
*
* @param nameOrOptions Name or legacy options with alias
* @param options Optional build options (when first arg is name)
* @returns Object with normalized name, tags, and build options
* @throws TemplateError if no template name is provided
*/
function normalizeBuildArguments(nameOrOptions, options) {
	let name;
	let buildOptions;
	if (typeof nameOrOptions === "string") {
		name = nameOrOptions;
		buildOptions = options !== null && options !== void 0 ? options : {};
	} else {
		const { alias } = nameOrOptions, restOpts = _objectWithoutProperties(nameOrOptions, _excluded);
		name = alias;
		buildOptions = restOpts;
	}
	if (!name || name.length === 0) throw new TemplateError("Name must be provided");
	return {
		name,
		buildOptions
	};
}
/**
* Read and parse a .dockerignore file.
*
* @param contextPath Directory path containing the .dockerignore file
* @returns Array of ignore patterns (empty lines and comments are filtered out)
*/
function readDockerignore(contextPath) {
	const dockerignorePath = path.join(contextPath, ".dockerignore");
	if (!fs.existsSync(dockerignorePath)) return [];
	return fs.readFileSync(dockerignorePath, "utf-8").split("\n").map((line) => line.trim()).filter((line) => line && !line.startsWith("#"));
}
/**
* Normalize path separators to forward slashes for glob patterns (glob expects / even on Windows)
* @param path - The path to normalize
* @returns The normalized path
*/
function normalizePath(path) {
	return path.replace(/\\/g, "/");
}
/**
* Get all files for a given path and ignore patterns.
*
* @param src Path to the source directory
* @param contextPath Base directory for resolving relative paths
* @param ignorePatterns Ignore patterns
* @returns Array of files
*/
async function getAllFilesInPath(src, contextPath, ignorePatterns, includeDirectories = true) {
	const { glob } = await dynamicImport("glob");
	const files = /* @__PURE__ */ new Map();
	const globFiles = await glob(src, {
		ignore: ignorePatterns,
		withFileTypes: true,
		dot: true,
		cwd: contextPath
	});
	for (const file of globFiles) if (file.isDirectory()) {
		if (includeDirectories) files.set(file.fullpath(), file);
		(await glob(normalizePath(path.join(file.relative() || ".", "**/*")), {
			ignore: ignorePatterns,
			withFileTypes: true,
			dot: true,
			cwd: contextPath
		})).forEach((f) => files.set(f.fullpath(), f));
	} else files.set(file.fullpath(), file);
	return Array.from(files.values()).sort((a, b) => a.fullpath() < b.fullpath() ? -1 : a.fullpath() > b.fullpath() ? 1 : 0);
}
/**
* Calculate a hash of files being copied to detect changes for cache invalidation.
* The hash includes file content, metadata (mode, size), and relative paths.
* Note: uid, gid, and mtime are excluded to ensure stable hashes across environments.
*
* @param src Source path pattern for files to copy
* @param dest Destination path where files will be copied
* @param contextPath Base directory for resolving relative paths
* @param ignorePatterns Glob patterns to ignore
* @param resolveSymlinks Whether to resolve symbolic links when hashing
* @param stackTrace Optional stack trace for error reporting
* @returns Hex string hash of all files
* @throws Error if no files match the source pattern
*/
async function calculateFilesHash(src, dest, contextPath, ignorePatterns, resolveSymlinks, stackTrace) {
	const srcPath = path.join(contextPath, src);
	const hash = crypto$1.createHash("sha256");
	const content = `COPY ${src} ${dest}`;
	hash.update(content);
	const files = await getAllFilesInPath(src, contextPath, ignorePatterns, true);
	if (files.length === 0) {
		const error = /* @__PURE__ */ new Error(`No files found in ${srcPath}`);
		if (stackTrace) error.stack = stackTrace;
		throw error;
	}
	const hashStats = (stats) => {
		hash.update(stats.mode.toString());
		hash.update(stats.size.toString());
	};
	for (const file of files) {
		const relativePath = file.relativePosix();
		hash.update(relativePath);
		if (file.isSymbolicLink()) {
			const stats = fs.statSync(file.fullpath(), { throwIfNoEntry: false });
			if (!(resolveSymlinks && ((stats === null || stats === void 0 ? void 0 : stats.isFile()) || (stats === null || stats === void 0 ? void 0 : stats.isDirectory())))) {
				hashStats(fs.lstatSync(file.fullpath()));
				const content = fs.readlinkSync(file.fullpath());
				hash.update(content);
				continue;
			}
		}
		const stats = fs.statSync(file.fullpath());
		hashStats(stats);
		if (stats.isFile()) {
			const content = fs.readFileSync(file.fullpath());
			hash.update(new Uint8Array(content));
		}
	}
	return hash.digest("hex");
}
/**
* Convert a stack-trace file name to a filesystem path.
* In ESM modules, stack frames report file:// URLs.
*/
function frameFileToPath(fileName) {
	return fileName.startsWith("file:") ? url.fileURLToPath(fileName) : fileName;
}
/**
* Check whether a stack-trace file name refers to user code, i.e. a file
* outside the SDK's own directory. Node internals (`node:*`) and native
* frames are never user code.
*/
function isUserFile(fileName, sdkDir) {
	if (fileName.startsWith("node:") || fileName === "native") return false;
	try {
		const relative = path.relative(sdkDir, path.dirname(frameFileToPath(fileName)));
		return relative !== "" && (relative.startsWith("..") || path.isAbsolute(relative));
	} catch (_unused) {
		return false;
	}
}
/**
* Capture the current stack and locate the first frame in user code.
*
* Frames are selected by boundary rather than by fixed depth: the SDK's own
* directory is derived from the top frame (which is always SDK code — this
* module), and the first frame whose file lies outside it is the user's call
* site. This keeps the result stable when transpilers inject extra frames
* (e.g. TS class-field initializers) or runtimes elide delegating frames
* (e.g. Bun's tail-call elision).
*
* @returns Parsed frames and the index of the user's frame, -1 when no user
*   frame is identifiable (e.g. the SDK is bundled into the caller's file)
*/
function captureUserFrames() {
	var _frames$;
	const frames = parse(/* @__PURE__ */ new Error(), { allowEmpty: true });
	const ownFile = (_frames$ = frames[0]) === null || _frames$ === void 0 ? void 0 : _frames$.fileName;
	if (!ownFile) return {
		frames,
		userFrameIndex: -1
	};
	const sdkDir = path.dirname(frameFileToPath(ownFile));
	return {
		frames,
		userFrameIndex: frames.findIndex((frame) => frame.fileName !== void 0 && isUserFile(frame.fileName, sdkDir))
	};
}
/**
* Get the stack trace starting at the caller's frame in user code.
*
* @returns The stack trace starting at the user's frame, or undefined when no
*   user frame is identifiable
*/
function getCallerFrame() {
	const { frames, userFrameIndex } = captureUserFrames();
	if (userFrameIndex === -1) return;
	return frames.slice(userFrameIndex).map((frame) => frame.source).filter((source) => source !== void 0).join("\n");
}
/**
* Get the directory of the caller in user code.
*
* @returns The caller's directory path, or undefined if not available
*/
function getCallerDirectory() {
	const { frames, userFrameIndex } = captureUserFrames();
	const fileName = userFrameIndex === -1 ? void 0 : frames[userFrameIndex].fileName;
	if (!fileName) return;
	return path.dirname(frameFileToPath(fileName));
}
/**
* Convert a numeric file mode to a zero-padded octal string.
*
* @param mode File mode as a number (e.g., 493 for 0o755)
* @returns Zero-padded 4-digit octal string (e.g., "0755")
*
* @example
* ```ts
* padOctal(0o755) // Returns "0755"
* padOctal(0o644) // Returns "0644"
* ```
*/
function padOctal(mode) {
	return mode.toString(8).padStart(4, "0");
}
/**
* Create a gzipped tar archive of files matching a pattern, spooled to a
* temporary file on disk.
*
* Spooling instead of buffering keeps memory bounded and gives the archive a
* known size, so the upload can send an exact `Content-Length`. The caller
* owns the archive's lifetime and must invoke `cleanup` once done with it.
* This mirrors the Python SDK's `tar_file_stream`.
*
* @param fileName Glob pattern for files to include
* @param fileContextPath Base directory for resolving file paths
* @param ignorePatterns Ignore patterns to exclude from the archive
* @param resolveSymlinks Whether to follow symbolic links
* @param gzip Whether to gzip the archive
* @returns The archive path, its size in bytes, and a cleanup callback that
*   removes the spooled archive. Cleanup is best-effort so it can never mask
*   the upload result — a leaked temp dir is non-fatal, the OS reclaims it.
*/
async function spoolTarArchive(fileName, fileContextPath, ignorePatterns, resolveSymlinks, gzip) {
	const { create } = await dynamicImport("tar");
	const filePaths = (await getAllFilesInPath(fileName, fileContextPath, ignorePatterns, true)).map((file) => file.relativePosix());
	const tmpDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "e2b-template-"));
	const tarPath = path.join(tmpDir, "context.tar.gz");
	const cleanup = () => fs.promises.rm(tmpDir, {
		recursive: true,
		force: true
	}).catch(() => {});
	try {
		await create({
			gzip,
			cwd: fileContextPath,
			follow: resolveSymlinks,
			noDirRecurse: true,
			file: tarPath
		}, filePaths);
		const { size } = await fs.promises.stat(tarPath);
		return {
			path: tarPath,
			size,
			cleanup
		};
	} catch (err) {
		await cleanup();
		throw err;
	}
}
/**
* Get the array index for a build step based on its name.
*
* Special steps:
* - BASE_STEP_NAME: Returns 0 (first step)
* - FINALIZE_STEP_NAME: Returns the last index
* - Numeric strings: Converted to number
*
* @param step Build step name or number as string
* @param stackTracesLength Total number of stack traces (used for FINALIZE_STEP_NAME)
* @returns Index for the build step
*/
function getBuildStepIndex(step, stackTracesLength) {
	if (step === "base") return 0;
	if (step === "finalize") return stackTracesLength - 1;
	return Number(step);
}
/**
* Read GCP service account JSON from a file or object.
*
* @param contextPath Base directory for resolving relative file paths
* @param pathOrContent Either a path to a JSON file or a service account object
* @returns Service account JSON as a string
*/
function readGCPServiceAccountJSON(contextPath, pathOrContent) {
	if (typeof pathOrContent === "string") return fs.readFileSync(path.join(contextPath, pathOrContent), "utf-8");
	return JSON.stringify(pathOrContent);
}
//#endregion
//#region src/template/buildApi.ts
async function requestBuild(client, { name, tags, cpuCount, memoryMB }, signal) {
	const requestBuildRes = await client.api.POST("/v3/templates", {
		body: {
			name,
			tags,
			cpuCount,
			memoryMB
		},
		signal
	});
	const error = handleApiError(requestBuildRes, BuildError);
	if (error) throw error;
	if (!requestBuildRes.data) throw new BuildError("Failed to request build");
	return requestBuildRes.data;
}
async function getFileUploadLink(client, { templateID, filesHash }, stackTrace, signal) {
	const fileUploadLinkRes = await client.api.GET("/templates/{templateID}/files/{hash}", {
		params: { path: {
			templateID,
			hash: filesHash
		} },
		signal
	});
	const error = handleApiError(fileUploadLinkRes, FileUploadError, stackTrace);
	if (error) throw error;
	if (!fileUploadLinkRes.data) throw new FileUploadError("Failed to get file upload link", stackTrace);
	return fileUploadLinkRes.data;
}
async function uploadFile(options, stackTrace, abortOpts) {
	const { fileName, url, fileContextPath, ignorePatterns, resolveSymlinks, gzip } = options;
	let cleanup;
	try {
		var _abortOpts$requestTim;
		const tar = await spoolTarArchive(fileName, fileContextPath, ignorePatterns, resolveSymlinks, gzip);
		cleanup = tar.cleanup;
		const signal = buildRequestSignal((_abortOpts$requestTim = abortOpts === null || abortOpts === void 0 ? void 0 : abortOpts.requestTimeoutMs) !== null && _abortOpts$requestTim !== void 0 ? _abortOpts$requestTim : FILE_UPLOAD_TIMEOUT_MS, abortOpts === null || abortOpts === void 0 ? void 0 : abortOpts.signal);
		const res = await putFileStream(url, tar.path, tar.size, signal);
		if (!res.ok) throw new FileUploadError(`Failed to upload file: ${res.statusText}`, stackTrace);
	} catch (error) {
		if (error instanceof FileUploadError) throw error;
		throw new FileUploadError(`Failed to upload file: ${error}`, stackTrace);
	} finally {
		await (cleanup === null || cleanup === void 0 ? void 0 : cleanup());
	}
}
async function putFileStream(url, filePath, size, signal) {
	var _ref;
	const undici = await loadUndici();
	return await ((_ref = undici === null || undici === void 0 ? void 0 : undici.fetch) !== null && _ref !== void 0 ? _ref : fetch)(url, {
		method: "PUT",
		body: stream.Readable.toWeb(fs.createReadStream(filePath)),
		headers: { "Content-Length": size.toString() },
		duplex: "half",
		signal
	});
}
async function triggerBuild(client, { templateID, buildID, template }, signal) {
	const error = handleApiError(await client.api.POST("/v2/templates/{templateID}/builds/{buildID}", {
		params: { path: {
			templateID,
			buildID
		} },
		body: template,
		signal
	}), BuildError);
	if (error) throw error;
}
function mapLogEntry(entry) {
	return new LogEntry(new Date(entry.timestamp), entry.level, entry.message);
}
function mapBuildStatusReason(reason) {
	var _reason$logEntries;
	if (!reason) return;
	return {
		message: reason.message,
		step: reason.step,
		logEntries: ((_reason$logEntries = reason.logEntries) !== null && _reason$logEntries !== void 0 ? _reason$logEntries : []).map(mapLogEntry)
	};
}
async function getBuildStatus(client, { templateID, buildID, logsOffset }, signal) {
	const buildStatusRes = await client.api.GET("/templates/{templateID}/builds/{buildID}/status", {
		params: {
			path: {
				templateID,
				buildID
			},
			query: { logsOffset }
		},
		signal
	});
	const error = handleApiError(buildStatusRes, BuildError);
	if (error) throw error;
	if (!buildStatusRes.data) throw new BuildError("Failed to get build status");
	return {
		buildID: buildStatusRes.data.buildID,
		templateID: buildStatusRes.data.templateID,
		status: buildStatusRes.data.status,
		logEntries: buildStatusRes.data.logEntries.map(mapLogEntry),
		logs: buildStatusRes.data.logs,
		reason: mapBuildStatusReason(buildStatusRes.data.reason)
	};
}
async function checkAliasExists(client, { alias }, signal) {
	const aliasRes = await client.api.GET("/templates/aliases/{alias}", {
		params: { path: { alias } },
		signal
	});
	if (aliasRes.response.status === 404) return false;
	if (aliasRes.response.status === 403) return true;
	const error = handleApiError(aliasRes, TemplateError);
	if (error) throw error;
	return aliasRes.data !== void 0;
}
async function waitForBuildFinish(client, { templateID, buildID, onBuildLogs, logsRefreshFrequency, stackTraces, signal, requestTimeoutMs }) {
	let logsOffset = 0;
	let status = "building";
	const pollStatus = async () => {
		const buildStatus = await getBuildStatus(client, {
			templateID,
			buildID,
			logsOffset
		}, buildRequestSignal(requestTimeoutMs, signal));
		logsOffset += buildStatus.logEntries.length;
		buildStatus.logEntries.forEach((logEntry) => onBuildLogs === null || onBuildLogs === void 0 ? void 0 : onBuildLogs(logEntry));
		return buildStatus;
	};
	while (status === "building" || status === "waiting") {
		signal === null || signal === void 0 || signal.throwIfAborted();
		const buildStatus = await pollStatus();
		status = buildStatus.status;
		switch (status) {
			case "ready":
			case "error": {
				var _buildStatus$reason, _buildStatus$reason$m, _buildStatus$reason2;
				let tailStatus = buildStatus;
				while (tailStatus.logEntries.length > 0) {
					signal === null || signal === void 0 || signal.throwIfAborted();
					tailStatus = await pollStatus();
				}
				if (status === "ready") return;
				let stackError;
				if (((_buildStatus$reason = buildStatus.reason) === null || _buildStatus$reason === void 0 ? void 0 : _buildStatus$reason.step) !== void 0) stackError = stackTraces[getBuildStepIndex(buildStatus.reason.step, stackTraces.length)];
				throw new BuildError((_buildStatus$reason$m = buildStatus === null || buildStatus === void 0 || (_buildStatus$reason2 = buildStatus.reason) === null || _buildStatus$reason2 === void 0 ? void 0 : _buildStatus$reason2.message) !== null && _buildStatus$reason$m !== void 0 ? _buildStatus$reason$m : "Unknown error", stackError);
			}
			case "waiting": break;
		}
		await new Promise((resolve) => setTimeout(resolve, logsRefreshFrequency));
	}
	throw new BuildError("Unknown build error occurred.");
}
async function assignTags(client, { targetName, tags }, signal) {
	const res = await client.api.POST("/templates/tags", {
		body: {
			target: targetName,
			tags
		},
		signal
	});
	const error = handleApiError(res, TemplateError);
	if (error) throw error;
	if (!res.data) throw new TemplateError("Failed to assign tags");
	return {
		buildId: res.data.buildID,
		tags: res.data.tags
	};
}
async function removeTags(client, { name, tags }, signal) {
	const error = handleApiError(await client.api.DELETE("/templates/tags", {
		body: {
			name,
			tags
		},
		signal
	}), TemplateError);
	if (error) throw error;
}
async function getTemplateTags(client, { templateID }, signal) {
	const res = await client.api.GET("/templates/{templateID}/tags", {
		params: { path: { templateID } },
		signal
	});
	const error = handleApiError(res, TemplateError);
	if (error) throw error;
	if (!res.data) throw new TemplateError("Failed to get template tags");
	return res.data.map((item) => ({
		tag: item.tag,
		buildId: item.buildID,
		createdAt: new Date(item.createdAt)
	}));
}
//#endregion
//#region src/template/readycmd.ts
/**
* Class for ready check commands.
*/
var ReadyCmd = class {
	constructor(cmd) {
		_defineProperty(this, "cmd", void 0);
		this.cmd = cmd;
	}
	getCmd() {
		return this.cmd;
	}
};
/**
* Wait for a port to be listening.
* Uses `ss` command to check if a port is open and listening.
*
* @param port Port number to wait for
* @returns ReadyCmd that checks for the port
*
* @example
* ```ts
* import { Template, waitForPort } from 'e2b'
*
* const template = Template()
*   .fromPythonImage()
*   .setStartCmd('python -m http.server 8000', waitForPort(8000))
* ```
*/
function waitForPort(port) {
	return new ReadyCmd(`[ -n "$(ss -Htuln sport = :${port})" ]`);
}
/**
* Wait for a URL to return a specific HTTP status code.
* Uses `curl` to make HTTP requests and check the response status.
*
* @param url URL to check (e.g., 'http://localhost:3000/health')
* @param statusCode Expected HTTP status code (default: 200)
* @returns ReadyCmd that checks the URL
*
* @example
* ```ts
* import { Template, waitForURL } from 'e2b'
*
* const template = Template()
*   .fromNodeImage()
*   .setStartCmd('npm start', waitForURL('http://localhost:3000/health'))
* ```
*/
function waitForURL(url, statusCode = 200) {
	return new ReadyCmd(`curl -s -o /dev/null -w "%{http_code}" ${shellQuote(url)} | grep -q "${statusCode}"`);
}
/**
* Wait for a process with a specific name to be running.
* Uses `pgrep` to check if a process exists.
*
* @param processName Name of the process to wait for
* @returns ReadyCmd that checks for the process
*
* @example
* ```ts
* import { Template, waitForProcess } from 'e2b'
*
* const template = Template()
*   .fromBaseImage()
*   .setStartCmd('./my-daemon', waitForProcess('my-daemon'))
* ```
*/
function waitForProcess(processName) {
	return new ReadyCmd(`pgrep ${shellQuote(processName)} > /dev/null`);
}
/**
* Wait for a file to exist.
* Uses shell test command to check file existence.
*
* @param filename Path to the file to wait for
* @returns ReadyCmd that checks for the file
*
* @example
* ```ts
* import { Template, waitForFile } from 'e2b'
*
* const template = Template()
*   .fromBaseImage()
*   .setStartCmd('./init.sh', waitForFile('/tmp/ready'))
* ```
*/
function waitForFile(filename) {
	return new ReadyCmd(`[ -f ${shellQuote(filename)} ]`);
}
/**
* Wait for a specified timeout before considering the sandbox ready.
* Uses `sleep` command to wait for a fixed duration.
*
* @param timeout Time to wait in milliseconds (minimum: 1000ms / 1 second)
* @returns ReadyCmd that waits for the specified duration
*
* @example
* ```ts
* import { Template, waitForTimeout } from 'e2b'
*
* const template = Template()
*   .fromNodeImage()
*   .setStartCmd('npm start', waitForTimeout(5000)) // Wait 5 seconds
* ```
*/
function waitForTimeout(timeout) {
	return new ReadyCmd(`sleep ${Math.max(1, Math.floor(timeout / 1e3))}`);
}
//#endregion
//#region src/template/dockerfileParser.ts
/**
* Parse a Dockerfile and convert it to Template SDK format
*
* @param dockerfileContentOrPath Either the Dockerfile content as a string,
*                                or a path to a Dockerfile file
* @param templateBuilder Interface providing template builder methods
* @returns Parsed Dockerfile result with base image and instructions
*/
function parseDockerfile(dockerfileContentOrPath, templateBuilder) {
	let dockerfileContent;
	try {
		if (fs.existsSync(dockerfileContentOrPath) && fs.statSync(dockerfileContentOrPath).isFile()) dockerfileContent = fs.readFileSync(dockerfileContentOrPath, "utf-8");
		else dockerfileContent = dockerfileContentOrPath;
	} catch (_unused) {
		dockerfileContent = dockerfileContentOrPath;
	}
	const instructions = DockerfileParser.parse(dockerfileContent).getInstructions();
	const fromInstructions = instructions.filter((instruction) => instruction.getKeyword() === "FROM");
	if (fromInstructions.length > 1) throw new Error("Multi-stage Dockerfiles are not supported");
	if (fromInstructions.length === 0) throw new Error("Dockerfile must contain a FROM instruction");
	const argumentsData = fromInstructions[0].getArguments();
	let baseImage = "e2bdev/base";
	let userChanged = false;
	let workdirChanged = false;
	if (argumentsData && argumentsData.length > 0) baseImage = argumentsData[0].getValue();
	templateBuilder.setUser("root");
	templateBuilder.setWorkdir("/");
	for (const instruction of instructions) {
		const keyword = instruction.getKeyword();
		switch (keyword) {
			case "FROM": break;
			case "RUN":
				handleRunInstruction(instruction, templateBuilder);
				break;
			case "COPY":
			case "ADD":
				handleCopyInstruction(instruction, templateBuilder);
				break;
			case "WORKDIR":
				handleWorkdirInstruction(instruction, templateBuilder);
				workdirChanged = true;
				break;
			case "USER":
				handleUserInstruction(instruction, templateBuilder);
				userChanged = true;
				break;
			case "ENV":
			case "ARG":
				handleEnvInstruction(instruction, templateBuilder);
				break;
			case "EXPOSE": break;
			case "VOLUME": break;
			case "CMD":
			case "ENTRYPOINT":
				handleCmdEntrypointInstruction(instruction, templateBuilder);
				break;
			default:
				console.warn(`Unsupported instruction: ${keyword}`);
				break;
		}
	}
	if (!userChanged) templateBuilder.setUser("user");
	if (!workdirChanged) templateBuilder.setWorkdir("/home/user");
	return { baseImage };
}
function handleRunInstruction(instruction, templateBuilder) {
	const argumentsData = instruction.getArguments();
	if (argumentsData && argumentsData.length > 0) {
		const command = argumentsData.map((arg) => arg.getValue()).join(" ");
		templateBuilder.runCmd(command);
	}
}
function handleCopyInstruction(instruction, templateBuilder) {
	const argumentsData = instruction.getArguments();
	if (argumentsData && argumentsData.length >= 2) {
		const dest = argumentsData[argumentsData.length - 1].getValue();
		const sources = argumentsData.slice(0, -1).map((arg) => arg.getValue());
		let user;
		const chownFlag = instruction.getFlags().find((flag) => flag.getName() === "chown");
		if (chownFlag) {
			var _chownFlag$getValue;
			user = (_chownFlag$getValue = chownFlag.getValue()) !== null && _chownFlag$getValue !== void 0 ? _chownFlag$getValue : void 0;
		}
		for (const src of sources) templateBuilder.copy(src, dest, { user });
	}
}
function handleWorkdirInstruction(instruction, templateBuilder) {
	const argumentsData = instruction.getArguments();
	if (argumentsData && argumentsData.length > 0) {
		const workdir = argumentsData[0].getValue();
		templateBuilder.setWorkdir(workdir);
	}
}
function handleUserInstruction(instruction, templateBuilder) {
	const argumentsData = instruction.getArguments();
	if (argumentsData && argumentsData.length > 0) {
		const user = argumentsData[0].getValue();
		templateBuilder.setUser(user);
	}
}
function handleEnvInstruction(instruction, templateBuilder) {
	const argumentsData = instruction.getArguments();
	const keyword = instruction.getKeyword();
	if (argumentsData && argumentsData.length >= 1) {
		const envVars = {};
		if (argumentsData.length === 2) {
			const firstArg = argumentsData[0].getValue();
			const secondArg = argumentsData[1].getValue();
			if (firstArg.includes("=") && secondArg.includes("=")) for (const arg of argumentsData) {
				const envString = arg.getValue();
				const equalIndex = envString.indexOf("=");
				if (equalIndex > 0) {
					const key = envString.substring(0, equalIndex);
					envVars[key] = envString.substring(equalIndex + 1);
				}
			}
			else envVars[firstArg] = secondArg;
		} else if (argumentsData.length === 1) {
			const envString = argumentsData[0].getValue();
			const equalIndex = envString.indexOf("=");
			if (equalIndex > 0) {
				const key = envString.substring(0, equalIndex);
				envVars[key] = envString.substring(equalIndex + 1);
			} else if (keyword === "ARG" && envString.trim()) {
				const key = envString.trim();
				envVars[key] = "";
			}
		} else for (const arg of argumentsData) {
			const envString = arg.getValue();
			const equalIndex = envString.indexOf("=");
			if (equalIndex > 0) {
				const key = envString.substring(0, equalIndex);
				envVars[key] = envString.substring(equalIndex + 1);
			} else if (keyword === "ARG") {
				const key = envString;
				envVars[key] = "";
			}
		}
		if (Object.keys(envVars).length > 0) templateBuilder.setEnvs(envVars);
	}
}
function handleCmdEntrypointInstruction(instruction, templateBuilder) {
	const argumentsData = instruction.getArguments();
	if (argumentsData && argumentsData.length > 0) {
		let command = argumentsData.map((arg) => arg.getValue()).join(" ");
		try {
			const parsedCommand = JSON.parse(command);
			if (Array.isArray(parsedCommand)) command = parsedCommand.join(" ");
		} catch (_unused2) {}
		templateBuilder.setStartCmd(command, waitForTimeout(2e4));
	}
}
//#endregion
//#region src/template/index.ts
/**
* Builder for E2B sandbox templates, and the entrypoint for the template API.
*
* Exposed as {@link Template}, which can be called as a factory.
*/
var TemplateBase = class extends ClientFactory {
	constructor(options) {
		var _options$fileContextP, _getCallerDirectory, _options$fileIgnorePa;
		super();
		_defineProperty(this, "defaultBaseImage", "e2bdev/base");
		_defineProperty(this, "baseImage", this.defaultBaseImage);
		_defineProperty(this, "baseTemplate", void 0);
		_defineProperty(this, "registryConfig", void 0);
		_defineProperty(this, "startCmd", void 0);
		_defineProperty(this, "readyCmd", void 0);
		_defineProperty(this, "force", false);
		_defineProperty(this, "forceNextLayer", false);
		_defineProperty(this, "instructions", []);
		_defineProperty(this, "fileContextPath", void 0);
		_defineProperty(this, "fileIgnorePatterns", []);
		_defineProperty(this, "logsRefreshFrequency", 200);
		_defineProperty(this, "stackTraces", []);
		this.fileContextPath = (_options$fileContextP = options === null || options === void 0 ? void 0 : options.fileContextPath) !== null && _options$fileContextP !== void 0 ? _options$fileContextP : runtime === "browser" ? "." : (_getCallerDirectory = getCallerDirectory()) !== null && _getCallerDirectory !== void 0 ? _getCallerDirectory : ".";
		this.fileIgnorePatterns = (_options$fileIgnorePa = options === null || options === void 0 ? void 0 : options.fileIgnorePatterns) !== null && _options$fileIgnorePa !== void 0 ? _options$fileIgnorePa : this.fileIgnorePatterns;
	}
	/**
	* Convert a template to JSON representation.
	*
	* @param template The template to convert
	* @param computeHashes Whether to compute file hashes for cache invalidation
	* @returns JSON string representation of the template
	*/
	static toJSON(template, computeHashes = true) {
		return template.toJSON(computeHashes);
	}
	/**
	* Convert a template to Dockerfile format.
	* Note: Templates based on other E2B templates cannot be converted to Dockerfile.
	*
	* @param template The template to convert
	* @returns Dockerfile string representation
	* @throws Error if the template is based on another E2B template
	*/
	static toDockerfile(template) {
		return template.toDockerfile();
	}
	static async build(template, nameOrOptions, options) {
		var _this = this;
		var _this$resolveOpts;
		const { name, buildOptions } = normalizeBuildArguments(nameOrOptions, options);
		const buildOpts = (_this$resolveOpts = _this.resolveOpts(buildOptions)) !== null && _this$resolveOpts !== void 0 ? _this$resolveOpts : {};
		try {
			var _buildOpts$onBuildLog, _buildOpts$onBuildLog2;
			(_buildOpts$onBuildLog = buildOpts.onBuildLogs) === null || _buildOpts$onBuildLog === void 0 || _buildOpts$onBuildLog.call(buildOpts, new LogEntryStart(/* @__PURE__ */ new Date(), "Build started"));
			const baseTemplate = template;
			const config = new ConnectionConfig(buildOpts);
			const client = new ApiClient(config);
			const data = await baseTemplate.build(client, config, name, buildOpts);
			(_buildOpts$onBuildLog2 = buildOpts.onBuildLogs) === null || _buildOpts$onBuildLog2 === void 0 || _buildOpts$onBuildLog2.call(buildOpts, new LogEntry(/* @__PURE__ */ new Date(), "info", "Waiting for logs..."));
			await waitForBuildFinish(client, {
				templateID: data.templateId,
				buildID: data.buildId,
				onBuildLogs: buildOpts.onBuildLogs,
				logsRefreshFrequency: baseTemplate.logsRefreshFrequency,
				stackTraces: baseTemplate.stackTraces,
				signal: buildOpts.signal,
				requestTimeoutMs: config.requestTimeoutMs
			});
			return data;
		} finally {
			var _buildOpts$onBuildLog3;
			(_buildOpts$onBuildLog3 = buildOpts.onBuildLogs) === null || _buildOpts$onBuildLog3 === void 0 || _buildOpts$onBuildLog3.call(buildOpts, new LogEntryEnd(/* @__PURE__ */ new Date(), "Build finished"));
		}
	}
	static async buildInBackground(template, nameOrOptions, options) {
		var _this2 = this;
		var _this$resolveOpts2;
		const { name, buildOptions } = normalizeBuildArguments(nameOrOptions, options);
		const buildOpts = (_this$resolveOpts2 = _this2.resolveOpts(buildOptions)) !== null && _this$resolveOpts2 !== void 0 ? _this$resolveOpts2 : {};
		const config = new ConnectionConfig(buildOpts);
		const client = new ApiClient(config);
		return template.build(client, config, name, buildOpts);
	}
	/**
	* Get the status of a build.
	*
	* @param data Build identifiers
	* @param options Authentication options
	*
	* @example
	* ```ts
	* const status = await Template.getBuildStatus(data, { logsOffset: 0 })
	* ```
	*/
	static async getBuildStatus(data, options) {
		var _this3 = this;
		var _options$logsOffset;
		const config = new ConnectionConfig(_this3.resolveOpts(options));
		return await getBuildStatus(new ApiClient(config), {
			templateID: data.templateId,
			buildID: data.buildId,
			logsOffset: (_options$logsOffset = options === null || options === void 0 ? void 0 : options.logsOffset) !== null && _options$logsOffset !== void 0 ? _options$logsOffset : 0
		}, config.getSignal(void 0, options === null || options === void 0 ? void 0 : options.signal));
	}
	/**
	* Check if a template with the given name exists.
	*
	* @param name Template name to check
	* @param options Authentication options
	* @returns True if the name exists, false otherwise
	*
	* @example
	* ```ts
	* const exists = await Template.exists('my-python-env')
	* if (exists) {
	*   console.log('Template exists!')
	* }
	* ```
	*/
	static async exists(name, options) {
		return this.aliasExists(name, options);
	}
	/**
	* Check if a template with the given alias exists.
	*
	* @param alias Template alias to check
	* @param options Authentication options
	* @returns True if the alias exists, false otherwise
	*
	* @deprecated Use `exists` instead.
	* @example
	* ```ts
	* const exists = await Template.aliasExists('my-python-env')
	* if (exists) {
	*   console.log('Template exists!')
	* }
	* ```
	*/
	static async aliasExists(alias, options) {
		const config = new ConnectionConfig(this.resolveOpts(options));
		return checkAliasExists(new ApiClient(config), { alias }, config.getSignal(void 0, options === null || options === void 0 ? void 0 : options.signal));
	}
	/**
	* Assign tag(s) to an existing template build.
	*
	* @param targetName Template name in 'name:tag' format (the source build to tag from)
	* @param tags Tag or tags to assign
	* @param options Authentication options
	* @returns Tag info with buildId and assigned tags
	*
	* @example
	* ```ts
	* // Assign a single tag
	* await Template.assignTags('my-template:v1.0', 'production')
	*
	* // Assign multiple tags
	* await Template.assignTags('my-template:v1.0', ['production', 'stable'])
	* ```
	*/
	static async assignTags(targetName, tags, options) {
		const config = new ConnectionConfig(this.resolveOpts(options));
		return assignTags(new ApiClient(config), {
			targetName,
			tags: Array.isArray(tags) ? tags : [tags]
		}, config.getSignal(void 0, options === null || options === void 0 ? void 0 : options.signal));
	}
	/**
	* Remove tag(s) from a template.
	*
	* @param name Template name
	* @param tags Tag or tags to remove
	* @param options Authentication options
	*
	* @example
	* ```ts
	* // Remove a single tag
	* await Template.removeTags('my-template', 'production')
	*
	* // Remove multiple tags from a template
	* await Template.removeTags('my-template', ['production', 'staging'])
	* ```
	*/
	static async removeTags(name, tags, options) {
		const config = new ConnectionConfig(this.resolveOpts(options));
		return removeTags(new ApiClient(config), {
			name,
			tags: Array.isArray(tags) ? tags : [tags]
		}, config.getSignal(void 0, options === null || options === void 0 ? void 0 : options.signal));
	}
	/**
	* Get all tags for a template.
	*
	* @param templateId Template ID or name
	* @param options Authentication options
	* @returns Array of tag details including tag name, buildId, and creation date
	*
	* @example
	* ```ts
	* const tags = await Template.getTags('my-template')
	* for (const tag of tags) {
	*   console.log(`Tag: ${tag.tag}, Build: ${tag.buildId}, Created: ${tag.createdAt}`)
	* }
	* ```
	*/
	static async getTags(templateId, options) {
		const config = new ConnectionConfig(this.resolveOpts(options));
		return getTemplateTags(new ApiClient(config), { templateID: templateId }, config.getSignal(void 0, options === null || options === void 0 ? void 0 : options.signal));
	}
	fromDebianImage(variant = "stable") {
		return this.fromImage(`debian:${variant}`);
	}
	fromUbuntuImage(variant = "latest") {
		return this.fromImage(`ubuntu:${variant}`);
	}
	fromFedoraImage(variant = "44") {
		return this.fromImage(`fedora:${variant}`);
	}
	fromAlpineImage(variant = "3.24") {
		return this.fromImage(`alpine:${variant}`);
	}
	fromArchImage(variant = "latest") {
		return this.fromImage(`archlinux:${variant}`);
	}
	fromPythonImage(version = "3") {
		return this.fromImage(`python:${version}`);
	}
	fromNodeImage(variant = "lts") {
		return this.fromImage(`node:${variant}`);
	}
	fromBunImage(variant = "latest") {
		return this.fromImage(`oven/bun:${variant}`);
	}
	fromBaseImage() {
		return this.fromImage(this.defaultBaseImage);
	}
	fromImage(baseImage, credentials) {
		if (credentials && (!credentials.username || !credentials.password)) throw new InvalidArgumentError("Both username and password are required when providing registry credentials", getCallerFrame());
		this.baseImage = baseImage;
		this.baseTemplate = void 0;
		if (credentials) this.registryConfig = {
			type: "registry",
			username: credentials.username,
			password: credentials.password
		};
		if (this.forceNextLayer) this.force = true;
		this.collectStackTrace();
		return this;
	}
	fromTemplate(template) {
		this.baseTemplate = template;
		this.baseImage = void 0;
		if (this.forceNextLayer) this.force = true;
		this.collectStackTrace();
		return this;
	}
	fromDockerfile(dockerfileContentOrPath) {
		const { baseImage } = parseDockerfile(dockerfileContentOrPath, this);
		this.baseImage = baseImage;
		this.baseTemplate = void 0;
		if (this.forceNextLayer) this.force = true;
		this.collectStackTrace();
		return this;
	}
	fromAWSRegistry(image, credentials) {
		this.baseImage = image;
		this.baseTemplate = void 0;
		this.registryConfig = {
			type: "aws",
			awsAccessKeyId: credentials.accessKeyId,
			awsSecretAccessKey: credentials.secretAccessKey,
			awsRegion: credentials.region
		};
		if (this.forceNextLayer) this.force = true;
		this.collectStackTrace();
		return this;
	}
	fromGCPRegistry(image, credentials) {
		this.baseImage = image;
		this.baseTemplate = void 0;
		this.registryConfig = {
			type: "gcp",
			serviceAccountJson: readGCPServiceAccountJSON(this.fileContextPath.toString(), credentials.serviceAccountJSON)
		};
		if (this.forceNextLayer) this.force = true;
		this.collectStackTrace();
		return this;
	}
	copy(src, dest, options) {
		if (runtime === "browser") throw new Error("Browser runtime is not supported for copy");
		const srcs = Array.isArray(src) ? src : [src];
		const stackTrace = getCallerFrame();
		for (const src of srcs) {
			var _options$user;
			const srcString = src.toString();
			validateRelativePath(srcString, stackTrace);
			const args = [
				srcString,
				dest.toString(),
				(_options$user = options === null || options === void 0 ? void 0 : options.user) !== null && _options$user !== void 0 ? _options$user : "",
				(options === null || options === void 0 ? void 0 : options.mode) ? padOctal(options.mode) : ""
			];
			this.instructions.push({
				type: "COPY",
				args,
				force: (options === null || options === void 0 ? void 0 : options.forceUpload) || this.forceNextLayer,
				forceUpload: options === null || options === void 0 ? void 0 : options.forceUpload,
				resolveSymlinks: options === null || options === void 0 ? void 0 : options.resolveSymlinks,
				gzip: options === null || options === void 0 ? void 0 : options.gzip
			});
			this.collectStackTrace();
		}
		return this;
	}
	copyItems(items) {
		if (runtime === "browser") throw new Error("Browser runtime is not supported for copyItems");
		const stackTrace = getCallerFrame();
		for (const item of items) try {
			this.copy(item.src, item.dest, {
				forceUpload: item.forceUpload,
				user: item.user,
				mode: item.mode,
				resolveSymlinks: item.resolveSymlinks,
				gzip: item.gzip
			});
		} catch (error) {
			const copyError = error;
			copyError.stack = stackTrace;
			throw copyError;
		}
		return this;
	}
	remove(path, options) {
		const paths = Array.isArray(path) ? path : [path];
		const args = ["rm"];
		if (options === null || options === void 0 ? void 0 : options.recursive) args.push("-r");
		if (options === null || options === void 0 ? void 0 : options.force) args.push("-f");
		args.push(...paths.map((p) => shellQuote(p.toString())));
		return this.runCmd(args.join(" "), { user: options === null || options === void 0 ? void 0 : options.user });
	}
	rename(src, dest, options) {
		const args = [
			"mv",
			shellQuote(src.toString()),
			shellQuote(dest.toString())
		];
		if (options === null || options === void 0 ? void 0 : options.force) args.push("-f");
		return this.runCmd(args.join(" "), { user: options === null || options === void 0 ? void 0 : options.user });
	}
	makeDir(path, options) {
		const paths = Array.isArray(path) ? path : [path];
		const args = ["mkdir", "-p"];
		if (options === null || options === void 0 ? void 0 : options.mode) args.push(`-m ${padOctal(options.mode)}`);
		args.push(...paths.map((p) => shellQuote(p.toString())));
		return this.runCmd(args.join(" "), { user: options === null || options === void 0 ? void 0 : options.user });
	}
	makeSymlink(src, dest, options) {
		const args = ["ln", "-s"];
		if (options === null || options === void 0 ? void 0 : options.force) args.push("-f");
		args.push(shellQuote(src.toString()), shellQuote(dest.toString()));
		return this.runCmd(args.join(" "), { user: options === null || options === void 0 ? void 0 : options.user });
	}
	runCmd(commandOrCommands, options) {
		const args = [(Array.isArray(commandOrCommands) ? commandOrCommands : [commandOrCommands]).join(" && ")];
		if (options === null || options === void 0 ? void 0 : options.user) args.push(options.user);
		this.instructions.push({
			type: "RUN",
			args,
			force: this.forceNextLayer
		});
		this.collectStackTrace();
		return this;
	}
	setWorkdir(workdir) {
		this.instructions.push({
			type: "WORKDIR",
			args: [workdir.toString()],
			force: this.forceNextLayer
		});
		this.collectStackTrace();
		return this;
	}
	setUser(user) {
		this.instructions.push({
			type: "USER",
			args: [user],
			force: this.forceNextLayer
		});
		this.collectStackTrace();
		return this;
	}
	pipInstall(packages, options) {
		var _options$g;
		const g = (_options$g = options === null || options === void 0 ? void 0 : options.g) !== null && _options$g !== void 0 ? _options$g : true;
		const args = ["pip", "install"];
		const packageList = packages ? Array.isArray(packages) ? packages : [packages] : void 0;
		if (g === false) args.push("--user");
		if (packageList) args.push(...packageList);
		else args.push(".");
		return this.runCmd(args.join(" "), { user: g ? "root" : void 0 });
	}
	npmInstall(packages, options) {
		const args = ["npm", "install"];
		const packageList = packages ? Array.isArray(packages) ? packages : [packages] : void 0;
		if (options === null || options === void 0 ? void 0 : options.g) args.push("-g");
		if (options === null || options === void 0 ? void 0 : options.dev) args.push("--save-dev");
		if (packageList) args.push(...packageList);
		return this.runCmd(args.join(" "), { user: (options === null || options === void 0 ? void 0 : options.g) ? "root" : void 0 });
	}
	bunInstall(packages, options) {
		const args = ["bun", "install"];
		const packageList = packages ? Array.isArray(packages) ? packages : [packages] : void 0;
		if (options === null || options === void 0 ? void 0 : options.g) args.push("-g");
		if (options === null || options === void 0 ? void 0 : options.dev) args.push("--dev");
		if (packageList) args.push(...packageList);
		return this.runCmd(args.join(" "), { user: (options === null || options === void 0 ? void 0 : options.g) ? "root" : void 0 });
	}
	aptInstall(packages, options) {
		const packageList = Array.isArray(packages) ? packages : [packages];
		return this.runCmd(["apt-get update", `DEBIAN_FRONTEND=noninteractive DEBCONF_NOWARNINGS=yes apt-get install -y ${(options === null || options === void 0 ? void 0 : options.noInstallRecommends) ? "--no-install-recommends " : ""}${(options === null || options === void 0 ? void 0 : options.fixMissing) ? "--fix-missing " : ""}${packageList.join(" ")}`], { user: "root" });
	}
	addMcpServer(servers) {
		if (this.baseTemplate !== "mcp-gateway") throw new BuildError("MCP servers can only be added to mcp-gateway template", getCallerFrame());
		const serverList = Array.isArray(servers) ? servers : [servers];
		return this.runCmd(`mcp-gateway pull ${serverList.join(" ")}`, { user: "root" });
	}
	gitClone(url, path, options) {
		const args = [
			"git",
			"clone",
			shellQuote(url)
		];
		if (options === null || options === void 0 ? void 0 : options.branch) {
			args.push(`--branch ${shellQuote(options.branch)}`);
			args.push("--single-branch");
		}
		if (options === null || options === void 0 ? void 0 : options.depth) args.push(`--depth ${options.depth}`);
		if (path) args.push(shellQuote(path.toString()));
		return this.runCmd(args.join(" "), { user: options === null || options === void 0 ? void 0 : options.user });
	}
	setStartCmd(startCommand, readyCommand) {
		this.startCmd = startCommand;
		if (readyCommand instanceof ReadyCmd) this.readyCmd = readyCommand.getCmd();
		else this.readyCmd = readyCommand;
		this.collectStackTrace();
		return this;
	}
	setReadyCmd(readyCommand) {
		if (readyCommand instanceof ReadyCmd) this.readyCmd = readyCommand.getCmd();
		else this.readyCmd = readyCommand;
		this.collectStackTrace();
		return this;
	}
	setEnvs(envs) {
		if (Object.keys(envs).length === 0) return this;
		this.instructions.push({
			type: "ENV",
			args: Object.entries(envs).flatMap(([key, value]) => [key, value]),
			force: this.forceNextLayer
		});
		this.collectStackTrace();
		return this;
	}
	skipCache() {
		this.forceNextLayer = true;
		return this;
	}
	betaDevContainerPrebuild(devcontainerDirectory) {
		if (this.baseTemplate !== "devcontainer") throw new BuildError("Devcontainers can only used in the devcontainer template", getCallerFrame());
		return this.runCmd(`devcontainer build --workspace-folder ${shellQuote(devcontainerDirectory)}`, { user: "root" });
	}
	betaSetDevContainerStart(devcontainerDirectory) {
		if (this.baseTemplate !== "devcontainer") throw new BuildError("Devcontainers can only used in the devcontainer template", getCallerFrame());
		const dir = shellQuote(devcontainerDirectory);
		return this.setStartCmd(`sudo devcontainer up --workspace-folder ${dir} && sudo /prepare-exec.sh ${dir} | sudo tee /devcontainer.sh > /dev/null && sudo chmod +x /devcontainer.sh && sudo touch /devcontainer.up`, waitForFile("/devcontainer.up"));
	}
	/**
	* Collect the current stack trace for debugging purposes.
	*
	* The trace resolves to the first frame outside the SDK, so methods that
	* delegate to other builder methods (e.g. `remove()` → `runCmd()`) collect
	* the user's call site without any bookkeeping.
	*
	* @returns this for method chaining
	*/
	collectStackTrace() {
		this.stackTraces.push(getCallerFrame());
		return this;
	}
	/**
	* Convert the template to JSON representation.
	*
	* @param computeHashes Whether to compute file hashes for COPY instructions
	* @returns JSON string representation of the template
	*/
	async toJSON(computeHashes) {
		var _this9 = this;
		let instructions = _this9.instructions;
		if (computeHashes) instructions = await _this9.instructionsWithHashes();
		return JSON.stringify(_this9.serialize(instructions), void 0, 2);
	}
	/**
	* Convert the template to Dockerfile format.
	*
	* Note: Only templates based on Docker images can be converted to Dockerfile.
	* Templates based on other E2B templates cannot be converted because they
	* may use features not available in standard Dockerfiles.
	*
	* @returns Dockerfile string representation
	* @throws Error if template is based on another E2B template or has no base image
	*/
	toDockerfile() {
		if (this.baseTemplate !== void 0) throw new Error("Cannot convert template built from another template to Dockerfile. Templates based on other templates can only be built using the E2B API.");
		if (this.baseImage === void 0) throw new Error("No base image specified for template");
		let dockerfile = `FROM ${this.baseImage}\n`;
		for (const instruction of this.instructions) {
			if (instruction.type === "RUN") {
				dockerfile += `RUN ${instruction.args[0]}\n`;
				continue;
			}
			if (instruction.type === "COPY") {
				dockerfile += `COPY ${instruction.args[0]} ${instruction.args[1]}\n`;
				continue;
			}
			if (instruction.type === "ENV") {
				const values = [];
				for (let i = 0; i < instruction.args.length; i += 2) values.push(`${instruction.args[i]}=${instruction.args[i + 1]}`);
				dockerfile += `ENV ${values.join(" ")}\n`;
				continue;
			}
			dockerfile += `${instruction.type} ${instruction.args.join(" ")}\n`;
		}
		if (this.startCmd) dockerfile += `ENTRYPOINT ${this.startCmd}\n`;
		return dockerfile;
	}
	/**
	* Internal implementation of the template build process.
	*
	* @param client API client for communicating with E2B backend
	* @param name Template name in 'name' or 'name:tag' format
	* @param tags Additional tags to assign to the build
	* @param options Build configuration options
	* @throws BuildError if the build fails
	*/
	async build(client, config, name, options) {
		var _this10 = this;
		var _options$onBuildLogs, _options$cpuCount, _options$memoryMB, _options$onBuildLogs2, _options$onBuildLogs5, _options$onBuildLogs6;
		if (options.skipCache) _this10.force = true;
		(_options$onBuildLogs = options.onBuildLogs) === null || _options$onBuildLogs === void 0 || _options$onBuildLogs.call(options, new LogEntry(/* @__PURE__ */ new Date(), "info", `Requesting build for template: ${name}${options.tags && options.tags.length > 0 ? ` with tags ${options.tags.join(", ")}` : ""}`));
		const { templateID, buildID, tags: responseTags } = await requestBuild(client, {
			name,
			tags: options.tags,
			cpuCount: (_options$cpuCount = options.cpuCount) !== null && _options$cpuCount !== void 0 ? _options$cpuCount : 2,
			memoryMB: (_options$memoryMB = options.memoryMB) !== null && _options$memoryMB !== void 0 ? _options$memoryMB : 1024
		}, config.getSignal(void 0, options.signal));
		(_options$onBuildLogs2 = options.onBuildLogs) === null || _options$onBuildLogs2 === void 0 || _options$onBuildLogs2.call(options, new LogEntry(/* @__PURE__ */ new Date(), "info", `Template created with ID: ${templateID}, Build ID: ${buildID}`));
		const instructionsWithHashes = await _this10.instructionsWithHashes();
		const uploadPromises = instructionsWithHashes.map(async (instruction, index) => {
			var _instruction$filesHas;
			if (instruction.type !== "COPY") return;
			const src = instruction.args.length > 0 ? instruction.args[0] : null;
			const filesHash = (_instruction$filesHas = instruction.filesHash) !== null && _instruction$filesHas !== void 0 ? _instruction$filesHas : null;
			if (src === null || filesHash === null) throw new Error("Source path and files hash are required");
			const forceUpload = instruction.forceUpload;
			let stackTrace = void 0;
			if (index + 1 >= 0 && index + 1 < _this10.stackTraces.length) stackTrace = _this10.stackTraces[index + 1];
			const { present, url } = await getFileUploadLink(client, {
				templateID,
				filesHash
			}, stackTrace, config.getSignal(void 0, options.signal));
			if (forceUpload && url != null || present === false && url != null) {
				var _instruction$resolveS, _instruction$gzip, _options$onBuildLogs3;
				await uploadFile({
					fileName: src,
					fileContextPath: _this10.fileContextPath.toString(),
					url,
					ignorePatterns: [..._this10.fileIgnorePatterns, ...readDockerignore(_this10.fileContextPath.toString())],
					resolveSymlinks: (_instruction$resolveS = instruction.resolveSymlinks) !== null && _instruction$resolveS !== void 0 ? _instruction$resolveS : false,
					gzip: (_instruction$gzip = instruction.gzip) !== null && _instruction$gzip !== void 0 ? _instruction$gzip : true
				}, stackTrace, {
					signal: options.signal,
					requestTimeoutMs: options.requestTimeoutMs
				});
				(_options$onBuildLogs3 = options.onBuildLogs) === null || _options$onBuildLogs3 === void 0 || _options$onBuildLogs3.call(options, new LogEntry(/* @__PURE__ */ new Date(), "info", `Uploaded '${src}'`));
			} else {
				var _options$onBuildLogs4;
				(_options$onBuildLogs4 = options.onBuildLogs) === null || _options$onBuildLogs4 === void 0 || _options$onBuildLogs4.call(options, new LogEntry(/* @__PURE__ */ new Date(), "info", `Skipping upload of '${src}', already cached`));
			}
		});
		await Promise.all(uploadPromises);
		(_options$onBuildLogs5 = options.onBuildLogs) === null || _options$onBuildLogs5 === void 0 || _options$onBuildLogs5.call(options, new LogEntry(/* @__PURE__ */ new Date(), "info", "All file uploads completed"));
		(_options$onBuildLogs6 = options.onBuildLogs) === null || _options$onBuildLogs6 === void 0 || _options$onBuildLogs6.call(options, new LogEntry(/* @__PURE__ */ new Date(), "info", "Starting building..."));
		await triggerBuild(client, {
			templateID,
			buildID,
			template: _this10.serialize(instructionsWithHashes)
		}, config.getSignal(void 0, options.signal));
		return {
			alias: name,
			name,
			tags: responseTags,
			templateId: templateID,
			buildId: buildID
		};
	}
	/**
	* Add file hashes to COPY instructions for cache invalidation.
	*
	* @returns Copy of instructions array with filesHash added to COPY instructions
	*/
	async instructionsWithHashes() {
		var _this11 = this;
		return Promise.all(_this11.instructions.map(async (instruction, index) => {
			var _instruction$resolveS2;
			if (instruction.type !== "COPY") return instruction;
			const src = instruction.args.length > 0 ? instruction.args[0] : null;
			const dest = instruction.args.length > 1 ? instruction.args[1] : null;
			if (src === null || dest === null) throw new Error("Source path and destination path are required");
			let stackTrace = void 0;
			if (index + 1 >= 0 && index + 1 < _this11.stackTraces.length) stackTrace = _this11.stackTraces[index + 1];
			return _objectSpread2(_objectSpread2({}, instruction), {}, { filesHash: await calculateFilesHash(src, dest, _this11.fileContextPath.toString(), [..._this11.fileIgnorePatterns, ...runtime === "browser" ? [] : readDockerignore(_this11.fileContextPath.toString())], (_instruction$resolveS2 = instruction.resolveSymlinks) !== null && _instruction$resolveS2 !== void 0 ? _instruction$resolveS2 : false, stackTrace) });
		}));
	}
	/**
	* Serialize the template to the API request format.
	*
	* @param steps Array of build instructions with file hashes
	* @returns Template data formatted for the API
	*/
	serialize(steps) {
		const templateData = {
			startCmd: this.startCmd,
			readyCmd: this.readyCmd,
			steps,
			force: this.force
		};
		if (this.baseImage !== void 0) templateData.fromImage = this.baseImage;
		if (this.baseTemplate !== void 0) templateData.fromTemplate = this.baseTemplate;
		if (this.registryConfig !== void 0) templateData.fromImageRegistry = this.registryConfig;
		return templateData;
	}
};
/**
* Builder and API entrypoint for E2B sandbox templates.
*
* `Template` is the {@link TemplateBase} class, wrapped so it can also be
* called as a factory returning a builder. The statics (`Template.build`,
* `Template.exists`, …) resolve their connection options off the class they are
* called on — so a subclass can bind its own defaults.
*
* @param options Optional builder options, e.g. the file context path used to
*   resolve relative paths passed to `copy`
* @returns A template builder
*
* @example
* ```ts
* import { Template } from 'e2b'
*
* const template = Template()
*   .fromPythonImage('3')
*   .copy('requirements.txt', '/app/')
*   .pipInstall()
*
* await Template.build(template, 'my-python-app:v1.0')
* ```
*/
const Template = callableTemplate(TemplateBase);
//#endregion
//#region src/client.ts
/**
* E2B client with an explicitly bound connection configuration.
*
* The resources exposed by the client ({@link E2B.Sandbox},
* {@link E2B.Volume}, {@link E2B.Template}, {@link E2B.Secret}) behave exactly
* like the top-level `Sandbox` / `Volume` / `Template` / `Secret` exports,
* except the options passed to the client are used as the defaults instead of
* the environment variables.
* Per-call options still take precedence over the client's options.
*
* Multiple clients are fully isolated from each other and from the top-level
* env-configured exports.
*
* @example
* ```ts
* import { E2B } from 'e2b'
*
* const client = new E2B({ apiKey: 'e2b_...', domain: 'e2b.dev' })
*
* const sandbox = await client.Sandbox.create()
* const volumes = await client.Volume.list()
* await client.Template.build(client.Template().fromPythonImage('3'), 'my-env')
* ```
*/
var E2B = class {
	/**
	* Create a new client with the connection options bound to it.
	*
	* @param opts connection options used as the defaults for every call made
	*   through this client's resource classes.
	*/
	constructor(opts) {
		var _Class, _Class2, _Class3, _Class4;
		_defineProperty(this, "Sandbox", void 0);
		_defineProperty(this, "Volume", void 0);
		_defineProperty(this, "Template", void 0);
		_defineProperty(this, "Secret", void 0);
		const boundOpts = _objectSpread2({}, opts !== null && opts !== void 0 ? opts : {});
		delete boundOpts.signal;
		this.Sandbox = (_Class = class extends Sandbox {}, _defineProperty(_Class, "boundOpts", boundOpts), _Class);
		this.Volume = (_Class2 = class extends Volume {}, _defineProperty(_Class2, "boundOpts", boundOpts), _Class2);
		this.Secret = (_Class3 = class extends Secret {}, _defineProperty(_Class3, "boundOpts", boundOpts), _Class3);
		this.Template = callableTemplate((_Class4 = class extends TemplateBase {}, _defineProperty(_Class4, "boundOpts", boundOpts), _Class4));
	}
};
//#endregion
//#region src/index.ts
var src_default = Sandbox;
//#endregion
export { ALL_TRAFFIC, ApiClient, AuthenticationError, BuildError, CommandExitError, ConnectionConfig, E2B, FileNotFoundError, FileType, FileUploadError, FilesystemEventType, Git, GitAuthError, GitUpstreamError, InvalidArgumentError, LogEntry, LogEntryEnd, LogEntryStart, NotEnoughSpaceError, NotFoundError, RateLimitError, ReadyCmd, Sandbox, SandboxError, SandboxNotFoundError, Secret, SecretError, SecretNotFoundError, SecretPaginator, Template, TemplateBase, TemplateError, TimeoutError, Volume, VolumeError, VolumeFileType, VolumeNotFoundError, VolumePathNotFoundError, src_default as default, defaultBuildLogger, getSignature, waitForFile, waitForPort, waitForProcess, waitForTimeout, waitForURL };

//# sourceMappingURL=index.mjs.map