UNPKG

e2b

Version:

E2B SDK that give agents cloud environments

1,395 lines (1,373 loc) 205 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __defProps = Object.defineProperties; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropDescs = Object.getOwnPropertyDescriptors; var __getOwnPropNames = Object.getOwnPropertyNames; var __getOwnPropSymbols = Object.getOwnPropertySymbols; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __propIsEnum = Object.prototype.propertyIsEnumerable; var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name); var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; var __spreadValues = (a, b) => { for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]); if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) { if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]); } return a; }; var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); var __objRest = (source, exclude) => { var target = {}; for (var prop in source) if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0) target[prop] = source[prop]; if (source != null && __getOwnPropSymbols) for (var prop of __getOwnPropSymbols(source)) { if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop)) target[prop] = source[prop]; } return target; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var __await = function(promise, isYieldStar) { this[0] = promise; this[1] = isYieldStar; }; var __asyncGenerator = (__this, __arguments, generator) => { var resume = (k, v, yes, no) => { try { var x = generator[k](v), isAwait = (v = x.value) instanceof __await, done = x.done; Promise.resolve(isAwait ? v[0] : v).then((y) => isAwait ? resume(k === "return" ? k : "next", v[1] ? { done: y.done, value: y.value } : y, yes, no) : yes({ value: y, done })).catch((e) => resume("throw", e, yes, no)); } catch (e) { no(e); } }, method = (k) => it[k] = (x) => new Promise((yes, no) => resume(k, x, yes, no)), it = {}; return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it; }; var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it); // src/index.ts var src_exports = {}; __export(src_exports, { ALL_TRAFFIC: () => ALL_TRAFFIC, ApiClient: () => ApiClient, AuthenticationError: () => AuthenticationError, BuildError: () => BuildError, CommandExitError: () => CommandExitError, ConnectionConfig: () => ConnectionConfig, FileNotFoundError: () => FileNotFoundError, FileType: () => FileType2, FileUploadError: () => FileUploadError, FilesystemEventType: () => FilesystemEventType, Git: () => Git, GitAuthError: () => GitAuthError, GitUpstreamError: () => GitUpstreamError, InvalidArgumentError: () => InvalidArgumentError, LogEntry: () => LogEntry, LogEntryEnd: () => LogEntryEnd, LogEntryStart: () => LogEntryStart, NotEnoughSpaceError: () => NotEnoughSpaceError, NotFoundError: () => NotFoundError, RateLimitError: () => RateLimitError, ReadyCmd: () => ReadyCmd, Sandbox: () => Sandbox, SandboxError: () => SandboxError, SandboxNotFoundError: () => SandboxNotFoundError, Template: () => Template, TemplateBase: () => TemplateBase, TemplateError: () => TemplateError, TimeoutError: () => TimeoutError, Volume: () => Volume, VolumeError: () => VolumeError, VolumeFileType: () => VolumeFileType, default: () => src_default, defaultBuildLogger: () => defaultBuildLogger, getSignature: () => getSignature, waitForFile: () => waitForFile, waitForPort: () => waitForPort, waitForProcess: () => waitForProcess, waitForTimeout: () => waitForTimeout, waitForURL: () => waitForURL }); module.exports = __toCommonJS(src_exports); // src/api/index.ts var import_openapi_fetch = __toESM(require("openapi-fetch")); // src/api/metadata.ts var import_platform2 = __toESM(require("platform")); // package.json var version = "2.24.0"; // src/utils.ts var import_platform = __toESM(require("platform")); function getRuntime() { var _a3, _b, _c; if (globalThis.Bun) { return { runtime: "bun", version: globalThis.Bun.version }; } if (globalThis.Deno) { return { runtime: "deno", version: globalThis.Deno.version.deno }; } if (((_b = (_a3 = globalThis.process) == null ? void 0 : _a3.release) == null ? void 0 : _b.name) === "node") { return { runtime: "node", version: import_platform.default.version || "unknown" }; } if (typeof EdgeRuntime === "string") { return { runtime: "vercel-edge", version: "unknown" }; } if (((_c = globalThis.navigator) == null ? void 0 : _c.userAgent) === "Cloudflare-Workers") { return { runtime: "cloudflare-worker", version: "unknown" }; } if (typeof window !== "undefined") { return { runtime: "browser", version: import_platform.default.version || "unknown" }; } return { runtime: "unknown", version: "unknown" }; } var { runtime, version: runtimeVersion } = getRuntime(); async function sha256(data) { if (typeof crypto !== "undefined") { const encoder = new TextEncoder(); const dataBuffer = encoder.encode(data); const hashBuffer = await crypto.subtle.digest("SHA-256", dataBuffer); const hashArray = new Uint8Array(hashBuffer); return btoa(String.fromCharCode(...hashArray)); } const { createHash } = require("crypto"); const hash = createHash("sha256").update(data, "utf8").digest(); return hash.toString("base64"); } function timeoutToSeconds(timeout) { return Math.ceil(timeout / 1e3); } function dynamicRequire(module2) { if (runtime === "browser") { throw new Error("Browser runtime is not supported for require"); } return require(module2); } async function dynamicImport(module2) { if (runtime === "browser") { throw new Error("Browser runtime is not supported for dynamic import"); } return await import(module2); } function ansiRegex({ onlyFirst = false } = {}) { const ST = "(?:\\u0007|\\u001B\\u005C|\\u009C)"; const osc = `(?:\\u001B\\][\\s\\S]*?${ST})`; const csi = "[\\u001B\\u009B][[\\]()#;?]*(?:\\d{1,4}(?:[;:]\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]"; const pattern = `${osc}|${csi}`; return new RegExp(pattern, onlyFirst ? void 0 : "g"); } function stripAnsi(text) { return text.replace(ansiRegex(), ""); } function toBlob(data) { if (data instanceof Blob) { return data; } if (typeof data === "string" || data instanceof ArrayBuffer) { return new Blob([data]); } return new Response(data).blob(); } function shellQuote(s) { return "'" + s.replace(/'/g, "'\\''") + "'"; } async function toUploadBody(data, gzip) { if (gzip) { const stream = data instanceof ReadableStream ? data : data instanceof Blob ? data.stream() : new Blob([data]).stream(); const compressed = stream.pipeThrough(new CompressionStream("gzip")); return new Response(compressed).blob(); } return toBlob(data); } // src/api/metadata.ts var _a; var defaultHeaders = { browser: typeof window !== "undefined" && import_platform2.default.name || "unknown", lang: "js", lang_version: runtimeVersion, package_version: version, publisher: "e2b", sdk_runtime: runtime, system: ((_a = import_platform2.default.os) == null ? void 0 : _a.family) || "unknown" }; function getEnvVar(name) { if (runtime === "deno") { return Deno.env.get(name); } if (typeof process === "undefined") { return ""; } return process.env[name]; } // src/undici.ts async function loadUndici() { try { const importModule = new Function( "moduleName", "return import(moduleName)" ); return await importModule("undici"); } catch (e) { return void 0; } } function toUndiciRequestInput(input, init) { if (!(input instanceof Request)) { return { input, init }; } const requestInit = __spreadValues({ body: input.body, cache: input.cache, credentials: input.credentials, headers: input.headers, integrity: input.integrity, keepalive: input.keepalive, method: input.method, mode: input.mode, redirect: input.redirect, referrer: input.referrer, referrerPolicy: input.referrerPolicy, signal: input.signal }, init); if (requestInit.body) { requestInit.duplex = "half"; } return { input: input.url, init: requestInit }; } // src/api/http2.ts var API_CONNECTION_LIMIT = 100; var API_UNDICI_FALLBACK_WARNING = "Failed to load undici for API HTTP/2 transport; falling back to global fetch."; var apiFetch; var hasWarnedUndiciFallback = false; function createApiFetch() { if (apiFetch) { return apiFetch; } apiFetch = createApiFetchForRuntime(runtime); return apiFetch; } function createApiFetchForRuntime(currentRuntime = runtime, options = { connectionLimit: API_CONNECTION_LIMIT }) { if (currentRuntime !== "node") { return fetch; } let fetcherPromise; return async (input, init) => { fetcherPromise != null ? fetcherPromise : fetcherPromise = buildApiFetcher(options); const fetcher = await fetcherPromise; return fetcher(input, init); }; } async function buildApiFetcher(options) { var _a3; const undici = await ((_a3 = options.loadUndici) != null ? _a3 : loadUndici)(); if (!undici) { warnUndiciFallback(); return fetch; } const { Agent, fetch: undiciFetch } = undici; const dispatcher = new Agent({ allowH2: true, connections: options.connectionLimit }); const fetchWithDispatcher = undiciFetch; return (input, init) => { const request = toUndiciRequestInput(input, init); return fetchWithDispatcher(request.input, __spreadProps(__spreadValues({}, request.init), { dispatcher })); }; } function warnUndiciFallback() { if (hasWarnedUndiciFallback) { return; } hasWarnedUndiciFallback = true; console.warn(API_UNDICI_FALLBACK_WARNING); } // src/errors.ts function formatSandboxTimeoutError(message) { return new TimeoutError( `${message}: This error is likely due to sandbox timeout. You can modify the sandbox timeout by passing 'timeoutMs' when starting the sandbox or calling '.setTimeout' on the sandbox with the desired timeout.` ); } var SandboxError = class extends Error { constructor(message, stackTrace) { super(message); this.name = "SandboxError"; if (stackTrace) { this.stack = stackTrace; } } }; var TimeoutError = class extends SandboxError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "TimeoutError"; } }; var InvalidArgumentError = class extends SandboxError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "InvalidArgumentError"; } }; var NotEnoughSpaceError = class extends SandboxError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "NotEnoughSpaceError"; } }; var NotFoundError = class extends SandboxError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "NotFoundError"; } }; var FileNotFoundError = class extends NotFoundError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "FileNotFoundError"; } }; var SandboxNotFoundError = class extends NotFoundError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "SandboxNotFoundError"; } }; var AuthenticationError = class extends Error { constructor(message) { super(message); this.name = "AuthenticationError"; } }; var GitAuthError = class extends AuthenticationError { constructor(message) { super(message); this.name = "GitAuthError"; } }; var GitUpstreamError = class extends SandboxError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "GitUpstreamError"; } }; var TemplateError = class extends SandboxError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "TemplateError"; } }; var RateLimitError = class extends SandboxError { constructor(message) { super(message); this.name = "RateLimitError"; } }; var BuildError = class extends Error { constructor(message, stackTrace) { super(message); this.name = "BuildError"; if (stackTrace) { this.stack = stackTrace; } } }; var FileUploadError = class extends BuildError { constructor(message, stackTrace) { super(message, stackTrace); this.name = "FileUploadError"; } }; var VolumeError = class extends Error { constructor(message) { super(message); this.name = "VolumeError"; } }; // src/logs.ts function formatLog(log) { return JSON.parse(JSON.stringify(log)); } function createRpcLogger(logger) { function logEach(stream) { return __asyncGenerator(this, null, function* () { var _a3; try { for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) { const m = temp.value; (_a3 = logger.debug) == null ? void 0 : _a3.call(logger, "Response stream:", formatLog(m)); yield m; } } catch (temp) { error = [temp]; } finally { try { more && (temp = iter.return) && (yield new __await(temp.call(iter))); } finally { if (error) throw error[0]; } } }); } return (next) => async (req) => { var _a3, _b; (_a3 = logger.info) == null ? void 0 : _a3.call(logger, `Request: POST ${req.url}`); const res = await next(req); if (res.stream) { return __spreadProps(__spreadValues({}, res), { message: logEach(res.message) }); } else { (_b = logger.info) == null ? void 0 : _b.call(logger, "Response:", formatLog(res.message)); } return res; }; } function createApiLogger(logger) { return { async onRequest({ request }) { var _a3; (_a3 = logger.info) == null ? void 0 : _a3.call(logger, `Request ${request.method} ${request.url}`); return request; }, async onResponse({ response }) { var _a3, _b; if (response.status >= 400) { (_a3 = logger.error) == null ? void 0 : _a3.call(logger, "Response:", response.status, response.statusText); } else { (_b = logger.info) == null ? void 0 : _b.call(logger, "Response:", response.status, response.statusText); } return response; } }; } // src/api/index.ts function handleApiError(response, errorClass = SandboxError, stackTrace) { var _a3, _b, _c, _d, _e, _f; if (response.error === void 0) { return; } if (response.response.status === 401) { const message2 = "Unauthorized, please check your credentials."; const content = (_b = (_a3 = response.error) == null ? void 0 : _a3.message) != null ? _b : response.error; if (content) { return new AuthenticationError(`${message2} - ${content}`); } return new AuthenticationError(message2); } if (response.response.status === 429) { const message2 = "Rate limit exceeded, please try again later"; const content = (_d = (_c = response.error) == null ? void 0 : _c.message) != null ? _d : response.error; if (content) { return new RateLimitError(`${message2} - ${content}`); } return new RateLimitError(message2); } const message = (_f = (_e = response.error) == null ? void 0 : _e.message) != null ? _f : response.error; return new errorClass(`${response.response.status}: ${message}`, stackTrace); } var ApiClient = class { constructor(config, opts = { requireAccessToken: false, requireApiKey: false }) { if ((opts == null ? void 0 : opts.requireApiKey) && !config.apiKey) { throw new AuthenticationError( "API key is required, please visit the Team tab at https://e2b.dev/dashboard to get your API key. You can either set the environment variable `E2B_API_KEY` or you can pass it directly to the sandbox like Sandbox.create({ apiKey: 'e2b_...' })" ); } if ((opts == null ? void 0 : opts.requireAccessToken) && !config.accessToken) { throw new AuthenticationError( "Access token is required, please visit the Personal tab at https://e2b.dev/dashboard to get your access token. You can set the environment variable `E2B_ACCESS_TOKEN` or pass the `accessToken` in options." ); } this.api = (0, import_openapi_fetch.default)({ baseUrl: config.apiUrl, fetch: createApiFetch(), // In HTTP 1.1, all connections are considered persistent unless declared otherwise // keepalive: true, headers: __spreadValues(__spreadValues(__spreadValues(__spreadValues({}, defaultHeaders), config.apiKey && { "X-API-KEY": config.apiKey }), config.accessToken && { Authorization: `Bearer ${config.accessToken}` }), config.headers), querySerializer: { array: { style: "form", explode: false } } }); if (config.logger) { this.api.use(createApiLogger(config.logger)); } } }; // src/connectionConfig.ts var REQUEST_TIMEOUT_MS = 6e4; var DEFAULT_SANDBOX_TIMEOUT_MS = 3e5; var KEEPALIVE_PING_INTERVAL_SEC = 50; var KEEPALIVE_PING_HEADER = "Keepalive-Ping-Interval"; function buildRequestSignal(requestTimeoutMs, userSignal) { const timeoutSignal = requestTimeoutMs ? AbortSignal.timeout(requestTimeoutMs) : void 0; if (timeoutSignal && userSignal) { return AbortSignal.any([timeoutSignal, userSignal]); } return timeoutSignal != null ? timeoutSignal : userSignal; } function setupRequestController(requestTimeoutMs, userSignal) { const controller = new AbortController(); const onUserAbort = () => controller.abort(userSignal == null ? void 0 : userSignal.reason); if (userSignal) { if (userSignal.aborted) { controller.abort(userSignal.reason); } else { userSignal.addEventListener("abort", onUserAbort, { once: true }); } } let reqTimeout = requestTimeoutMs ? setTimeout( () => controller.abort( new DOMException( `Request handshake timed out after ${requestTimeoutMs}ms`, "TimeoutError" ) ), requestTimeoutMs ) : void 0; const clearStartTimeout = () => { if (reqTimeout) { clearTimeout(reqTimeout); reqTimeout = void 0; } }; let cleaned = false; const cleanup = () => { if (cleaned) return; cleaned = true; userSignal == null ? void 0 : userSignal.removeEventListener("abort", onUserAbort); clearStartTimeout(); controller.abort(); }; return { controller, clearStartTimeout, cleanup }; } var _ConnectionConfig = class _ConnectionConfig { constructor(opts) { var _a3; this.apiKey = (opts == null ? void 0 : opts.apiKey) || _ConnectionConfig.apiKey; this.debug = (opts == null ? void 0 : opts.debug) || _ConnectionConfig.debug; this.domain = (opts == null ? void 0 : opts.domain) || _ConnectionConfig.domain; this.accessToken = (opts == null ? void 0 : opts.accessToken) || _ConnectionConfig.accessToken; this.requestTimeoutMs = (_a3 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a3 : REQUEST_TIMEOUT_MS; this.logger = opts == null ? void 0 : opts.logger; this.headers = (opts == null ? void 0 : opts.headers) || {}; this.headers["User-Agent"] = `e2b-js-sdk/${version}`; this.apiUrl = (opts == null ? void 0 : opts.apiUrl) || _ConnectionConfig.apiUrl || (this.debug ? "http://localhost:3000" : `https://api.${this.domain}`); this.sandboxUrl = (opts == null ? void 0 : opts.sandboxUrl) || _ConnectionConfig.sandboxUrl; } static get domain() { return getEnvVar("E2B_DOMAIN") || "e2b.app"; } static get apiUrl() { return getEnvVar("E2B_API_URL"); } static get sandboxUrl() { return getEnvVar("E2B_SANDBOX_URL"); } static get debug() { return (getEnvVar("E2B_DEBUG") || "false").toLowerCase() === "true"; } static get apiKey() { return getEnvVar("E2B_API_KEY"); } static get accessToken() { return getEnvVar("E2B_ACCESS_TOKEN"); } getSignal(requestTimeoutMs, signal) { return buildRequestSignal(requestTimeoutMs != null ? requestTimeoutMs : this.requestTimeoutMs, signal); } getSandboxUrl(sandboxId, opts) { if (this.sandboxUrl) { return this.sandboxUrl; } return `${this.debug ? "http" : "https"}://${this.getHost(sandboxId, opts.envdPort, opts.sandboxDomain)}`; } getHost(sandboxId, port, sandboxDomain) { if (this.debug) { return `localhost:${port}`; } return `${port}-${sandboxId}.${sandboxDomain != null ? sandboxDomain : this.domain}`; } }; _ConnectionConfig.envdPort = 49983; var ConnectionConfig = _ConnectionConfig; var defaultUsername = "user"; // src/sandbox/signature.ts async function getSignature({ path: path2, operation, user, expirationInSeconds, envdAccessToken }) { if (!envdAccessToken) { throw new Error( "Access token is not set and signature cannot be generated!" ); } const signatureExpiration = expirationInSeconds ? Math.floor(Date.now() / 1e3) + expirationInSeconds : null; let signatureRaw; if (user == void 0) { user = ""; } if (signatureExpiration === null) { signatureRaw = `${path2}:${operation}:${user}:${envdAccessToken}`; } else { signatureRaw = `${path2}:${operation}:${user}:${envdAccessToken}:${signatureExpiration.toString()}`; } const hashBase64 = await sha256(signatureRaw); const signature = "v1_" + hashBase64.replace(/=+$/, ""); return { signature, expiration: signatureExpiration }; } // src/sandbox/filesystem/index.ts var import_connect3 = require("@connectrpc/connect"); // src/envd/api.ts var import_openapi_fetch2 = __toESM(require("openapi-fetch")); var import_connect = require("@connectrpc/connect"); var DEFAULT_ERROR_MAP = { 400: (message) => new InvalidArgumentError(message), 401: (message) => new AuthenticationError(message), 404: (message) => new NotFoundError(message), 429: (message) => new SandboxError(`${message}: The requests are being rate limited.`), 502: formatSandboxTimeoutError, 507: (message) => new NotEnoughSpaceError(message) }; async function handleEnvdApiError(res, errorMap) { var _a3, _b, _c; if (!res.error) { return; } const message = typeof res.error == "string" ? res.error : ((_a3 = res.error) == null ? void 0 : _a3.message) || await res.response.text(); if (errorMap && res.response.status in errorMap) { return (_b = errorMap[res.response.status]) == null ? void 0 : _b.call(errorMap, message); } if (res.response.status in DEFAULT_ERROR_MAP) { return (_c = DEFAULT_ERROR_MAP[res.response.status]) == null ? void 0 : _c.call(DEFAULT_ERROR_MAP, message); } return new SandboxError(`${res.response.status}: ${message}`); } async function handleProcessStartEvent(events) { var _a3; let startEvent; try { startEvent = (await events[Symbol.asyncIterator]().next()).value; } catch (err) { if (err instanceof import_connect.ConnectError) { if (err.code === import_connect.Code.Unavailable) { throw new SandboxNotFoundError( "Sandbox is probably not running anymore" ); } } throw err; } if (((_a3 = startEvent.event) == null ? void 0 : _a3.event.case) !== "start") { throw new Error("Expected start event"); } return startEvent.event.event.value.pid; } async function handleWatchDirStartEvent(events) { var _a3; let startEvent; try { startEvent = (await events[Symbol.asyncIterator]().next()).value; } catch (err) { if (err instanceof import_connect.ConnectError) { if (err.code === import_connect.Code.Unavailable) { throw new SandboxNotFoundError( "Sandbox is probably not running anymore" ); } } throw err; } if (((_a3 = startEvent.event) == null ? void 0 : _a3.case) !== "start") { throw new Error("Expected start event"); } return startEvent.event.value; } var EnvdApiClient = class { constructor(config, metadata) { this.api = (0, import_openapi_fetch2.default)({ baseUrl: config.apiUrl, fetch: config == null ? void 0 : config.fetch, headers: config == null ? void 0 : config.headers // In HTTP 1.1, all connections are considered persistent unless declared otherwise // keepalive: true, }); this.version = metadata.version; if (config.logger) { this.api.use(createApiLogger(config.logger)); } } }; // src/envd/rpc.ts var import_connect2 = require("@connectrpc/connect"); var import_compare_versions = require("compare-versions"); // src/envd/versions.ts var ENVD_VERSION_RECURSIVE_WATCH = "0.1.4"; var ENVD_DEBUG_FALLBACK = "99.99.99"; var ENVD_COMMANDS_STDIN = "0.3.0"; var ENVD_DEFAULT_USER = "0.4.0"; var ENVD_ENVD_CLOSE = "0.5.2"; var ENVD_OCTET_STREAM_UPLOAD = "0.5.7"; // src/envd/rpc.ts var DEFAULT_ERROR_MAP2 = { [import_connect2.Code.InvalidArgument]: (message) => new InvalidArgumentError(message), [import_connect2.Code.Unauthenticated]: (message) => new AuthenticationError(message), [import_connect2.Code.NotFound]: (message) => new NotFoundError(message), [import_connect2.Code.Unavailable]: formatSandboxTimeoutError, [import_connect2.Code.Canceled]: (message) => new TimeoutError( `${message}: This error is likely due to exceeding 'requestTimeoutMs'. You can pass the request timeout value as an option when making the request.` ), [import_connect2.Code.DeadlineExceeded]: (message) => new TimeoutError( `${message}: This error is likely due to exceeding 'timeoutMs' \u2014 the total time a long running request (like command execution or directory watch) can be active. It can be modified by passing 'timeoutMs' when making the request. Use '0' to disable the timeout.` ) }; function handleRpcError(err, errorMap) { if (err instanceof import_connect2.ConnectError) { if (errorMap && err.code in errorMap) { return errorMap[err.code](err.message); } if (err.code in DEFAULT_ERROR_MAP2) { return DEFAULT_ERROR_MAP2[err.code](err.message); } return new SandboxError(`${err.code}: ${err.message}`); } return err; } function encode64(value) { switch (runtime) { case "deno": return btoa(value); case "node": return Buffer.from(value).toString("base64"); case "bun": return Buffer.from(value).toString("base64"); default: return btoa(value); } } function authenticationHeader(envdVersion, username) { if (username == void 0 && (0, import_compare_versions.compareVersions)(envdVersion, ENVD_DEFAULT_USER) < 0) { username = defaultUsername; } if (!username) { return {}; } const value = `${username}:`; const encoded = encode64(value); return { Authorization: `Basic ${encoded}` }; } // src/envd/filesystem/filesystem_pb.ts var import_codegenv2 = require("@bufbuild/protobuf/codegenv2"); var import_wkt = require("@bufbuild/protobuf/wkt"); var file_filesystem_filesystem = /* @__PURE__ */ (0, import_codegenv2.fileDesc)( "ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8i/QEKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKDnN5bWxpbmtfdGFyZ2V0GAogASgJSACIAQFCEQoPX3N5bWxpbmtfdGFyZ2V0Ii0KDkxpc3REaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSDQoFZGVwdGgYAiABKA0iOQoPTGlzdERpclJlc3BvbnNlEiYKB2VudHJpZXMYASADKAsyFS5maWxlc3lzdGVtLkVudHJ5SW5mbyIyCg9XYXRjaERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiRAoPRmlsZXN5c3RlbUV2ZW50EgwKBG5hbWUYASABKAkSIwoEdHlwZRgCIAEoDjIVLmZpbGVzeXN0ZW0uRXZlbnRUeXBlIuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiNwoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiKwoVQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEhIKCndhdGNoZXJfaWQYASABKAkiLQoXR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSJHChhHZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USKwoGZXZlbnRzGAEgAygLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnQiKgoUUmVtb3ZlV2F0Y2hlclJlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSIXChVSZW1vdmVXYXRjaGVyUmVzcG9uc2UqUgoIRmlsZVR5cGUSGQoVRklMRV9UWVBFX1VOU1BFQ0lGSUVEEAASEgoORklMRV9UWVBFX0ZJTEUQARIXChNGSUxFX1RZUEVfRElSRUNUT1JZEAIqmAEKCUV2ZW50VHlwZRIaChZFVkVOVF9UWVBFX1VOU1BFQ0lGSUVEEAASFQoRRVZFTlRfVFlQRV9DUkVBVEUQARIUChBFVkVOVF9UWVBFX1dSSVRFEAISFQoRRVZFTlRfVFlQRV9SRU1PVkUQAxIVChFFVkVOVF9UWVBFX1JFTkFNRRAEEhQKEEVWRU5UX1RZUEVfQ0hNT0QQBTKfBQoKRmlsZXN5c3RlbRI5CgRTdGF0EhcuZmlsZXN5c3RlbS5TdGF0UmVxdWVzdBoYLmZpbGVzeXN0ZW0uU3RhdFJlc3BvbnNlEkIKB01ha2VEaXISGi5maWxlc3lzdGVtLk1ha2VEaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5NYWtlRGlyUmVzcG9uc2USOQoETW92ZRIXLmZpbGVzeXN0ZW0uTW92ZVJlcXVlc3QaGC5maWxlc3lzdGVtLk1vdmVSZXNwb25zZRJCCgdMaXN0RGlyEhouZmlsZXN5c3RlbS5MaXN0RGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTGlzdERpclJlc3BvbnNlEj8KBlJlbW92ZRIZLmZpbGVzeXN0ZW0uUmVtb3ZlUmVxdWVzdBoaLmZpbGVzeXN0ZW0uUmVtb3ZlUmVzcG9uc2USRwoIV2F0Y2hEaXISGy5maWxlc3lzdGVtLldhdGNoRGlyUmVxdWVzdBocLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZTABElQKDUNyZWF0ZVdhdGNoZXISIC5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVzcG9uc2USXQoQR2V0V2F0Y2hlckV2ZW50cxIjLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QaJC5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXNwb25zZRJUCg1SZW1vdmVXYXRjaGVyEiAuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlc3BvbnNlQmkKDmNvbS5maWxlc3lzdGVtQg9GaWxlc3lzdGVtUHJvdG9QAaICA0ZYWKoCCkZpbGVzeXN0ZW3KAgpGaWxlc3lzdGVt4gIWRmlsZXN5c3RlbVxHUEJNZXRhZGF0YeoCCkZpbGVzeXN0ZW1iBnByb3RvMw", [import_wkt.file_google_protobuf_timestamp] ); var Filesystem = /* @__PURE__ */ (0, import_codegenv2.serviceDesc)(file_filesystem_filesystem, 0); // src/sandbox/filesystem/watchHandle.ts var FilesystemEventType = /* @__PURE__ */ ((FilesystemEventType2) => { FilesystemEventType2["CHMOD"] = "chmod"; FilesystemEventType2["CREATE"] = "create"; FilesystemEventType2["REMOVE"] = "remove"; FilesystemEventType2["RENAME"] = "rename"; FilesystemEventType2["WRITE"] = "write"; return FilesystemEventType2; })(FilesystemEventType || {}); function mapEventType(type) { switch (type) { case 5 /* CHMOD */: return "chmod" /* CHMOD */; case 1 /* CREATE */: return "create" /* CREATE */; case 3 /* REMOVE */: return "remove" /* REMOVE */; case 4 /* RENAME */: return "rename" /* RENAME */; case 2 /* WRITE */: return "write" /* WRITE */; } } var WatchHandle = class { constructor(handleStop, events, onEvent, onExit) { this.handleStop = handleStop; this.events = events; this.onEvent = onEvent; this.onExit = onExit; this.handleEvents(); } /** * Stop watching the directory. */ async stop() { this.handleStop(); } iterateEvents() { return __asyncGenerator(this, null, function* () { try { try { for (var iter = __forAwait(this.events), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) { const event = temp.value; switch (event.event.case) { case "filesystem": yield event.event; break; } } } catch (temp) { error = [temp]; } finally { try { more && (temp = iter.return) && (yield new __await(temp.call(iter))); } finally { if (error) throw error[0]; } } } catch (err) { throw handleRpcError(err); } }); } async handleEvents() { var _a3, _b, _c; try { try { for (var iter = __forAwait(this.iterateEvents()), more, temp, error; more = !(temp = await iter.next()).done; more = false) { const event = temp.value; const eventType = mapEventType(event.value.type); if (eventType === void 0) { continue; } (_a3 = this.onEvent) == null ? void 0 : _a3.call(this, { name: event.value.name, type: eventType }); } } catch (temp) { error = [temp]; } finally { try { more && (temp = iter.return) && await temp.call(iter); } finally { if (error) throw error[0]; } } (_b = this.onExit) == null ? void 0 : _b.call(this); } catch (err) { (_c = this.onExit) == null ? void 0 : _c.call(this, err); } finally { this.handleStop(); } } }; // src/sandbox/filesystem/index.ts var import_compare_versions2 = require("compare-versions"); var FILESYSTEM_HTTP_ERROR_MAP = { 404: (message) => new FileNotFoundError(message) }; var FILESYSTEM_RPC_ERROR_MAP = { [import_connect3.Code.NotFound]: (message) => new FileNotFoundError(message) }; function handleFilesystemRpcError(err) { return handleRpcError(err, FILESYSTEM_RPC_ERROR_MAP); } function handleFilesystemEnvdApiError(res) { return handleEnvdApiError(res, FILESYSTEM_HTTP_ERROR_MAP); } var FileType2 = /* @__PURE__ */ ((FileType3) => { FileType3["FILE"] = "file"; FileType3["DIR"] = "dir"; return FileType3; })(FileType2 || {}); function mapFileType(fileType) { switch (fileType) { case 2 /* DIRECTORY */: return "dir" /* DIR */; case 1 /* FILE */: return "file" /* FILE */; } } function mapModifiedTime(modifiedTime) { if (!modifiedTime) return void 0; return new Date( Number(modifiedTime.seconds) * 1e3 + Math.floor(modifiedTime.nanos / 1e6) ); } var Filesystem2 = class { constructor(transport, envdApi, connectionConfig) { this.envdApi = envdApi; this.connectionConfig = connectionConfig; this.defaultWatchTimeout = 6e4; // 60 seconds this.defaultWatchRecursive = false; this.rpc = (0, import_connect3.createClient)(Filesystem, transport); } async read(path2, opts) { var _a3; const format = (_a3 = opts == null ? void 0 : opts.format) != null ? _a3 : "text"; let user = opts == null ? void 0 : opts.user; if (user == void 0 && (0, import_compare_versions2.compareVersions)(this.envdApi.version, ENVD_DEFAULT_USER) < 0) { user = defaultUsername; } const headers = {}; if (opts == null ? void 0 : opts.gzip) { headers["Accept-Encoding"] = "gzip"; } const res = await this.envdApi.api.GET("/files", { params: { query: { path: path2, username: user } }, parseAs: format === "bytes" ? "arrayBuffer" : format, signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ), headers }); const err = await handleFilesystemEnvdApiError(res); if (err) { throw err; } if (format === "bytes") { return new Uint8Array(res.data); } if (res.response.headers.get("content-length") === "0") { return ""; } return res.data; } async write(pathOrFiles, dataOrOpts, opts) { var _a3, _b; 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: path2, 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 ? void 0 : writeOpts.user; if (user == void 0 && (0, import_compare_versions2.compareVersions)(this.envdApi.version, ENVD_DEFAULT_USER) < 0) { user = defaultUsername; } const supportsOctetStream = (0, import_compare_versions2.compareVersions)(this.envdApi.version, ENVD_OCTET_STREAM_UPLOAD) >= 0; const useOctetStream = ((_a3 = writeOpts == null ? void 0 : writeOpts.useOctetStream) != null ? _a3 : false) && supportsOctetStream; const results = []; const useGzip = (writeOpts == null ? void 0 : writeOpts.gzip) === true; if (useOctetStream) { const headers = { "Content-Type": "application/octet-stream" }; if (useGzip) { headers["Content-Encoding"] = "gzip"; } const uploadResults = await Promise.all( writeFiles.map(async (file) => { const filePath = path2 != null ? path2 : file.path; const body = await toUploadBody(file.data, useGzip); const res = await this.envdApi.api.POST("/files", { params: { query: { path: filePath, username: user } }, bodySerializer: () => body, headers, signal: this.connectionConfig.getSignal( writeOpts == null ? void 0 : writeOpts.requestTimeoutMs, writeOpts == null ? void 0 : writeOpts.signal ), body: {} }); 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" ); } return files; }) ); for (const files of uploadResults) { results.push(...files); } } else { const formData = new FormData(); for (const file of writeFiles) { formData.append( "file", await toBlob(file.data), (_b = file.path) != null ? _b : path2 ); } const res = await this.envdApi.api.POST("/files", { params: { query: { path: path2, username: user } }, bodySerializer: () => formData, signal: this.connectionConfig.getSignal( writeOpts == null ? void 0 : writeOpts.requestTimeoutMs, writeOpts == null ? void 0 : writeOpts.signal ), body: {} }); 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"); } results.push(...files); } return results.length === 1 && path2 ? 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(path2, opts) { var _a3; if (typeof (opts == null ? void 0 : opts.depth) === "number" && opts.depth < 1) { throw new InvalidArgumentError("depth should be at least one"); } try { const res = await this.rpc.listDir( { path: path2, depth: (_a3 = opts == null ? void 0 : opts.depth) != null ? _a3 : 1 }, { headers: authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user), signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ) } ); const entries = []; for (const e of res.entries) { const type = mapFileType(e.type); if (type) { entries.push({ name: e.name, type, path: e.path, size: Number(e.size), mode: e.mode, permissions: e.permissions, owner: e.owner, group: e.group, modifiedTime: mapModifiedTime(e.modifiedTime), symlinkTarget: e.symlinkTarget }); } } return entries; } catch (err) { throw handleFilesystemRpcError(err); } } /** * Create a new directory and all directories along the way if needed on the specified path. * * @param path path to a new directory. For example '/dirA/dirB' when creating 'dirB'. * @param opts connection options. * * @returns `true` if the directory was created, `false` if it already exists. */ async makeDir(path2, opts) { try { await this.rpc.makeDir( { path: path2 }, { headers: authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user), signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ) } ); return true; } catch (err) { if (err instanceof import_connect3.ConnectError) { if (err.code === import_connect3.Code.AlreadyExists) { return false; } } throw handleFilesystemRpcError(err); } } /** * Rename a file or directory. * * @param oldPath path to the file or directory to rename. * @param newPath new path for the file or directory. * @param opts connection options. * * @returns information about renamed file or directory. */ async rename(oldPath, newPath, opts) { try { const res = await this.rpc.move( { source: oldPath, destination: newPath }, { headers: authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user), signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ) } ); const entry = res.entry; if (!entry) { throw new Error("Expected to receive information about moved object"); } return { name: entry.name, type: mapFileType(entry.type), path: entry.path, size: Number(entry.size), mode: entry.mode, permissions: entry.permissions, owner: entry.owner, group: entry.group, modifiedTime: mapModifiedTime(entry.modifiedTime), symlinkTarget: entry.symlinkTarget }; } catch (err) { throw handleFilesystemRpcError(err); } } /** * Remove a file or directory. * * @param path path to a file or directory. * @param opts connection options. */ async remove(path2, opts) { try { await this.rpc.remove( { path: path2 }, { headers: authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user), signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ) } ); } catch (err) { throw handleFilesystemRpcError(err); } } /** * Check if a file or a directory exists. * * @param path path to a file or a directory * @param opts connection options. * * @returns `true` if the file or directory exists, `false` otherwise */ async exists(path2, opts) { try { await this.rpc.stat( { path: path2 }, { headers: authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user), signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ) } ); return true; } catch (err) { if (err instanceof import_connect3.ConnectError) { if (err.code === import_connect3.Code.NotFound) { return false; } } throw handleFilesystemRpcError(err); } } /** * Get information about a file or directory. * * @param path path to a file or directory. * @param opts connection options. * * @returns information about the file or directory like name, type, and path. */ async getInfo(path2, opts) { try { const res = await this.rpc.stat( { path: path2 }, { headers: authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user), signal: this.connectionConfig.getSignal( opts == null ? void 0 : opts.requestTimeoutMs, opts == null ? void 0 : opts.signal ) } ); if (!res.entry) { throw new Error( "Expected to receive information about the file or directory" ); } return { name: res.entry.name, type: mapFileType(res.entry.type), path: res.entry.path, size: Number(res.entry.size), mode: res.entry.mode, permissions: res.entry.permissions, owner: res.entry.owner, group: res.entry.group, modifiedTime: mapModifiedTime(res.entry.modifiedTime), symlinkTarget: res.entry.symlinkTarget }; } catch (err) { throw handleFilesystemRpcError(err); } } /** * Start watching a directory for filesystem events. * * @param path path to directory to watch. * @param onEvent callback to call when an event in the directory occurs. * @param opts connection options. * * @returns `WatchHandle` object for stopping watching directory. */ async watchDir(path2, onEvent, opts) { var _a3, _b, _c; if ((opts == null ? void 0 : opts.recursive) && this.envdApi.version && (0, import_compare_versions2.compareVersions)(this.envdApi.version, ENVD_VERSION_RECURSIVE_WATCH) < 0) { throw new TemplateError( "You need to update the template to use recursive watching. You can do this by running `e2b template build` in the directory with the template." ); } const requestTimeoutMs = (_a3 = opts == null ? void 0 : opts.requestTimeoutMs) != null ? _a3 : this.connectionConfig.requestTimeoutMs; const { controller, clearStartTimeout, cleanup } = setupRequestController( requestTimeoutMs, opts == null ? void 0 : opts.signal ); const events = this.rpc.watchDir( { path: path2, recursive: (_b = opts == null ? void 0 : opts.recursive) != null ? _b : this.defaultWatchRecursive }, { headers: __spreadProps(__spreadValues({}, authenticationHeader(this.envdApi.version, opts == null ? void 0 : opts.user)), { [KEEPALIVE_PING_HEADER]: KEEPALIVE_PING_INTERVAL_SEC.toString() }), signal: controller.signal, timeoutMs: (_c = opts == null ? void 0 : opts.timeoutMs) != null ? _c : this.defaultWatchTimeout } ); try { await handleWatchDirStartEvent(events); clearStartTimeout(); return new WatchHandle(cleanup, events, onEvent, opts == null ? void 0 : opts.onExit); } catch (err) { cleanup(); throw handleFilesystemRpcError(err); } } }; // src/sandbox/commands/commandHandle.ts var CommandExi