@fastgpt-sdk/sandbox-adapter 0.0.35 → 0.0.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -4,39 +4,60 @@ var __defProp = Object.defineProperty;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
7
12
  var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
8
20
  target = mod != null ? __create(__getProtoOf(mod)) : {};
9
21
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
22
  for (let key of __getOwnPropNames(mod))
11
23
  if (!__hasOwnProp.call(to, key))
12
24
  __defProp(to, key, {
13
- get: () => mod[key],
25
+ get: __accessProp.bind(mod, key),
14
26
  enumerable: true
15
27
  });
28
+ if (canCache)
29
+ cache.set(mod, to);
16
30
  return to;
17
31
  };
18
- var __moduleCache = /* @__PURE__ */ new WeakMap;
19
32
  var __toCommonJS = (from) => {
20
- var entry = __moduleCache.get(from), desc;
33
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
21
34
  if (entry)
22
35
  return entry;
23
36
  entry = __defProp({}, "__esModule", { value: true });
24
- if (from && typeof from === "object" || typeof from === "function")
25
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
26
- get: () => from[key],
27
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
28
- }));
37
+ if (from && typeof from === "object" || typeof from === "function") {
38
+ for (var key of __getOwnPropNames(from))
39
+ if (!__hasOwnProp.call(entry, key))
40
+ __defProp(entry, key, {
41
+ get: __accessProp.bind(from, key),
42
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
43
+ });
44
+ }
29
45
  __moduleCache.set(from, entry);
30
46
  return entry;
31
47
  };
48
+ var __moduleCache;
32
49
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
50
+ var __returnValue = (v) => v;
51
+ function __exportSetter(name, newValue) {
52
+ this[name] = __returnValue.bind(null, newValue);
53
+ }
33
54
  var __export = (target, all) => {
34
55
  for (var name in all)
35
56
  __defProp(target, name, {
36
57
  get: all[name],
37
58
  enumerable: true,
38
59
  configurable: true,
39
- set: (newValue) => all[name] = () => newValue
60
+ set: __exportSetter.bind(all, name)
40
61
  });
41
62
  };
42
63
  var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
@@ -19139,7 +19160,7 @@ var require_frame = __commonJS((exports2, module2) => {
19139
19160
  var BUFFER_SIZE = 8 * 1024;
19140
19161
  var buffer = null;
19141
19162
  var bufIdx = BUFFER_SIZE;
19142
- var randomFillSync = runtimeFeatures.has("crypto") ? require("node:crypto").randomFillSync : function randomFillSync(buffer2, _offset, _size) {
19163
+ var randomFillSync = runtimeFeatures.has("crypto") ? require("node:crypto").randomFillSync : function randomFillSync2(buffer2, _offset, _size) {
19143
19164
  for (let i = 0;i < buffer2.length; ++i) {
19144
19165
  buffer2[i] = Math.random() * 255 | 0;
19145
19166
  }
@@ -21083,7 +21104,7 @@ var require_eventsource = __commonJS((exports2, module2) => {
21083
21104
 
21084
21105
  // node_modules/undici/index.js
21085
21106
  var require_undici = __commonJS((exports2, module2) => {
21086
- var __filename = "/Volumes/code/dev/agent-sandbox-adaptor/node_modules/undici/index.js";
21107
+ var __filename = "/Users/sealos/Documents/GitHub/agent-sandbox-adaptor/node_modules/undici/index.js";
21087
21108
  var Client = require_client();
21088
21109
  var Dispatcher = require_dispatcher();
21089
21110
  var Pool = require_pool();
@@ -21206,7 +21227,7 @@ var require_undici = __commonJS((exports2, module2) => {
21206
21227
  err.stack = stack ? `${stack}
21207
21228
  ${captureLines}` : capture.stack;
21208
21229
  }
21209
- module2.exports.fetch = function fetch(init, options = undefined) {
21230
+ module2.exports.fetch = function fetch2(init, options = undefined) {
21210
21231
  return fetchImpl(init, options).catch((err) => {
21211
21232
  appendFetchStackTrace(err, __filename);
21212
21233
  throw err;
@@ -45023,13 +45044,34 @@ class CommandPolyfillService {
45023
45044
  constructor(executor) {
45024
45045
  this.executor = executor;
45025
45046
  }
45047
+ static READ_CHUNK_SIZE = 256 * 1024;
45026
45048
  async readFile(path) {
45027
45049
  try {
45028
- const result = await this.executor.execute(`cat "${this.escapePath(path)}" | base64 -w 0`);
45029
- if (result.exitCode !== 0) {
45030
- throw this.createFileError(path, result.stderr);
45050
+ const size = await this.statSize(path);
45051
+ if (size === undefined) {
45052
+ const result = await this.executor.execute(`cat "${this.escapePath(path)}" | base64 -w 0`);
45053
+ if (result.exitCode !== 0) {
45054
+ throw this.createFileError(path, result.stderr);
45055
+ }
45056
+ return base64ToBytes(result.stdout);
45057
+ }
45058
+ if (size === 0)
45059
+ return new Uint8Array;
45060
+ const chunks = [];
45061
+ let totalLength = 0;
45062
+ for (let offset = 0;offset < size; offset += CommandPolyfillService.READ_CHUNK_SIZE) {
45063
+ const end = Math.min(offset + CommandPolyfillService.READ_CHUNK_SIZE, size);
45064
+ const chunk = await this.readFileRange(path, offset, end);
45065
+ chunks.push(chunk);
45066
+ totalLength += chunk.length;
45031
45067
  }
45032
- return base64ToBytes(result.stdout);
45068
+ const combined = new Uint8Array(totalLength);
45069
+ let writeOffset = 0;
45070
+ for (const chunk of chunks) {
45071
+ combined.set(chunk, writeOffset);
45072
+ writeOffset += chunk.length;
45073
+ }
45074
+ return combined;
45033
45075
  } catch (error) {
45034
45076
  if (error instanceof FileOperationError) {
45035
45077
  throw error;
@@ -45040,9 +45082,18 @@ class CommandPolyfillService {
45040
45082
  throw error;
45041
45083
  }
45042
45084
  }
45085
+ async statSize(path) {
45086
+ const result = await this.executor.execute(`stat -c '%s' "${this.escapePath(path)}" 2>/dev/null || stat -f '%z' "${this.escapePath(path)}" 2>/dev/null || echo STAT_FAILED`);
45087
+ const stdout = result.stdout.trim();
45088
+ if (!stdout || stdout.includes("STAT_FAILED"))
45089
+ return;
45090
+ const parsed = Number.parseInt(stdout, 10);
45091
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : undefined;
45092
+ }
45043
45093
  async readFileRange(path, start, end) {
45044
- const length = end ? end - start : "";
45045
- const cmd = `dd if="${this.escapePath(path)}" bs=1 skip=${start} count=${length} 2>/dev/null | base64 -w 0`;
45094
+ const escaped = this.escapePath(path);
45095
+ const tailPos = start + 1;
45096
+ const cmd = end !== undefined ? `tail -c +${tailPos} "${escaped}" | head -c ${end - start} | base64 -w 0` : `tail -c +${tailPos} "${escaped}" | base64 -w 0`;
45046
45097
  const result = await this.executor.execute(cmd);
45047
45098
  if (result.exitCode !== 0) {
45048
45099
  throw this.createFileError(path, result.stderr);
@@ -45050,10 +45101,25 @@ class CommandPolyfillService {
45050
45101
  return base64ToBytes(result.stdout);
45051
45102
  }
45052
45103
  async writeFile(path, data) {
45104
+ await this.appendBytes(path, data, { truncate: true });
45105
+ return data.length;
45106
+ }
45107
+ async appendBytes(path, data, options) {
45108
+ if (options?.truncate) {
45109
+ await this.createParentDirectory(path);
45110
+ }
45111
+ if (data.length === 0) {
45112
+ if (options?.truncate) {
45113
+ const result = await this.executor.execute(`: > "${this.escapePath(path)}"`);
45114
+ if (result.exitCode !== 0) {
45115
+ throw this.createFileError(path, result.stderr);
45116
+ }
45117
+ }
45118
+ return;
45119
+ }
45053
45120
  const base64 = bytesToBase64(data);
45054
45121
  const chunkSize = 1024;
45055
- await this.createParentDirectory(path);
45056
- let first = true;
45122
+ let first = Boolean(options?.truncate);
45057
45123
  for (let i = 0;i < base64.length; i += chunkSize) {
45058
45124
  const chunk = base64.slice(i, i + chunkSize);
45059
45125
  const redirect = first ? ">" : ">>";
@@ -45063,7 +45129,6 @@ class CommandPolyfillService {
45063
45129
  }
45064
45130
  first = false;
45065
45131
  }
45066
- return data.length;
45067
45132
  }
45068
45133
  async writeTextFile(path, content) {
45069
45134
  await this.createParentDirectory(path);
@@ -45344,6 +45409,12 @@ class BaseSandboxAdapter {
45344
45409
  async renewExpiration(_additionalSeconds) {
45345
45410
  throw new FeatureNotSupportedError("Sandbox expiration renewal not supported by this provider", "renewExpiration", this.provider);
45346
45411
  }
45412
+ async getEndpoint(_selector) {
45413
+ throw new FeatureNotSupportedError("Endpoint resolution not supported by this provider", "getEndpoint", this.provider);
45414
+ }
45415
+ async getProxyTarget(_service = "code-server") {
45416
+ throw new FeatureNotSupportedError("Proxy target resolution not supported by this provider", "getProxyTarget", this.provider);
45417
+ }
45347
45418
  async executeStream(command, handlers, options) {
45348
45419
  const result = await this.execute(command, options);
45349
45420
  if (handlers.onStdout && result.stdout) {
@@ -45406,23 +45477,7 @@ class BaseSandboxAdapter {
45406
45477
  const arrayBuffer = await entry.data.arrayBuffer();
45407
45478
  bytesWritten = await polyfillService.writeFile(entry.path, new Uint8Array(arrayBuffer));
45408
45479
  } else {
45409
- const chunks = [];
45410
- const reader = entry.data.getReader();
45411
- while (true) {
45412
- const { done, value } = await reader.read();
45413
- if (done) {
45414
- break;
45415
- }
45416
- chunks.push(value);
45417
- }
45418
- const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
45419
- const combined = new Uint8Array(totalLength);
45420
- let offset = 0;
45421
- for (const chunk of chunks) {
45422
- combined.set(chunk, offset);
45423
- offset += chunk.length;
45424
- }
45425
- bytesWritten = await polyfillService.writeFile(entry.path, combined);
45480
+ bytesWritten = await this.writeStreamToFile(polyfillService, entry.path, entry.data);
45426
45481
  }
45427
45482
  results.push({ path: entry.path, bytesWritten, error: null });
45428
45483
  } catch (error) {
@@ -45497,23 +45552,36 @@ class BaseSandboxAdapter {
45497
45552
  }
45498
45553
  }
45499
45554
  async writeFileStream(path, stream) {
45555
+ const polyfillService = this.requirePolyfillService("writeFileStream", "File stream write not supported by this provider");
45556
+ await this.writeStreamToFile(polyfillService, this.normalizePath(path), stream);
45557
+ }
45558
+ async writeStreamToFile(polyfillService, path, stream) {
45559
+ const tmpPath = `${path}.tmp.${Date.now().toString(36)}${Math.random().toString(36).slice(2, 8)}`;
45500
45560
  const reader = stream.getReader();
45501
- const chunks = [];
45502
- while (true) {
45503
- const { done, value } = await reader.read();
45504
- if (done) {
45505
- break;
45561
+ let totalBytes = 0;
45562
+ let first = true;
45563
+ try {
45564
+ while (true) {
45565
+ const { done, value } = await reader.read();
45566
+ if (done)
45567
+ break;
45568
+ if (!value || value.length === 0)
45569
+ continue;
45570
+ await polyfillService.appendBytes(tmpPath, value, first ? { truncate: true } : undefined);
45571
+ totalBytes += value.length;
45572
+ first = false;
45506
45573
  }
45507
- chunks.push(value);
45508
- }
45509
- const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
45510
- const combined = new Uint8Array(totalLength);
45511
- let offset = 0;
45512
- for (const chunk of chunks) {
45513
- combined.set(chunk, offset);
45514
- offset += chunk.length;
45574
+ if (first) {
45575
+ await polyfillService.appendBytes(tmpPath, new Uint8Array, { truncate: true });
45576
+ }
45577
+ await polyfillService.moveFiles([{ source: tmpPath, destination: path }]);
45578
+ } catch (error) {
45579
+ await polyfillService.deleteFiles([tmpPath]).catch(() => {});
45580
+ throw error;
45581
+ } finally {
45582
+ reader.releaseLock();
45515
45583
  }
45516
- await this.writeFiles([{ path, data: combined }]);
45584
+ return totalBytes;
45517
45585
  }
45518
45586
  async getFileInfo(paths) {
45519
45587
  const polyfillService = this.requirePolyfillService("getFileInfo", "File info not supported by this provider");
@@ -45583,10 +45651,10 @@ class DevboxApi {
45583
45651
  const result = await res.json();
45584
45652
  return result;
45585
45653
  }
45586
- async create(name) {
45654
+ async create(req) {
45587
45655
  return this.request(this.url("/api/v1/devbox"), {
45588
45656
  method: "POST",
45589
- body: JSON.stringify({ name })
45657
+ body: JSON.stringify(req)
45590
45658
  });
45591
45659
  }
45592
45660
  async info(name) {
@@ -45644,18 +45712,60 @@ class DevboxApi {
45644
45712
  }
45645
45713
  }
45646
45714
 
45715
+ // src/adapters/ports.ts
45716
+ var OPEN_SANDBOX_EXECD_PORT = 44772;
45717
+ var OPEN_SANDBOX_CODE_SERVER_PORT = 8080;
45718
+ var SEALOS_DEVBOX_CODE_SERVER_PORT = 1318;
45719
+
45720
+ // src/utils/image.ts
45721
+ function formatImageSpec(image) {
45722
+ const parts = [image.repository];
45723
+ if (image.tag)
45724
+ parts.push(":", image.tag);
45725
+ if (image.digest)
45726
+ parts.push("@", image.digest);
45727
+ return parts.join("");
45728
+ }
45729
+ function parseImageSpec(image) {
45730
+ if (!image)
45731
+ return { repository: "" };
45732
+ const atIndex = image.indexOf("@");
45733
+ if (atIndex > -1) {
45734
+ return { repository: image.slice(0, atIndex), digest: image.slice(atIndex + 1) };
45735
+ }
45736
+ const colonIndex = image.indexOf(":");
45737
+ if (colonIndex > -1) {
45738
+ return { repository: image.slice(0, colonIndex), tag: image.slice(colonIndex + 1) };
45739
+ }
45740
+ return { repository: image };
45741
+ }
45742
+
45743
+ // src/utils/url.ts
45744
+ function normalizePathPrefix(path) {
45745
+ if (!path)
45746
+ return "";
45747
+ const normalized = path.startsWith("/") ? path : `/${path}`;
45748
+ return normalized.length > 1 ? normalized.replace(/\/+$/, "") : "";
45749
+ }
45750
+ function joinUrlPath(url, path) {
45751
+ const normalizedPath = normalizePathPrefix(path);
45752
+ return normalizedPath ? `${url.replace(/\/+$/, "")}${normalizedPath}` : url.replace(/\/+$/, "");
45753
+ }
45754
+
45647
45755
  // src/adapters/SealosDevboxAdapter/index.ts
45648
45756
  class SealosDevboxAdapter extends BaseSandboxAdapter {
45649
45757
  config;
45758
+ createConfig;
45650
45759
  provider = "sealosdevbox";
45651
45760
  get rootPath() {
45652
45761
  return "/home/devbox/workspace";
45653
45762
  }
45654
45763
  api;
45655
45764
  _id;
45656
- constructor(config) {
45765
+ constructor(config, createConfig) {
45657
45766
  super();
45658
45767
  this.config = config;
45768
+ this.createConfig = createConfig;
45659
45769
  this.api = new DevboxApi({ baseUrl: config.baseUrl, token: config.token });
45660
45770
  this._id = config.sandboxId;
45661
45771
  this.polyfillService = new CommandPolyfillService(this);
@@ -45680,6 +45790,26 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45680
45790
  return "Error";
45681
45791
  }
45682
45792
  }
45793
+ buildCreateRequest() {
45794
+ const spec = this.createConfig ?? {};
45795
+ const env = { ...spec.env ?? {} };
45796
+ if (spec.workingDir && !env.CODEX_GATEWAY_CWD) {
45797
+ env.CODEX_GATEWAY_CWD = spec.workingDir;
45798
+ }
45799
+ return this.removeUndefined({
45800
+ name: this._id,
45801
+ image: spec.image ? formatImageSpec(spec.image) : undefined,
45802
+ env: Object.keys(env).length > 0 ? env : undefined,
45803
+ labels: spec.labels,
45804
+ upstreamID: spec.upstreamID,
45805
+ kubeAccess: spec.kubeAccess,
45806
+ pauseAt: spec.lifecycle?.pauseAt,
45807
+ archiveAfterPauseTime: spec.lifecycle?.archiveAfterPauseTime
45808
+ });
45809
+ }
45810
+ removeUndefined(obj) {
45811
+ return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== undefined));
45812
+ }
45683
45813
  async getInfo() {
45684
45814
  try {
45685
45815
  const res = await this.api.info(this._id);
@@ -45691,10 +45821,10 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45691
45821
  this._status = { state: this.StatusAdapt(data), message: res.message };
45692
45822
  return {
45693
45823
  id: data.name,
45694
- image: { repository: "" },
45824
+ image: parseImageSpec(data.image),
45695
45825
  entrypoint: [],
45696
45826
  status: this._status,
45697
- createdAt: new Date
45827
+ createdAt: data.creationTimestamp ? new Date(data.creationTimestamp) : new Date
45698
45828
  };
45699
45829
  } catch (error) {
45700
45830
  throw new CommandExecutionError(`Failed to get sandbox info`, "getInfo", error instanceof Error ? error : undefined);
@@ -45732,7 +45862,10 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45732
45862
  async create() {
45733
45863
  try {
45734
45864
  this._status = { state: "Creating" };
45735
- await this.api.create(this._id);
45865
+ const res = await this.api.create(this.buildCreateRequest());
45866
+ if (res.code !== 200 && res.code !== 201) {
45867
+ throw new Error(res.message || `Devbox create failed with code ${res.code}`);
45868
+ }
45736
45869
  await this.waitUntilReady();
45737
45870
  await new Promise((resolve) => setTimeout(resolve, 1000));
45738
45871
  this._status = { state: "Running" };
@@ -45788,11 +45921,98 @@ class SealosDevboxAdapter extends BaseSandboxAdapter {
45788
45921
  throw new CommandExecutionError(`Command execution failed: ${error?.message || error?.code}`, command, error instanceof Error ? error : undefined);
45789
45922
  }
45790
45923
  }
45924
+ async getEndpoint(selector) {
45925
+ const port = typeof selector === "number" ? selector : SEALOS_DEVBOX_CODE_SERVER_PORT;
45926
+ const target = await this.getHttpgateTarget(port);
45927
+ const url = new URL(target.origin);
45928
+ return {
45929
+ host: url.host,
45930
+ port: target.port,
45931
+ protocol: url.protocol === "https:" ? "https" : "http",
45932
+ url: joinUrlPath(target.origin, target.basePath)
45933
+ };
45934
+ }
45935
+ async getProxyTarget(service = "code-server") {
45936
+ if (service !== "code-server") {
45937
+ throw new FeatureNotSupportedError(`Proxy service "${service}" is not supported by this provider`, "getProxyTarget", this.provider);
45938
+ }
45939
+ const target = await this.getHttpgateTarget(SEALOS_DEVBOX_CODE_SERVER_PORT);
45940
+ return {
45941
+ service,
45942
+ origin: target.origin,
45943
+ basePath: target.basePath,
45944
+ auth: "code-server",
45945
+ ...target.password ? { password: target.password } : {}
45946
+ };
45947
+ }
45948
+ async getHttpgateTarget(port) {
45949
+ const res = await this.api.info(this._id);
45950
+ if (res.code !== 200 || !res.data) {
45951
+ throw new ConnectionError(`Failed to get devbox info: ${res.message}`, this.config.baseUrl);
45952
+ }
45953
+ if (port === SEALOS_DEVBOX_CODE_SERVER_PORT) {
45954
+ const gateway2 = res.data.codeServerGateway;
45955
+ if (!gateway2?.url) {
45956
+ throw new ConnectionError("Devbox info does not include codeServerGateway.url; cannot resolve code-server endpoint", this.config.baseUrl);
45957
+ }
45958
+ const codeServerUrl = new URL(gateway2.url);
45959
+ return {
45960
+ origin: codeServerUrl.origin,
45961
+ basePath: normalizePathPrefix(codeServerUrl.pathname),
45962
+ port: gateway2.port ?? port,
45963
+ password: gateway2.password
45964
+ };
45965
+ }
45966
+ const gatewayUrl = res.data.gateway?.url;
45967
+ if (!gatewayUrl) {
45968
+ throw new ConnectionError("Devbox info does not include gateway.url; cannot derive httpgate endpoint", this.config.baseUrl);
45969
+ }
45970
+ const gateway = new URL(gatewayUrl);
45971
+ const uniqueID = this.getGatewayUniqueID(res.data, gateway);
45972
+ const domain = this.getHttpgateDomain(gateway);
45973
+ return {
45974
+ origin: `${gateway.protocol}//devbox-${uniqueID}-${port}.${domain}`,
45975
+ basePath: "",
45976
+ port
45977
+ };
45978
+ }
45979
+ getGatewayUniqueID(data, gateway) {
45980
+ if (data.gateway?.uniqueID)
45981
+ return data.gateway.uniqueID;
45982
+ const parts = gateway.pathname.split("/").filter(Boolean);
45983
+ const uniqueID = parts[parts.length - 1];
45984
+ if (!uniqueID) {
45985
+ throw new ConnectionError("Devbox gateway.url does not include uniqueID; cannot derive httpgate endpoint", this.config.baseUrl);
45986
+ }
45987
+ return uniqueID;
45988
+ }
45989
+ getHttpgateDomain(gateway) {
45990
+ if (this.config.httpgateDomain) {
45991
+ return this.normalizeHttpgateDomain(this.config.httpgateDomain);
45992
+ }
45993
+ const prefix = "devbox-gateway.";
45994
+ if (!gateway.host.startsWith(prefix)) {
45995
+ throw new ConnectionError(`Cannot derive httpgate domain from gateway host "${gateway.host}"`, this.config.baseUrl);
45996
+ }
45997
+ return gateway.host.slice(prefix.length);
45998
+ }
45999
+ normalizeHttpgateDomain(domain) {
46000
+ const trimmed = domain.trim().replace(/^\.+|\.+$/g, "");
46001
+ if (!trimmed) {
46002
+ throw new ConnectionError("httpgateDomain is empty", this.config.baseUrl);
46003
+ }
46004
+ if (trimmed.includes("://")) {
46005
+ return new URL(trimmed).host;
46006
+ }
46007
+ return trimmed;
46008
+ }
45791
46009
  async ping() {
45792
46010
  try {
45793
46011
  const res = await this.api.info(this._id);
45794
46012
  if (res.code !== 200)
45795
46013
  return false;
46014
+ if (!res.data)
46015
+ return false;
45796
46016
  return res.data.state.phase === "Running" /* Running */;
45797
46017
  } catch {
45798
46018
  return false;
@@ -47384,7 +47604,7 @@ function createNodeFetch() {
47384
47604
  const nodeFetch = async (input, init) => {
47385
47605
  dispatcherPromise ??= (async () => {
47386
47606
  try {
47387
- const mod = await Promise.resolve().then(() => __toESM(require_undici()));
47607
+ const mod = await Promise.resolve().then(() => __toESM(require_undici(), 1));
47388
47608
  const Agent = mod.Agent;
47389
47609
  if (!Agent) {
47390
47610
  return;
@@ -47909,7 +48129,79 @@ var Sandbox = class _Sandbox {
47909
48129
  }
47910
48130
  };
47911
48131
 
48132
+ // src/utils/outputBuffer.ts
48133
+ class BoundedOutputBuffer {
48134
+ maxBytes;
48135
+ chunks = [];
48136
+ currentBytes = 0;
48137
+ _totalBytes = 0;
48138
+ _truncated = false;
48139
+ separatorBuf;
48140
+ constructor(maxBytes, separator) {
48141
+ this.maxBytes = maxBytes;
48142
+ if (!(maxBytes > 0)) {
48143
+ throw new Error(`BoundedOutputBuffer: maxBytes must be > 0 (got ${maxBytes})`);
48144
+ }
48145
+ if (separator) {
48146
+ this.separatorBuf = Buffer.from(separator, "utf8");
48147
+ }
48148
+ }
48149
+ append(text) {
48150
+ if (!text)
48151
+ return;
48152
+ const needsSep = this.separatorBuf && this.chunks.length > 0;
48153
+ const textBuf = Buffer.from(text, "utf8");
48154
+ const sepLen = needsSep ? this.separatorBuf.length : 0;
48155
+ this._totalBytes += textBuf.length + sepLen;
48156
+ if (textBuf.length + sepLen > this.maxBytes) {
48157
+ this._truncated = true;
48158
+ const keep = Math.min(textBuf.length, this.maxBytes);
48159
+ this.chunks = [
48160
+ keep < textBuf.length ? Buffer.from(textBuf.subarray(textBuf.length - keep)) : textBuf
48161
+ ];
48162
+ this.currentBytes = keep;
48163
+ return;
48164
+ }
48165
+ const chunk = needsSep ? Buffer.concat([this.separatorBuf, textBuf]) : textBuf;
48166
+ this.chunks.push(chunk);
48167
+ this.currentBytes += chunk.length;
48168
+ if (this.currentBytes <= this.maxBytes)
48169
+ return;
48170
+ this._truncated = true;
48171
+ while (this.chunks.length > 1 && this.currentBytes - this.chunks[0].length >= this.maxBytes) {
48172
+ this.currentBytes -= this.chunks[0].length;
48173
+ this.chunks.shift();
48174
+ }
48175
+ if (this.currentBytes > this.maxBytes && this.chunks.length > 0) {
48176
+ const overflow = this.currentBytes - this.maxBytes;
48177
+ this.chunks[0] = this.chunks[0].subarray(overflow);
48178
+ this.currentBytes -= overflow;
48179
+ }
48180
+ if (this.separatorBuf && this.chunks.length > 0) {
48181
+ const first = this.chunks[0];
48182
+ const sep = this.separatorBuf;
48183
+ if (first.subarray(0, sep.length).equals(sep)) {
48184
+ this.chunks[0] = first.subarray(sep.length);
48185
+ this.currentBytes -= sep.length;
48186
+ }
48187
+ }
48188
+ }
48189
+ get totalBytes() {
48190
+ return this._totalBytes;
48191
+ }
48192
+ get truncated() {
48193
+ return this._truncated;
48194
+ }
48195
+ toString() {
48196
+ if (this.chunks.length === 0)
48197
+ return "";
48198
+ return Buffer.concat(this.chunks, this.currentBytes).toString("utf8");
48199
+ }
48200
+ }
48201
+
47912
48202
  // src/adapters/OpenSandboxAdapter/index.ts
48203
+ var DEFAULT_MAX_OUTPUT_BYTES = 1024 * 1024;
48204
+
47913
48205
  class OpenSandboxAdapter extends BaseSandboxAdapter {
47914
48206
  connectionConfig;
47915
48207
  createConfig;
@@ -47972,27 +48264,6 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
47972
48264
  message: sdkStatus.message
47973
48265
  };
47974
48266
  }
47975
- convertImageSpec(image) {
47976
- const parts = [image.repository];
47977
- if (image.tag) {
47978
- parts.push(":", image.tag);
47979
- }
47980
- if (image.digest) {
47981
- parts.push("@", image.digest);
47982
- }
47983
- return parts.join("");
47984
- }
47985
- parseImageSpec(image) {
47986
- const atIndex = image.indexOf("@");
47987
- if (atIndex > -1) {
47988
- return { repository: image.slice(0, atIndex), digest: image.slice(atIndex + 1) };
47989
- }
47990
- const colonIndex = image.indexOf(":");
47991
- if (colonIndex > -1) {
47992
- return { repository: image.slice(0, colonIndex), tag: image.slice(colonIndex + 1) };
47993
- }
47994
- return { repository: image };
47995
- }
47996
48267
  convertResourceLimits(resourceLimits) {
47997
48268
  if (!resourceLimits)
47998
48269
  return;
@@ -48107,7 +48378,7 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48107
48378
  }
48108
48379
  try {
48109
48380
  this._status = { state: "Creating" };
48110
- const image = this.convertImageSpec(cfg.image);
48381
+ const image = formatImageSpec(cfg.image);
48111
48382
  const resource = this.convertResourceLimits(cfg.resourceLimits);
48112
48383
  this.sandbox = await Sandbox.create({
48113
48384
  connectionConfig: this._connection,
@@ -48211,7 +48482,18 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48211
48482
  async close() {
48212
48483
  await this.sandbox.close();
48213
48484
  }
48214
- async getEndpoint(port) {
48485
+ async getEndpoint(selector) {
48486
+ const port = typeof selector === "number" ? selector : OPEN_SANDBOX_EXECD_PORT;
48487
+ const endpoint = await this.getOpenSandboxEndpoint(port);
48488
+ if (selector === "code-server") {
48489
+ return {
48490
+ ...endpoint,
48491
+ url: joinUrlPath(endpoint.url, `/proxy/${OPEN_SANDBOX_CODE_SERVER_PORT}`)
48492
+ };
48493
+ }
48494
+ return endpoint;
48495
+ }
48496
+ async getOpenSandboxEndpoint(port) {
48215
48497
  const sdkEndpoint = await this.sandbox.getEndpoint(port);
48216
48498
  const raw = sdkEndpoint.endpoint;
48217
48499
  const colonIdx = raw.lastIndexOf(":");
@@ -48230,6 +48512,40 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48230
48512
  url: `https://${raw}`
48231
48513
  };
48232
48514
  }
48515
+ async getProxyTarget(service = "code-server") {
48516
+ if (service !== "code-server") {
48517
+ throw new FeatureNotSupportedError(`Proxy service "${service}" is not supported by this provider`, "getProxyTarget", this.provider);
48518
+ }
48519
+ return {
48520
+ service,
48521
+ origin: await this.getDirectEndpointOrigin(OPEN_SANDBOX_EXECD_PORT),
48522
+ basePath: `/proxy/${OPEN_SANDBOX_CODE_SERVER_PORT}`,
48523
+ auth: "code-server"
48524
+ };
48525
+ }
48526
+ async getDirectEndpointOrigin(port) {
48527
+ if (!this.id) {
48528
+ throw new SandboxStateError("Sandbox not initialized. Call create() or connect() first.", "UnExist", "Running");
48529
+ }
48530
+ const headers = {
48531
+ ...this._connection.headers,
48532
+ Accept: "application/json"
48533
+ };
48534
+ const response = await this._connection.fetch(`${this._connection.getBaseUrl()}/sandboxes/${this.id}/endpoints/${port}?use_server_proxy=false`, { method: "GET", headers });
48535
+ if (!response.ok) {
48536
+ throw new ConnectionError(`OpenSandbox endpoint lookup failed: HTTP ${response.status}`, this.connectionConfig.baseUrl);
48537
+ }
48538
+ const data = await response.json();
48539
+ if (!data.endpoint) {
48540
+ throw new ConnectionError("OpenSandbox returned no endpoint", this.connectionConfig.baseUrl);
48541
+ }
48542
+ let hostPort = data.endpoint.replace(/\/proxy\/\d+\/?$/, "");
48543
+ if (this.connectionConfig.replaceDockerInternalWithLocalhost) {
48544
+ hostPort = hostPort.replace(/^host\.docker\.internal\b/, "localhost");
48545
+ }
48546
+ const url = new URL(/^https?:\/\//.test(hostPort) ? hostPort : `http://${hostPort}`);
48547
+ return url.origin;
48548
+ }
48233
48549
  async getInfo() {
48234
48550
  if (!this._sandbox) {
48235
48551
  return null;
@@ -48238,7 +48554,7 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48238
48554
  const info = await this.sandbox.getInfo();
48239
48555
  return {
48240
48556
  id: info.id,
48241
- image: typeof info.image === "string" ? this.parseImageSpec(info.image) : ("uri" in info.image) ? this.parseImageSpec(info.image.uri) : info.image,
48557
+ image: typeof info.image === "string" ? parseImageSpec(info.image) : ("uri" in info.image) ? parseImageSpec(info.image.uri) : info.image,
48242
48558
  entrypoint: info.entrypoint,
48243
48559
  metadata: info.metadata,
48244
48560
  status: this.mapStatus(info.status),
@@ -48293,21 +48609,30 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48293
48609
  return results;
48294
48610
  }
48295
48611
  async execute(command, options) {
48612
+ const maxBytes = options?.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
48613
+ const stdoutBuf = new BoundedOutputBuffer(maxBytes, `
48614
+ `);
48615
+ const stderrBuf = new BoundedOutputBuffer(maxBytes, `
48616
+ `);
48296
48617
  try {
48297
48618
  const execution = await this.sandbox.commands.run(command, {
48298
48619
  workingDirectory: this.normalizePath(options?.workingDirectory),
48299
48620
  background: options?.background
48621
+ }, {
48622
+ onStdout: (msg) => {
48623
+ stdoutBuf.append(msg.text);
48624
+ },
48625
+ onStderr: (msg) => {
48626
+ stderrBuf.append(msg.text);
48627
+ }
48300
48628
  });
48301
- const stdout = execution.logs.stdout.map((msg) => msg.text).join(`
48302
- `);
48303
- const stderr = execution.logs.stderr.map((msg) => msg.text).join(`
48304
- `);
48305
48629
  const exitCode = this.extractExitCode(execution);
48306
- const stdoutLength = execution.logs.stdout.reduce((sum, msg) => sum + msg.text.length, 0);
48307
- const stderrLength = execution.logs.stderr.reduce((sum, msg) => sum + msg.text.length, 0);
48308
- const MaxOutputSize = 1024 * 1024;
48309
- const truncated = stdoutLength >= MaxOutputSize || stderrLength >= MaxOutputSize;
48310
- return { stdout, stderr, exitCode, truncated };
48630
+ return {
48631
+ stdout: stdoutBuf.toString(),
48632
+ stderr: stderrBuf.toString(),
48633
+ exitCode,
48634
+ truncated: stdoutBuf.truncated || stderrBuf.truncated
48635
+ };
48311
48636
  } catch (error) {
48312
48637
  if (error instanceof SandboxStateError)
48313
48638
  throw error;
@@ -48315,10 +48640,26 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48315
48640
  }
48316
48641
  }
48317
48642
  async executeStream(command, handlers, options) {
48643
+ const wantsComplete = Boolean(handlers.onComplete);
48644
+ const maxBytes = options?.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES;
48645
+ const stdoutBuf = wantsComplete ? new BoundedOutputBuffer(maxBytes, `
48646
+ `) : undefined;
48647
+ const stderrBuf = wantsComplete ? new BoundedOutputBuffer(maxBytes, `
48648
+ `) : undefined;
48318
48649
  try {
48319
48650
  const sdkHandlers = {
48320
- ...handlers.onStderr ? { onStderr: handlers.onStderr } : {},
48321
- ...handlers.onStdout ? { onStdout: handlers.onStdout } : {},
48651
+ ...handlers.onStdout || wantsComplete ? {
48652
+ onStdout: async (msg) => {
48653
+ stdoutBuf?.append(msg.text);
48654
+ await handlers.onStdout?.(msg);
48655
+ }
48656
+ } : {},
48657
+ ...handlers.onStderr || wantsComplete ? {
48658
+ onStderr: async (msg) => {
48659
+ stderrBuf?.append(msg.text);
48660
+ await handlers.onStderr?.(msg);
48661
+ }
48662
+ } : {},
48322
48663
  ...handlers.onError ? {
48323
48664
  onError: async (err) => {
48324
48665
  const error = new Error(err.value || err.name || "Execution error");
@@ -48335,17 +48676,14 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48335
48676
  workingDirectory: this.normalizePath(options?.workingDirectory),
48336
48677
  background: options?.background
48337
48678
  }, sdkHandlers);
48338
- if (handlers.onComplete) {
48339
- const stdout = execution.logs.stdout.map((msg) => msg.text).join(`
48340
- `);
48341
- const stderr = execution.logs.stderr.map((msg) => msg.text).join(`
48342
- `);
48679
+ if (wantsComplete) {
48343
48680
  const exitCode = this.extractExitCode(execution);
48344
- const stdoutLength = execution.logs.stdout.reduce((sum, msg) => sum + msg.text.length, 0);
48345
- const stderrLength = execution.logs.stderr.reduce((sum, msg) => sum + msg.text.length, 0);
48346
- const MaxOutputSize = 1024 * 1024;
48347
- const truncated = stdoutLength >= MaxOutputSize || stderrLength >= MaxOutputSize;
48348
- await handlers.onComplete({ stdout, stderr, exitCode, truncated });
48681
+ await handlers.onComplete({
48682
+ stdout: stdoutBuf.toString(),
48683
+ stderr: stderrBuf.toString(),
48684
+ exitCode,
48685
+ truncated: stdoutBuf.truncated || stderrBuf.truncated
48686
+ });
48349
48687
  }
48350
48688
  } catch (error) {
48351
48689
  throw new CommandExecutionError(`Streaming command execution failed: ${command}`, command, error instanceof Error ? error : undefined);
@@ -48398,7 +48736,7 @@ class OpenSandboxAdapter extends BaseSandboxAdapter {
48398
48736
  }
48399
48737
 
48400
48738
  // src/adapters/E2BAdapter/index.ts
48401
- var import_code_interpreter = __toESM(require_dist3());
48739
+ var import_code_interpreter = __toESM(require_dist3(), 1);
48402
48740
  class E2BAdapter extends BaseSandboxAdapter {
48403
48741
  config;
48404
48742
  provider = "e2b";
@@ -48718,7 +49056,7 @@ function createSandbox(provider, config, createConfig) {
48718
49056
  case "opensandbox":
48719
49057
  return new OpenSandboxAdapter(config, createConfig);
48720
49058
  case "sealosdevbox":
48721
- return new SealosDevboxAdapter(config);
49059
+ return new SealosDevboxAdapter(config, createConfig);
48722
49060
  case "e2b":
48723
49061
  return new E2BAdapter(config);
48724
49062
  default: